24 #include <QDomDocument> 
   25 #include <Qt3DRender/QCamera> 
   26 #include <Qt3DRender/QObjectPicker> 
   27 #include <Qt3DRender/QPickEvent> 
   34   , mMouseDevice( new 
Qt3DInput::QMouseDevice() )
 
   35   , mKeyboardDevice( new 
Qt3DInput::QKeyboardDevice() )
 
   36   , mMouseHandler( new 
Qt3DInput::QMouseHandler )
 
   37   , mKeyboardHandler( new 
Qt3DInput::QKeyboardHandler )
 
   39   mMouseHandler->setSourceDevice( mMouseDevice );
 
   40   connect( mMouseHandler, &Qt3DInput::QMouseHandler::positionChanged,
 
   41            this, &QgsCameraController::onPositionChanged );
 
   42   connect( mMouseHandler, &Qt3DInput::QMouseHandler::wheel,
 
   43            this, &QgsCameraController::onWheel );
 
   44   connect( mMouseHandler, &Qt3DInput::QMouseHandler::pressed,
 
   45            this, &QgsCameraController::onMousePressed );
 
   46   connect( mMouseHandler, &Qt3DInput::QMouseHandler::released,
 
   47            this, &QgsCameraController::onMouseReleased );
 
   48   addComponent( mMouseHandler );
 
   50   mKeyboardHandler->setSourceDevice( mKeyboardDevice );
 
   51   connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::pressed,
 
   52            this, &QgsCameraController::onKeyPressed );
 
   53   connect( mKeyboardHandler, &Qt3DInput::QKeyboardHandler::released,
 
   54            this, &QgsCameraController::onKeyReleased );
 
   55   addComponent( mKeyboardHandler );
 
   58   connect( 
this, &Qt3DCore::QEntity::enabledChanged,
 
   59            mMouseHandler, &Qt3DInput::QMouseHandler::setEnabled );
 
   60   connect( 
this, &Qt3DCore::QEntity::enabledChanged,
 
   61            mKeyboardHandler, &Qt3DInput::QMouseHandler::setEnabled );
 
   63   mFpsNavTimer = 
new QTimer( 
this );
 
   64   mFpsNavTimer->setInterval( 10 );
 
   65   connect( mFpsNavTimer, &QTimer::timeout, 
this, &QgsCameraController::applyFlyModeKeyMovements );
 
   66   mFpsNavTimer->start();
 
   71   if ( navigationMode == mCameraNavigationMode )
 
   74   mCameraNavigationMode = navigationMode;
 
   75   mIgnoreNextMouseMove = 
true;
 
   80   if ( movementSpeed == mCameraMovementSpeed )
 
   83   mCameraMovementSpeed = movementSpeed;
 
   89   mVerticalAxisInversion = inversion;
 
   97     connect( te->terrainPicker(), &Qt3DRender::QObjectPicker::pressed, 
this, &QgsCameraController::onPickerMousePressed );
 
  123 static QVector3D unproject( QVector3D v, 
const QMatrix4x4 &modelView, 
const QMatrix4x4 &projection, QRect viewport )
 
  130   const QMatrix4x4 inverse = QMatrix4x4( projection * modelView ).inverted();
 
  132   QVector4D tmp( v, 1.0f );
 
  133   tmp.setX( ( tmp.x() - 
float( viewport.x() ) ) / 
float( viewport.width() ) );
 
  134   tmp.setY( ( tmp.y() - 
float( viewport.y() ) ) / 
float( viewport.height() ) );
 
  135   tmp = tmp * 2.0f - QVector4D( 1.0f, 1.0f, 1.0f, 1.0f );
 
  137   QVector4D obj = inverse * tmp;
 
  141   return obj.toVector3D();
 
  147   const float d_x = x1 - x0;
 
  148   const float d_y = y1 - y0;
 
  149   const float k = ( y - y0 ) / d_y; 
 
  156   const QVector3D l0 = unproject( QVector3D( pt.x(), viewport.height() - pt.y(), 0 ), camera->viewMatrix(), camera->projectionMatrix(), viewport );
 
  157   const QVector3D l1 = unproject( QVector3D( pt.x(), viewport.height() - pt.y(), 1 ), camera->viewMatrix(), camera->projectionMatrix(), viewport );
 
  159   const QVector3D p0( 0, y, 0 ); 
 
  160   const QVector3D n( 0, 1, 0 ); 
 
  161   const QVector3D l = l1 - l0; 
 
  162   const float d = QVector3D::dotProduct( p0 - l0, n ) / QVector3D::dotProduct( l, n );
 
  163   const QVector3D p = d * l + l0;
 
  165   return QPointF( p.x(), p.z() );
 
  169 void QgsCameraController::rotateCamera( 
float diffPitch, 
float diffYaw )
 
  174   if ( 
pitch + diffPitch > 180 )
 
  175     diffPitch = 180 - 
