QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgscamerapose.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscamerapose.cpp
3 --------------------------------------
4 Date : July 2018
5 Copyright : (C) 2018 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgscamerapose.h"
17
18#include "qgs3dutils.h"
19
20#include <QDomDocument>
21#include <Qt3DRender/QCamera>
22
23QDomElement QgsCameraPose::writeXml( QDomDocument &doc ) const
24{
25 QDomElement elemCamera = doc.createElement( QStringLiteral( "camera-pose" ) );
26 elemCamera.setAttribute( QStringLiteral( "x" ), mCenterPoint.x() );
27 elemCamera.setAttribute( QStringLiteral( "y" ), mCenterPoint.y() );
28 elemCamera.setAttribute( QStringLiteral( "z" ), mCenterPoint.z() );
29 elemCamera.setAttribute( QStringLiteral( "dist" ), mDistanceFromCenterPoint );
30 elemCamera.setAttribute( QStringLiteral( "pitch" ), mPitchAngle );
31 elemCamera.setAttribute( QStringLiteral( "heading" ), mHeadingAngle );
32 return elemCamera;
33}
34
35void QgsCameraPose::readXml( const QDomElement &elem )
36{
37 const double x = elem.attribute( QStringLiteral( "x" ) ).toDouble();
38 const double y = elem.attribute( QStringLiteral( "y" ) ).toDouble();
39 const double z = elem.attribute( QStringLiteral( "z" ) ).toDouble();
40 mCenterPoint = QgsVector3D( x, y, z );
41
42 mDistanceFromCenterPoint = elem.attribute( QStringLiteral( "dist" ) ).toFloat();
43 mPitchAngle = elem.attribute( QStringLiteral( "pitch" ) ).toFloat();
44 mHeadingAngle = elem.attribute( QStringLiteral( "heading" ) ).toFloat();
45}
46
48{
49 // something went horribly wrong. Prevent further errors
50 if ( std::isnan( point.x() ) || std::isnan( point.y() ) || std::isnan( point.z() ) )
51 qWarning() << "Not updating camera position: it cannot be NaN!";
52 else
53 mCenterPoint = point;
54}
55
57{
58 mDistanceFromCenterPoint = std::max( distance, 10.0f );
59}
60
62{
63 // prevent going over the head
64 mPitchAngle = std::clamp( pitch, 0.0f, 180.0f );
65}
66
67void QgsCameraPose::updateCamera( Qt3DRender::QCamera *camera )
68{
69 // first rotate by pitch angle around X axis, then by heading angle around Z axis
70 QQuaternion q = Qgs3DUtils::rotationFromPitchHeadingAngles( mPitchAngle, mHeadingAngle );
71 QVector3D cameraToCenter = q * QVector3D( 0, 0, -mDistanceFromCenterPoint );
72 camera->setUpVector( q * QVector3D( 0, 1, 0 ) );
73 camera->setPosition( mCenterPoint.toVector3D() - cameraToCenter );
74 camera->setViewCenter( mCenterPoint.toVector3D() );
75}
76
77void QgsCameraPose::updateCameraGlobe( Qt3DRender::QCamera *camera, double lat, double lon )
78{
79 // how the camera setup works:
80 // - we are using ECEF coordinates (https://en.wikipedia.org/wiki/Earth-centered,_Earth-fixed_coordinate_system)
81 // - point (0,0,0) is in the center of reference ellipsoid
82 // - X and Y axes define equator plane
83 // - X axis grows towards the prime meridian (zero longitude)
84 // - Y axis grows towards 90 degrees of longitude
85 // - Z axis grows towards the north pole
86
87 QVector3D viewCenter = mCenterPoint.toVector3D();
88
89 // rotate camera so that it is looking towards the tangent plane to ellipsoid at given
90 // lat/lon coordinates
91 QQuaternion qLatLon = QQuaternion::fromAxisAndAngle( QVector3D( 0, 0, 1 ), static_cast<float>( lon ) ) * QQuaternion::fromAxisAndAngle( QVector3D( 0, -1, 0 ), static_cast<float>( lat ) );
92
93 // rotate camera using the pitch and heading angles
94 QQuaternion qPitchHeading = QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), mHeadingAngle ) * QQuaternion::fromAxisAndAngle( QVector3D( 0, 1, 0 ), mPitchAngle );
95
96 // combine the two rotations (the order is important: pitch/heading is applied first)
97 QQuaternion q = qLatLon * qPitchHeading;
98
99 QVector3D cameraToCenter = ( q * QVector3D( -1, 0, 0 ) ) * mDistanceFromCenterPoint;
100 camera->setUpVector( q * QVector3D( 0, 0, 1 ) );
101 camera->setPosition( viewCenter - cameraToCenter );
102 camera->setViewCenter( viewCenter );
103}
static QQuaternion rotationFromPitchHeadingAngles(float pitchAngle, float headingAngle)
Returns rotation quaternion that performs rotation around X axis by pitchAngle, followed by rotation ...
void updateCameraGlobe(Qt3DRender::QCamera *camera, double lat, double lon)
Updates camera when using a globe scene.
void setPitchAngle(float pitch)
Sets pitch angle in degrees.
QDomElement writeXml(QDomDocument &doc) const
Writes configuration to a new DOM element and returns it.
void setCenterPoint(const QgsVector3D &point)
Sets center point (towards which point the camera is looking).
void readXml(const QDomElement &elem)
Reads configuration from a DOM element previously written using writeXml().
void setDistanceFromCenterPoint(float distance)
Sets distance of the camera from the center point.
void updateCamera(Qt3DRender::QCamera *camera)
Update Qt3D camera view matrix based on the pose.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
Definition qgsvector3d.h:30
double y() const
Returns Y coordinate.
Definition qgsvector3d.h:49
double z() const
Returns Z coordinate.
Definition qgsvector3d.h:51
double x() const
Returns X coordinate.
Definition qgsvector3d.h:47