pitch;  
 
  176   if ( 
pitch + diffPitch < 0 )
 
  177     diffPitch = 0 - 
pitch;   
 
  184   const QQuaternion q = QQuaternion::fromEulerAngles( 
pitch + diffPitch, 
yaw + diffYaw, 0 ) *
 
  185                         QQuaternion::fromEulerAngles( 
pitch, 
yaw, 0 ).conjugated();
 
  188   const QVector3D position = mCamera->position();
 
  189   QVector3D viewCenter = mCamera->viewCenter();
 
  190   const QVector3D viewVector = viewCenter - position;
 
  191   const QVector3D cameraToCenter = q * viewVector;
 
  192   viewCenter = position + cameraToCenter;
 
  213   if ( mTerrainEntity )
 
  221   mCamera->setNearPlane( 
distance / 2 );
 
  222   mCamera->setFarPlane( 
distance * 2 );
 
  244   if ( camPose == mCameraPose )
 
  247   mCameraPose = camPose;
 
  257   QDomElement elemCamera = doc.createElement( QStringLiteral( 
"camera" ) );
 
  258   elemCamera.setAttribute( QStringLiteral( 
"x" ), mCameraPose.
centerPoint().
x() );
 
  259   elemCamera.setAttribute( QStringLiteral( 
"y" ), mCameraPose.
centerPoint().
z() );
 
  260   elemCamera.setAttribute( QStringLiteral( 
"elev" ), mCameraPose.
centerPoint().
y() );
 
  262   elemCamera.setAttribute( QStringLiteral( 
"pitch" ), mCameraPose.
pitchAngle() );
 
  263   elemCamera.setAttribute( QStringLiteral( 
"yaw" ), mCameraPose.
headingAngle() );
 
  269   const float x = elem.attribute( QStringLiteral( 
"x" ) ).toFloat();
 
  270   const float y = elem.attribute( QStringLiteral( 
"y" ) ).toFloat();
 
  271   const float elev = elem.attribute( QStringLiteral( 
"elev" ) ).toFloat();
 
  272   const float dist = elem.attribute( QStringLiteral( 
"dist" ) ).toFloat();
 
  273   const float pitch = elem.attribute( QStringLiteral( 
"pitch" ) ).toFloat();
 
  274   const float yaw = elem.attribute( QStringLiteral( 
"yaw" ) ).toFloat();
 
  278 void QgsCameraController::updateCameraFromPose( 
bool centerPointChanged )
 
  283     qWarning() << 
"camera position got NaN!";
 
  297   if ( mCamera && mTerrainEntity && centerPointChanged )
 
  301     QVector3D intersectionPoint;
 
  302     const QgsRayCastingUtils::Ray3D ray = QgsRayCastingUtils::rayForCameraCenter( mCamera );
 
  303     if ( mTerrainEntity->rayIntersection( ray, intersectionPoint ) )
 
  305       const float dist = ( intersectionPoint - mCamera->position() ).length();
 
  313       centerPoint.
set( centerPoint.
x(), mTerrainEntity->terrainElevationOffset(), centerPoint.
z() );
 
  319   if ( mCamera && !mTerrainEntity && centerPointChanged )
 
  322     centerPoint.
set( centerPoint.
x(), 0, centerPoint.
z() );
 
  330 void QgsCameraController::moveCameraPositionBy( 
const QVector3D &posDiff )
 
  348 void QgsCameraController::onPositionChanged( Qt3DInput::QMouseEvent *mouse )
 
  350   switch ( mCameraNavigationMode )
 
  353       onPositionChangedTerrainNavigation( mouse );
 
  357       onPositionChangedFlyNavigation( mouse );
 
  362 void QgsCameraController::onPositionChangedTerrainNavigation( Qt3DInput::QMouseEvent *mouse )
 
  364   if ( mIgnoreNextMouseMove )
 
  366     mIgnoreNextMouseMove = 
false;
 
  367     mMousePos = QPoint( mouse->x(), mouse->y() );
 
  371   const int dx = mouse->x() - mMousePos.x();
 
  372   const int dy = mouse->y() - mMousePos.y();
 
  374   const bool hasShift = ( mouse->modifiers() & Qt::ShiftModifier );
 
  375   const bool hasCtrl = ( mouse->modifiers() & Qt::ControlModifier );
 
  376   const bool hasLeftButton = ( mouse->buttons() & Qt::LeftButton );
 
  377   const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
 
  378   const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
 
  380   if ( ( hasLeftButton && hasShift && !hasCtrl ) || ( hasMiddleButton && !hasShift && !hasCtrl ) )
 
  389     updateCameraFromPose();
 
  391   else if ( hasLeftButton && hasCtrl && !hasShift )
 
  394     const float diffPitch = 0.2f * dy;
 
  395     const float diffYaw = - 0.2f * dx;
 
  396     rotateCamera( diffPitch, diffYaw );
 
  397     updateCameraFromPose( 
true );
 
  399   else if ( hasLeftButton && !hasShift && !hasCtrl )
 
  405     const float z = mLastPressedHeight;
 
  410     center.
set( center.
x() - ( p2.x() - p1.x() ), center.
y(), center.
z() - ( p2.y() - p1.y() ) );
 
  412     updateCameraFromPose( 
true );
 
  414   else if ( hasRightButton && !hasShift && !hasCtrl )
 
  419   mMousePos = QPoint( mouse->x(), mouse->y() );
 
  428   dist -= dist * factor * 0.01f;
 
  430   updateCameraFromPose();
 
  433 void QgsCameraController::onWheel( Qt3DInput::QWheelEvent *wheel )
 
  435   switch ( mCameraNavigationMode )
 
  439       const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) ? 0.1f : 1.0f ) / 1000.f;
 
  440       setCameraMovementSpeed( mCameraMovementSpeed + mCameraMovementSpeed * scaling * wheel->angleDelta().y() );
 
  446       const float scaling = ( ( wheel->modifiers() & Qt::ControlModifier ) ? 0.1f : 1.0f ) / 1000.f;
 
  448       dist -= dist * scaling * wheel->angleDelta().y();
 
  450       updateCameraFromPose();
 
  456 void QgsCameraController::onMousePressed( Qt3DInput::QMouseEvent *mouse )
 
  459   mKeyboardHandler->setFocus( 
true );
 
  460   if ( mouse->button() == Qt3DInput::QMouseEvent::LeftButton || mouse->button() == Qt3DInput::QMouseEvent::RightButton || mouse->button() == Qt3DInput::QMouseEvent::MiddleButton )
 
  462     mMousePos = QPoint( mouse->x(), mouse->y() );
 
  463     mPressedButton = mouse->button();
 
  464     mMousePressed = 
true;
 
  465     if ( mCaptureFpsMouseMovements )
 
  466       mIgnoreNextMouseMove = 
true;
 
  470 void QgsCameraController::onMouseReleased( Qt3DInput::QMouseEvent *mouse )
 
  473   mPressedButton = Qt3DInput::QMouseEvent::NoButton;
 
  474   mMousePressed = 
false;
 
  477 void QgsCameraController::onKeyPressed( Qt3DInput::QKeyEvent *event )
 
  479   if ( event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_QuoteLeft )
 
  482     switch ( mCameraNavigationMode )
 
  484       case NavigationMode::WalkNavigation:
 
  487       case NavigationMode::TerrainBasedNavigation:
 
  495   switch ( mCameraNavigationMode )
 
  499       onKeyPressedFlyNavigation( event );
 
  505       onKeyPressedTerrainNavigation( event );
 
  511 void QgsCameraController::onKeyPressedTerrainNavigation( Qt3DInput::QKeyEvent *event )
 
  513   const bool hasShift = ( 
event->modifiers() & Qt::ShiftModifier );
 
  514   const bool hasCtrl = ( 
event->modifiers() & Qt::ControlModifier );
 
  516   int tx = 0, ty = 0, tElev = 0;
 
  517   switch ( event->key() )
 
  533     case Qt::Key_PageDown:
 
  543     if ( !hasShift && !hasCtrl )
 
  547     else if ( hasShift && !hasCtrl )
 
  553     else if ( hasCtrl && !hasShift )
 
  556       const float diffPitch = ty;   
 
  557       const float diffYaw = -tx;    
 
  558       rotateCamera( diffPitch, diffYaw );
 
  559       updateCameraFromPose( 
true );
 
  566     center.
set( center.
x(), center.
y() + tElev * 10, center.
z() );
 
  568     updateCameraFromPose( 
true );
 
  572 void QgsCameraController::onKeyPressedFlyNavigation( Qt3DInput::QKeyEvent *event )
 
  574   switch ( event->key() )
 
  576     case Qt::Key_QuoteLeft:
 
  579       mCaptureFpsMouseMovements = !mCaptureFpsMouseMovements;
 
  580       mIgnoreNextMouseMove = 
true;
 
  581       if ( mCaptureFpsMouseMovements )
 
  583         qApp->setOverrideCursor( QCursor( Qt::BlankCursor ) );
 
  587         qApp->restoreOverrideCursor();
 
  595       if ( mCaptureFpsMouseMovements )
 
  597         mCaptureFpsMouseMovements = 
false;
 
  598         mIgnoreNextMouseMove = 
true;
 
  599         qApp->restoreOverrideCursor();
 
  609   if ( event->isAutoRepeat() )
 
  612   mDepressedKeys.insert( event->key() );
 
  615 void QgsCameraController::applyFlyModeKeyMovements()
 
  617   const QVector3D cameraUp = mCamera->upVector().normalized();
 
  619   const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
 
  621   QVector3D cameraPosDiff( 0.0f, 0.0f, 0.0f );
 
  624   const bool shiftPressed = mDepressedKeys.contains( Qt::Key_Shift );
 
  625   const bool ctrlPressed = mDepressedKeys.contains( Qt::Key_Control );
 
  627   const double movementSpeed = mCameraMovementSpeed * ( shiftPressed ? 2 : 1 ) * ( ctrlPressed ? 0.1 : 1 );
 
  629   bool changed = 
false;
 
  630   if ( mDepressedKeys.contains( Qt::Key_Left ) || mDepressedKeys.contains( Qt::Key_A ) )
 
  633     cameraPosDiff += movementSpeed * cameraLeft;
 
  636   if ( mDepressedKeys.contains( Qt::Key_Right ) || mDepressedKeys.contains( Qt::Key_D ) )
 
  639     cameraPosDiff += - movementSpeed * cameraLeft;
 
  642   if ( mDepressedKeys.contains( Qt::Key_Up ) || mDepressedKeys.contains( Qt::Key_W ) )
 
  645     cameraPosDiff += movementSpeed * cameraFront;
 
  648   if ( mDepressedKeys.contains( Qt::Key_Down ) || mDepressedKeys.contains( Qt::Key_S ) )
 
  651     cameraPosDiff += - movementSpeed * cameraFront;
 
  656   static constexpr 
double ELEVATION_MOVEMENT_SCALE = 0.5;
 
  657   if ( mDepressedKeys.contains( Qt::Key_PageUp ) || mDepressedKeys.contains( Qt::Key_E ) )
 
  660     cameraPosDiff += ELEVATION_MOVEMENT_SCALE * movementSpeed * QVector3D( 0.0f, 1.0f, 0.0f );
 
  663   if ( mDepressedKeys.contains( Qt::Key_PageDown ) || mDepressedKeys.contains( Qt::Key_Q ) )
 
  666     cameraPosDiff += ELEVATION_MOVEMENT_SCALE * - movementSpeed * QVector3D( 0.0f, 1.0f, 0.0f );
 
  670     moveCameraPositionBy( cameraPosDiff );
 
  673 void QgsCameraController::onPositionChangedFlyNavigation( Qt3DInput::QMouseEvent *mouse )
 
  675   const bool hasMiddleButton = ( mouse->buttons() & Qt::MiddleButton );
 
  676   const bool hasRightButton = ( mouse->buttons() & Qt::RightButton );
 
  678   const double dx = mCaptureFpsMouseMovements ? QCursor::pos().x() - mMousePos.x() : mouse->x() - mMousePos.x();
 
  679   const double dy = mCaptureFpsMouseMovements ? QCursor::pos().y() - mMousePos.y() : mouse->y() - mMousePos.y();
 
  680   mMousePos = mCaptureFpsMouseMovements ? QCursor::pos() : QPoint( mouse->x(), mouse->y() );
 
  682   if ( mIgnoreNextMouseMove )
 
  684     mIgnoreNextMouseMove = 
false;
 
  688   if ( hasMiddleButton )
 
  691     const QVector3D cameraUp = mCamera->upVector().normalized();
 
  693     const QVector3D cameraLeft = QVector3D::crossProduct( cameraUp, cameraFront );
 
  694     const QVector3D cameraPosDiff = -dx * cameraLeft - dy * cameraUp;
 
  695     moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 10.0 );
 
  697   else if ( hasRightButton )
 
  701     const QVector3D cameraPosDiff = dy * cameraFront;
 
  702     moveCameraPositionBy( mCameraMovementSpeed * cameraPosDiff / 5.0 );
 
  706     if ( mCaptureFpsMouseMovements )
 
  708       float diffPitch = -0.2f * dy;
 
  709       switch ( mVerticalAxisInversion )
 
  720       const float diffYaw = - 0.2f * dx;
 
  721       rotateCamera( diffPitch, diffYaw );
 
  722       updateCameraFromPose( 
false );
 
  724     else if ( mouse->buttons() & Qt::LeftButton )
 
  726       float diffPitch = -0.2f * dy;
 
  727       switch ( mVerticalAxisInversion )
 
  737       const float diffYaw = - 0.2f * dx;
 
  738       rotateCamera( diffPitch, diffYaw );
 
  739       updateCameraFromPose( 
false );
 
  743   if ( mCaptureFpsMouseMovements )
 
  745     mIgnoreNextMouseMove = 
true;
 
  748     emit 
setCursorPosition( QPoint( mViewport.width() / 2, mViewport.height() / 2 ) );
 
  752 void QgsCameraController::onKeyReleased( Qt3DInput::QKeyEvent *event )
 
  754   if ( event->isAutoRepeat() )
 
  757   mDepressedKeys.remove( event->key() );
 
  760 void QgsCameraController::onPickerMousePressed( Qt3DRender::QPickEvent *pick )
 
  762   mLastPressedHeight = pick->worldIntersection().y();
 
  772   updateCameraFromPose();
 
  781   updateCameraFromPose();
 
  782   qInfo() << 
"Delta yaw: " << deltaYaw;
 
  783   qInfo() << 
"Yaw: " << 
yaw;
 
  789   updateCameraFromPose();
 
  796   const float x = tx * dist * 0.02f;
 
  797   const float y = -ty * dist * 0.02f;
 
  800   const float t = sqrt( x * x + y * y );
 
  801   const float a = atan2( y, x ) - 
yaw * M_PI / 180;
 
  802   const float dx = cos( a ) * t;
 
  803   const float dy = sin( a ) * t;
 
  806   center.
set( center.
x() + dx, center.
y(), center.
z() + dy );
 
  808   updateCameraFromPose( 
true );
 
  813   if ( event->key() == Qt::Key_QuoteLeft )
 
  816   switch ( mCameraNavigationMode )
 
  820       switch ( event->key() )
 
  832         case Qt::Key_PageDown:
 
  837           if ( mCaptureFpsMouseMovements )
 
  849       switch ( event->key() )
 
  854         case Qt::Key_PageDown:
 
void setViewport(QRect viewport)
Sets viewport rectangle. Called internally from 3D canvas. Allows conversion of mouse coordinates.
 
void readXml(const QDomElement &elem)
Reads camera configuration from the given DOM element.
 
float pitch() const
Returns pitch angle in degrees (0 = looking from the top, 90 = looking from the side).
 
float yaw() const
Returns yaw angle in degrees.
 
void setCameraNavigationMode(QgsCameraController::NavigationMode navigationMode)
Sets the navigation mode used by the camera controller.
 
void tiltUpAroundViewCenter(float deltaPitch)
Tilt up the view by deltaPitch around the view center (camera moves)
 
bool willHandleKeyEvent(QKeyEvent *event)
Returns true if the camera controller will handle the specified key event, preventing it from being i...
 
void navigationModeHotKeyPressed(QgsCameraController::NavigationMode mode)
Emitted when the navigation mode is changed using the hotkey ctrl + ~.
 
Qt3DRender::QCamera * camera
 
void setVerticalAxisInversion(QgsCameraController::VerticalAxisInversion inversion)
Sets the vertical axis inversion behavior.
 
float distance() const
Returns distance of the camera from the point it is looking at.
 
void setCamera(Qt3DRender::QCamera *camera)
Assigns camera that should be controlled by this class. Called internally from 3D scene.
 
VerticalAxisInversion
Vertical axis inversion options.
 
@ WhenDragging
Invert vertical axis movements when dragging in first person modes.
 
@ Always
Always invert vertical axis movements.
 
@ Never
Never invert vertical axis movements.
 
void cameraChanged()
Emitted when camera has been updated.
 
void cameraMovementSpeedChanged(double speed)
Emitted whenever the camera movement speed is changed by the controller.
 
void frameTriggered(float dt)
Called internally from 3D scene when a new frame is generated. Updates camera according to keyboard/m...
 
void resetView(float distance)
Move camera back to the initial position (looking down towards origin of world's coordinates)
 
void setLookingAtPoint(const QgsVector3D &point, float distance, float pitch, float yaw)
Sets the complete camera configuration: the point towards it is looking (in 3D world coordinates),...
 
QgsVector3D lookingAtPoint() const
Returns the point in the world coordinates towards which the camera is looking.
 
QDomElement writeXml(QDomDocument &doc) const
Writes camera configuration to the given DOM element.
 
void setViewFromTop(float worldX, float worldY, float distance, float yaw=0)
Sets camera to look down towards given point in world coordinate, in given distance from plane with z...
 
NavigationMode
The navigation mode used by the camera.
 
@ WalkNavigation
Uses WASD keys or arrows to navigate in walking (first person) manner.
 
@ TerrainBasedNavigation
The default navigation based on the terrain.
 
void zoom(float factor)
Zoom the map by factor.
 
void setTerrainEntity(QgsTerrainEntity *te)
Connects to object picker attached to terrain entity.
 
void rotateAroundViewCenter(float deltaYaw)
Rotate clockwise the view by deltaYaw around the view center (camera moves)
 
QgsCameraController(Qt3DCore::QNode *parent=nullptr)
Constructs the camera controller with optional parent node that will take ownership.
 
void setCameraHeadingAngle(float angle)
Set camera heading to angle (used for rotating the view)
 
void setCameraMovementSpeed(double movementSpeed)
Sets the camera movement speed.
 
void setCameraPose(const QgsCameraPose &camPose)
Sets camera pose.
 
void viewportChanged()
Emitted when viewport rectangle has been updated.
 
void setCursorPosition(QPoint point)
Emitted when the mouse cursor position should be moved to the specified point on the map viewport.
 
void moveView(float tx, float ty)
Move the map by tx and ty.
 
float headingAngle() const
Returns heading (yaw) angle in degrees.
 
QgsVector3D centerPoint() const
Returns center point (towards which point the camera is looking)
 
float pitchAngle() const
Returns pitch angle in degrees.
 
float distanceFromCenterPoint() const
Returns distance of the camera from the center point.
 
void setPitchAngle(float pitch)
Sets pitch angle in degrees.
 
void setCenterPoint(const QgsVector3D &point)
Sets center point (towards which point the camera is looking)
 
void setHeadingAngle(float heading)
Sets heading (yaw) angle in degrees.
 
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.
 
double y() const
Returns Y coordinate.
 
double z() const
Returns Z coordinate.
 
double x() const
Returns X coordinate.
 
void set(double x, double y, double z)
Sets vector coordinates.
 
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
QPointF screen_point_to_point_on_plane(QPointF pt, QRect viewport, Qt3DRender::QCamera *camera, float y)
 
float find_x_on_line(float x0, float y0, float x1, float y1, float y)