18#include <Qt3DCore/QTransform>
19#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
20#include <Qt3DRender/QAttribute>
21#include <Qt3DRender/QGeometry>
26#include <Qt3DCore/QAttribute>
27#include <Qt3DCore/QGeometry>
32#include <Qt3DExtras/QCylinderMesh>
33#include <Qt3DExtras/QPhongMaterial>
34#include <Qt3DExtras/QConeMesh>
35#include <Qt3DRender/qcameralens.h>
36#include <Qt3DRender/QCameraSelector>
37#include <Qt3DRender/QClearBuffers>
38#include <Qt3DRender/QLayer>
39#include <Qt3DRender/QLayerFilter>
40#include <Qt3DRender/QPointLight>
41#include <Qt3DRender/QSortPolicy>
45#include <QFontDatabase>
47#include <QApplication>
48#include <QActionGroup>
59 Qt3DCore::QEntity *parent3DScene,
63 : QObject( parentWindow )
65 , mParentWindow( parentWindow )
66 , mMapScene( mapScene )
67 , mCameraController( cameraCtrl )
70 mAxisViewport = constructAxisViewport( parent3DScene );
71 mAxisViewport->setParent( mParentWindow->activeFrameGraph() );
73 mTwoDLabelViewport = constructLabelViewport( parent3DScene, QRectF( 0.0f, 0.0f, 1.0f, 1.0f ) );
74 mTwoDLabelViewport->setParent( mParentWindow->activeFrameGraph() );
77 connect( mParentWindow, &Qt3DExtras::Qt3DWindow::widthChanged,
this, &Qgs3DAxis::onAxisViewportSizeUpdate );
78 connect( mParentWindow, &Qt3DExtras::Qt3DWindow::heightChanged,
this, &Qgs3DAxis::onAxisViewportSizeUpdate );
81 onAxisViewportSizeUpdate();
83 init3DObjectPicking();
85 createKeyboardShortCut();
94void Qgs3DAxis::init3DObjectPicking( )
100 mScreenRayCaster =
new Qt3DRender::QScreenRayCaster( mAxisSceneEntity );
101 mScreenRayCaster->addLayer( mAxisSceneLayer );
102 mScreenRayCaster->setFilterMode( Qt3DRender::QScreenRayCaster::AcceptAllMatchingLayers );
103 mScreenRayCaster->setRunMode( Qt3DRender::QAbstractRayCaster::SingleShot );
105 mAxisSceneEntity->addComponent( mScreenRayCaster );
107 QObject::connect( mScreenRayCaster, &Qt3DRender::QScreenRayCaster::hitsChanged,
this, &Qgs3DAxis::onTouchedByRay );
110 mParentWindow->installEventFilter(
this );
113bool Qgs3DAxis::eventFilter( QObject *watched, QEvent *event )
115 if ( watched != mParentWindow )
118 if ( event->type() == QEvent::MouseButtonPress )
122 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>( event );
123 mLastClickedPos = mouseEvent->pos();
127 else if ( event->type() == QEvent::MouseButtonRelease ||
event->type() == QEvent::MouseMove )
129 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>( event );
132 if ( event->type() == QEvent::MouseMove &&
133 ( ( mHasClicked && ( mouseEvent->pos() - mLastClickedPos ).manhattanLength() < QApplication::startDragDistance() ) || mIsDragging ) )
139 else if ( mIsDragging && event->type() == QEvent::MouseButtonRelease )
146 else if ( ! mIsDragging )
149 QPointF normalizedPos(
static_cast<float>( mouseEvent->pos().x() ) / mParentWindow->width(),
150 (
float )mouseEvent->pos().y() / mParentWindow->height() );
154 std::ostringstream os;
155 os <<
"QGS3DAxis: normalized pos: " << normalizedPos <<
" / viewport: " << mAxisViewport->normalizedRect();
159 if ( mAxisViewport->normalizedRect().contains( normalizedPos ) )
161 mLastClickedButton = mouseEvent->button();
162 mLastClickedPos = mouseEvent->pos();
165 mScreenRayCaster->trigger( mLastClickedPos );
169 else if ( mPreviousCursor != Qt::ArrowCursor && mParentWindow->cursor() == Qt::ArrowCursor )
171 mParentWindow->setCursor( mPreviousCursor );
172 mPreviousCursor = Qt::ArrowCursor;
183void Qgs3DAxis::onTouchedByRay(
const Qt3DRender::QAbstractRayCaster::Hits &hits )
190 std::ostringstream os;
191 os <<
"Qgs3DAxis::onTouchedByRay " << hits.length() <<
" hits at pos " << mLastClickedPos <<
" with QButton: " << mLastClickedButton;
192 for (
int i = 0; i < hits.length(); ++i )
195 os <<
"\tHit Type: " << hits.at( i ).type() <<
"\n";
196 os <<
"\tHit triangle id: " << hits.at( i ).primitiveIndex() <<
"\n";
197 os <<
"\tHit distance: " << hits.at( i ).distance() <<
"\n";
198 os <<
"\tHit entity name: " << hits.at( i ).entity()->objectName().toStdString();
203 for (
int i = 0; i < hits.length() && mHitsFound == -1; ++i )
205 if ( hits.at( i ).distance() < 500.0f && ( hits.at( i ).entity() == mCubeRoot || hits.at( i ).entity() == mAxisRoot || hits.at( i ).entity()->parent() == mCubeRoot || hits.at( i ).entity()->parent() == mAxisRoot ) )
212 if ( mLastClickedButton == Qt::NoButton )
214 if ( mHitsFound != -1 )
216 if ( mParentWindow->cursor() != Qt::ArrowCursor )
218 mPreviousCursor = mParentWindow->cursor();
219 mParentWindow->setCursor( Qt::ArrowCursor );
224 else if ( mLastClickedButton == Qt::MouseButton::RightButton && mHitsFound != -1 )
226 displayMenuAt( mLastClickedPos );
228 else if ( mLastClickedButton == Qt::MouseButton::LeftButton )
232 if ( mHitsFound != -1 )
234 if ( hits.at( mHitsFound ).entity() == mCubeRoot || hits.at( mHitsFound ).entity()->parent() == mCubeRoot )
236 switch ( hits.at( mHitsFound ).primitiveIndex() / 2 )
240 onCameraViewChangeEast();
245 onCameraViewChangeWest();
250 onCameraViewChangeNorth();
255 onCameraViewChangeSouth();
260 onCameraViewChangeTop();
265 onCameraViewChangeBottom();
276Qt3DRender::QViewport *Qgs3DAxis::constructAxisViewport( Qt3DCore::QEntity *parent3DScene )
278 Qt3DRender::QViewport *axisViewport =
new Qt3DRender::QViewport;
282 mAxisSceneEntity =
new Qt3DCore::QEntity;
283 mAxisSceneEntity->setParent( parent3DScene );
284 mAxisSceneEntity->setObjectName(
"3DAxis_SceneEntity" );
286 mAxisSceneLayer =
new Qt3DRender::QLayer;
287 mAxisSceneLayer->setObjectName(
"3DAxis_SceneLayer" );
288 mAxisSceneLayer->setParent( mAxisSceneEntity );
289 mAxisSceneLayer->setRecursive(
true );
291 mAxisCamera =
new Qt3DRender::QCamera;
292 mAxisCamera->setParent( mAxisSceneEntity );
293 mAxisCamera->setProjectionType( mCameraController->
camera()->projectionType() );
294 mAxisCamera->lens()->setFieldOfView( mCameraController->
camera()->lens()->fieldOfView() * 0.5f );
296 mAxisCamera->setUpVector( QVector3D( 0.0f, 0.0f, 1.0f ) );
297 mAxisCamera->setViewCenter( QVector3D( 0.0f, 0.0f, 0.0f ) );
300 Qt3DRender::QLayer *axisLayer =
new Qt3DRender::QLayer;
301 axisLayer->setRecursive(
true );
302 mAxisSceneEntity->addComponent( axisLayer );
304 Qt3DRender::QLayerFilter *axisLayerFilter =
new Qt3DRender::QLayerFilter( axisViewport );
305 axisLayerFilter->addLayer( axisLayer );
307 Qt3DRender::QCameraSelector *axisCameraSelector =
new Qt3DRender::QCameraSelector;
308 axisCameraSelector->setParent( axisLayerFilter );
309 axisCameraSelector->setCamera( mAxisCamera );
313 Qt3DRender::QSortPolicy *sortPolicy =
new Qt3DRender::QSortPolicy( axisCameraSelector );
314 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes = QVector<Qt3DRender::QSortPolicy::SortType>();
315 sortTypes << Qt3DRender::QSortPolicy::BackToFront;
316 sortPolicy->setSortTypes( sortTypes );
318 Qt3DRender::QClearBuffers *clearBuffers =
new Qt3DRender::QClearBuffers( sortPolicy );
319 clearBuffers->setBuffers( Qt3DRender::QClearBuffers::DepthBuffer );
325Qt3DRender::QViewport *Qgs3DAxis::constructLabelViewport( Qt3DCore::QEntity *parent3DScene,
const QRectF &parentViewportSize )
327 Qt3DRender::QViewport *twoDViewport =
new Qt3DRender::QViewport;
329 twoDViewport->setNormalizedRect( parentViewportSize );
331 mTwoDLabelSceneEntity =
new Qt3DCore::QEntity;
332 mTwoDLabelSceneEntity->setParent( parent3DScene );
333 mTwoDLabelSceneEntity->setEnabled(
true );
335 mTwoDLabelCamera =
new Qt3DRender::QCamera;
336 mTwoDLabelCamera->setParent( mTwoDLabelSceneEntity );
337 mTwoDLabelCamera->setProjectionType( Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection );
338 mTwoDLabelCamera->lens()->setOrthographicProjection(
339 -mParentWindow->width() / 2.0f, mParentWindow->width() / 2.0f,
340 -mParentWindow->height() / 2.0f, mParentWindow->height() / 2.0f,
343 mTwoDLabelCamera->setUpVector( QVector3D( 0.0f, 0.0f, 1.0f ) );
344 mTwoDLabelCamera->setViewCenter( QVector3D( 0.0f, 0.0f, 0.0f ) );
346 mTwoDLabelCamera->setPosition( QVector3D( 0.0f, 0.0f, 100.0f ) );
348 Qt3DRender::QLayer *twoDLayer =
new Qt3DRender::QLayer;
349 twoDLayer->setRecursive(
true );
350 mTwoDLabelSceneEntity->addComponent( twoDLayer );
352 Qt3DRender::QLayerFilter *twoDLayerFilter =
new Qt3DRender::QLayerFilter( twoDViewport );
353 twoDLayerFilter->addLayer( twoDLayer );
355 Qt3DRender::QCameraSelector *twoDCameraSelector =
new Qt3DRender::QCameraSelector;
356 twoDCameraSelector->setParent( twoDLayerFilter );
357 twoDCameraSelector->setCamera( mTwoDLabelCamera );
361 Qt3DRender::QSortPolicy *sortPolicy =
new Qt3DRender::QSortPolicy( twoDCameraSelector );
362 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes = QVector<Qt3DRender::QSortPolicy::SortType>();
363 sortTypes << Qt3DRender::QSortPolicy::BackToFront;
364 sortPolicy->setSortTypes( sortTypes );
366 Qt3DRender::QClearBuffers *clearBuffers =
new Qt3DRender::QClearBuffers( sortPolicy );
367 clearBuffers->setBuffers( Qt3DRender::QClearBuffers::DepthBuffer );
374 Qt3DRender::QCamera *sourceCamera, Qt3DRender::QViewport *sourceViewport,
375 Qt3DRender::QCamera *destCamera, Qt3DRender::QViewport *destViewport,
376 const QSize &destSize )
378 QVector3D destPos = sourcePos.project( sourceCamera->viewMatrix(),
379 destCamera->projectionMatrix(),
381 destViewport->normalizedRect().width() * destSize.width(),
382 destViewport->normalizedRect().height() * destSize.height() ) );
383 QPointF axisCenter = sourceViewport->normalizedRect().center();
384 QPointF labelCenter = destViewport->normalizedRect().center();
385 QVector3D viewTranslation = QVector3D( ( axisCenter - labelCenter ).x() * destSize.width(),
386 ( axisCenter - labelCenter ).y() * destSize.height(),
388 destPos -= QVector3D( labelCenter.x() * destSize.width(),
389 labelCenter.y() * destSize.height(),
391 destPos.setX( destPos.x() + viewTranslation.x() );
392 destPos.setY( destPos.y() - viewTranslation.y() );
393 destPos.setZ( 0.0f );
397 std::ostringstream os;
398 os <<
"Qgs3DAxis::from3DTo2DLabelPosition: sourcePos: " << sourcePos.toPoint()
399 <<
" with translation: " << viewTranslation.toPoint()
400 <<
" corrected to pos: " << destPos.toPoint();
406void Qgs3DAxis::setEnableCube(
bool show )
408 mCubeRoot->setEnabled( show );
411 mCubeRoot->setParent( mAxisSceneEntity );
415 mCubeRoot->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
419void Qgs3DAxis::setEnableAxis(
bool show )
421 mAxisRoot->setEnabled( show );
424 mAxisRoot->setParent( mAxisSceneEntity );
428 mAxisRoot->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
431 mTextX->setEnabled( show );
432 mTextY->setEnabled( show );
433 mTextZ->setEnabled( show );
436void Qgs3DAxis::createAxisScene()
438 if ( mAxisRoot ==
nullptr || mCubeRoot ==
nullptr )
440 mAxisRoot =
new Qt3DCore::QEntity;
441 mAxisRoot->setParent( mAxisSceneEntity );
442 mAxisRoot->setObjectName(
"3DAxis_AxisRoot" );
443 mAxisRoot->addComponent( mAxisSceneLayer );
445 createAxis( Qt::Axis::XAxis );
446 createAxis( Qt::Axis::YAxis );
447 createAxis( Qt::Axis::ZAxis );
449 mCubeRoot =
new Qt3DCore::QEntity;
450 mCubeRoot->setParent( mAxisSceneEntity );
451 mCubeRoot->setObjectName(
"3DAxis_CubeRoot" );
452 mCubeRoot->addComponent( mAxisSceneLayer );
461 mAxisSceneEntity->setEnabled(
false );
462 setEnableAxis(
false );
463 setEnableCube(
false );
467 mAxisSceneEntity->setEnabled(
true );
470 setEnableCube(
false );
471 setEnableAxis(
true );
473 const QList< Qgis::CrsAxisDirection > axisDirections = mCrs.
axisOrdering();
475 if ( axisDirections.length() > 0 )
478 mTextY->setText(
"X?" );
480 if ( axisDirections.length() > 1 )
483 mTextY->setText(
"Y?" );
485 if ( axisDirections.length() > 2 )
488 mTextZ->setText( QStringLiteral(
"up" ) );
492 setEnableCube(
true );
493 setEnableAxis(
false );
497 setEnableCube(
false );
498 setEnableAxis(
true );
499 mTextX->setText(
"X?" );
500 mTextY->setText(
"Y?" );
501 mTextZ->setText(
"Z?" );
504 updateAxisLabelPosition();
508void Qgs3DAxis::createKeyboardShortCut()
513 QWidget *mapCanvas =
dynamic_cast<QWidget *
>( eng->parent() );
514 if ( mapCanvas ==
nullptr )
520 QShortcut *shortcutHome =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_1 ), mapCanvas );
521 connect( shortcutHome, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeHome();} );
523 QShortcut *shortcutTop =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_5 ), mapCanvas );
524 connect( shortcutTop, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeTop();} );
526 QShortcut *shortcutNorth =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_8 ), mapCanvas );
527 connect( shortcutNorth, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeNorth();} );
529 QShortcut *shortcutEast =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_6 ), mapCanvas );
530 connect( shortcutEast, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeEast();} );
532 QShortcut *shortcutSouth =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_2 ), mapCanvas );
533 connect( shortcutSouth, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeSouth();} );
535 QShortcut *shortcutWest =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_4 ), mapCanvas );
536 connect( shortcutWest, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeWest();} );
541void Qgs3DAxis::createMenu()
546 QAction *typeOffAct =
new QAction( tr(
"&Off" ), mMenu );
547 typeOffAct->setCheckable(
true );
548 typeOffAct->setStatusTip( tr(
"Disable 3D axis" ) );
552 typeOffAct->setChecked(
true );
555 QAction *typeCrsAct =
new QAction( tr(
"Coordinate Reference &System" ), mMenu );
556 typeCrsAct->setCheckable(
true );
557 typeCrsAct->setStatusTip( tr(
"Coordinate Reference System 3D axis" ) );
561 typeCrsAct->setChecked(
true );
564 QAction *typeCubeAct =
new QAction( tr(
"&Cube" ), mMenu );
565 typeCubeAct->setCheckable(
true );
566 typeCubeAct->setStatusTip( tr(
"Cube 3D axis" ) );
570 typeCubeAct->setChecked(
true );
573 QActionGroup *typeGroup =
new QActionGroup( mMenu );
574 typeGroup->addAction( typeOffAct );
575 typeGroup->addAction( typeCrsAct );
576 typeGroup->addAction( typeCubeAct );
582 QMenu *typeMenu =
new QMenu( QStringLiteral(
"Axis Type" ), mMenu );
583 Q_ASSERT( typeMenu );
584 typeMenu->addAction( typeOffAct );
585 typeMenu->addAction( typeCrsAct );
586 typeMenu->addAction( typeCubeAct );
587 mMenu->addMenu( typeMenu );
590 QAction *hPosLeftAct =
new QAction( tr(
"&Left" ), mMenu );
591 hPosLeftAct->setCheckable(
true );
595 hPosLeftAct->setChecked(
true );
598 QAction *hPosMiddleAct =
new QAction( tr(
"&Center" ), mMenu );
599 hPosMiddleAct->setCheckable(
true );
603 hPosMiddleAct->setChecked(
true );
606 QAction *hPosRightAct =
new QAction( tr(
"&Right" ), mMenu );
607 hPosRightAct->setCheckable(
true );
611 hPosRightAct->setChecked(
true );
614 QActionGroup *hPosGroup =
new QActionGroup( mMenu );
615 hPosGroup->addAction( hPosLeftAct );
616 hPosGroup->addAction( hPosMiddleAct );
617 hPosGroup->addAction( hPosRightAct );
619 connect( hPosLeftAct, &QAction::triggered,
this, [
this](
bool ) {onAxisHorizPositionChanged( Qt::AnchorPoint::AnchorLeft );} );
620 connect( hPosMiddleAct, &QAction::triggered,
this, [
this](
bool ) {onAxisHorizPositionChanged( Qt::AnchorPoint::AnchorHorizontalCenter );} );
621 connect( hPosRightAct, &QAction::triggered,
this, [
this](
bool ) {onAxisHorizPositionChanged( Qt::AnchorPoint::AnchorRight );} );
623 QMenu *horizPosMenu =
new QMenu( QStringLiteral(
"Horizontal Position" ), mMenu );
624 horizPosMenu->addAction( hPosLeftAct );
625 horizPosMenu->addAction( hPosMiddleAct );
626 horizPosMenu->addAction( hPosRightAct );
627 mMenu->addMenu( horizPosMenu );
630 QAction *vPosTopAct =
new QAction( tr(
"&Top" ), mMenu );
631 vPosTopAct->setCheckable(
true );
635 vPosTopAct->setChecked(
true );
638 QAction *vPosMiddleAct =
new QAction( tr(
"&Middle" ), mMenu );
639 vPosMiddleAct->setCheckable(
true );
643 vPosMiddleAct->setChecked(
true );
646 QAction *vPosBottomAct =
new QAction( tr(
"&Bottom" ), mMenu );
647 vPosBottomAct->setCheckable(
true );
651 vPosBottomAct->setChecked(
true );
654 QActionGroup *vPosGroup =
new QActionGroup( mMenu );
655 vPosGroup->addAction( vPosTopAct );
656 vPosGroup->addAction( vPosMiddleAct );
657 vPosGroup->addAction( vPosBottomAct );
659 connect( vPosTopAct, &QAction::triggered,
this, [
this](
bool ) {onAxisVertPositionChanged( Qt::AnchorPoint::AnchorTop );} );
660 connect( vPosMiddleAct, &QAction::triggered,
this, [
this](
bool ) {onAxisVertPositionChanged( Qt::AnchorPoint::AnchorVerticalCenter );} );
661 connect( vPosBottomAct, &QAction::triggered,
this, [
this](
bool ) {onAxisVertPositionChanged( Qt::AnchorPoint::AnchorBottom );} );
663 QMenu *vertPosMenu =
new QMenu( QStringLiteral(
"Vertical Position" ), mMenu );
664 vertPosMenu->addAction( vPosTopAct );
665 vertPosMenu->addAction( vPosMiddleAct );
666 vertPosMenu->addAction( vPosBottomAct );
667 mMenu->addMenu( vertPosMenu );
670 QAction *viewHomeAct =
new QAction( tr(
"&Home" ) +
"\t Ctrl+1", mMenu );
671 QAction *viewTopAct =
new QAction( tr(
"&Top" ) +
"\t Ctrl+5", mMenu );
672 QAction *viewNorthAct =
new QAction( tr(
"&North" ) +
"\t Ctrl+8", mMenu );
673 QAction *viewEastAct =
new QAction( tr(
"&East" ) +
"\t Ctrl+6", mMenu );
674 QAction *viewSouthAct =
new QAction( tr(
"&South" ) +
"\t Ctrl+2", mMenu );
675 QAction *viewWestAct =
new QAction( tr(
"&West" ) +
"\t Ctrl+4", mMenu );
676 QAction *viewBottomAct =
new QAction( tr(
"&Bottom" ), mMenu );
678 connect( viewHomeAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeHome );
679 connect( viewTopAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeTop );
680 connect( viewNorthAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeNorth );
681 connect( viewEastAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeEast );
682 connect( viewSouthAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeSouth );
683 connect( viewWestAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeWest );
684 connect( viewBottomAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeBottom );
686 QMenu *viewMenu =
new QMenu( QStringLiteral(
"Camera View" ), mMenu );
687 viewMenu->addAction( viewHomeAct );
688 viewMenu->addAction( viewTopAct );
689 viewMenu->addAction( viewNorthAct );
690 viewMenu->addAction( viewEastAct );
691 viewMenu->addAction( viewSouthAct );
692 viewMenu->addAction( viewWestAct );
693 viewMenu->addAction( viewBottomAct );
694 mMenu->addMenu( viewMenu );
700void Qgs3DAxis::hideMenu()
702 if ( mMenu && mMenu->isVisible() )
706void Qgs3DAxis::displayMenuAt(
const QPoint &sourcePos )
708 if ( mMenu ==
nullptr )
712 QObject *threeDMapCanvasWidget = mMapScene->
engine()
716 QWidget *container =
dynamic_cast<QWidget *
>( threeDMapCanvasWidget->parent() );
718 mMenu->popup( container->mapToGlobal( sourcePos ) );
720 mMenu->popup( mParentWindow->parent()->mapToGlobal( sourcePos ) );
730void Qgs3DAxis::onAxisHorizPositionChanged( Qt::AnchorPoint pos )
737void Qgs3DAxis::onAxisVertPositionChanged( Qt::AnchorPoint pos )
744void Qgs3DAxis::onCameraViewChange(
float pitch,
float yaw )
747 double elevation = 0.0;
751 QVector3D intersectionPoint;
752 QVector3D camPos = mCameraController->
camera()->position();
753 QgsRayCastingUtils::Ray3D r( camPos, pos.
toVector3D() - camPos );
754 if ( mMapScene->
terrainEntity()->rayIntersection( r, intersectionPoint ) )
756 elevation = intersectionPoint.y();
757 QgsDebugMsgLevel( QString(
"Computed elevation from terrain: %1" ).arg( elevation ), 2 );
770void Qgs3DAxis::createCube( )
772 QVector3D minPos = QVector3D( -mCylinderLength * 0.5f, -mCylinderLength * 0.5f, -mCylinderLength * 0.5f );
775 Qt3DCore::QEntity *cubeLineEntity =
new Qt3DCore::QEntity( mCubeRoot );
776 cubeLineEntity->setObjectName(
"3DAxis_cubeline" );
778 QgsAABB box =
QgsAABB( -mCylinderLength * 0.5f, -mCylinderLength * 0.5f, -mCylinderLength * 0.5f,
779 mCylinderLength * 0.5f, mCylinderLength * 0.5f, mCylinderLength * 0.5f );
781 cubeLineEntity->addComponent( cubeLine );
783 Qt3DExtras::QPhongMaterial *cubeLineMaterial =
new Qt3DExtras::QPhongMaterial;
784 cubeLineMaterial->setAmbient( Qt::white );
785 cubeLineEntity->addComponent( cubeLineMaterial );
788 Qt3DExtras::QCuboidMesh *cubeMesh =
new Qt3DExtras::QCuboidMesh;
789 cubeMesh->setObjectName(
"3DAxis_cubemesh" );
790 cubeMesh->setXExtent( mCylinderLength );
791 cubeMesh->setYExtent( mCylinderLength );
792 cubeMesh->setZExtent( mCylinderLength );
793 mCubeRoot->addComponent( cubeMesh );
795 Qt3DExtras::QPhongMaterial *cubeMaterial =
new Qt3DExtras::QPhongMaterial( mCubeRoot );
796 cubeMaterial->setAmbient( QColor( 100, 100, 100, 50 ) );
797 cubeMaterial->setShininess( 100 );
798 mCubeRoot->addComponent( cubeMaterial );
800 Qt3DCore::QTransform *cubeTransform =
new Qt3DCore::QTransform;
801 QMatrix4x4 transformMatrixcube;
803 transformMatrixcube.translate( minPos + QVector3D( mCylinderLength * 0.5f, mCylinderLength * 0.5f, mCylinderLength * 0.5f ) );
804 cubeTransform->setMatrix( transformMatrixcube );
805 mCubeRoot->addComponent( cubeTransform );
809 int fontSize = 0.75 * mFontSize;
810 float textHeight = fontSize * 1.5f;
812 QFont f = QFontDatabase::systemFont( QFontDatabase::FixedFont );
813 f.setPointSize( fontSize );
814 f.setWeight( QFont::Weight::Black );
817 text = QStringLiteral(
"top" );
818 textWidth = text.length() * fontSize * 0.75f;
819 QVector3D translation = minPos + QVector3D(
820 mCylinderLength * 0.5f - textWidth / 2.0f,
821 mCylinderLength * 0.5f - textHeight / 2.0f,
822 mCylinderLength * 1.01f );
824 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
828 text = QStringLiteral(
"btm" );
829 textWidth = text.length() * fontSize * 0.75f;
830 QVector3D translation = minPos + QVector3D(
831 mCylinderLength * 0.5f - textWidth / 2.0f,
832 mCylinderLength * 0.5f + textHeight / 2.0f,
833 -mCylinderLength * 0.01f );
835 rotation.rotate( 180.0f, QVector3D( 1.0f, 0.0f, 0.0f ).normalized() );
836 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
840 text = QStringLiteral(
"west" );
841 textWidth = text.length() * fontSize * 0.75f;
842 QVector3D translation = minPos + QVector3D(
843 - mCylinderLength * 0.01f,
844 mCylinderLength * 0.5f + textWidth / 2.0f,
845 mCylinderLength * 0.5f - textHeight / 2.0f );
847 rotation.rotate( 90.0f, QVector3D( 0.0f, -1.0f, 0.0f ).normalized() );
848 rotation.rotate( 90.0f, QVector3D( 0.0f, 0.0f, -1.0f ).normalized() );
849 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
853 text = QStringLiteral(
"east" );
854 textWidth = text.length() * fontSize * 0.75f;
855 QVector3D translation = minPos + QVector3D(
856 mCylinderLength * 1.01f,
857 mCylinderLength * 0.5f - textWidth / 2.0f,
858 mCylinderLength * 0.5f - textHeight / 2.0f );
860 rotation.rotate( 90.0f, QVector3D( 0.0f, 1.0f, 0.0f ).normalized() );
861 rotation.rotate( 90.0f, QVector3D( 0.0f, 0.0f, 1.0f ).normalized() );
862 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
866 text = QStringLiteral(
"south" );
867 textWidth = text.length() * fontSize * 0.75f;
868 QVector3D translation = minPos + QVector3D(
869 mCylinderLength * 0.5f - textWidth / 2.0f,
870 - mCylinderLength * 0.01f,
871 mCylinderLength * 0.5f - textHeight / 2.0f );
873 rotation.rotate( 90.0f, QVector3D( 1.0f, 0.0f, 0.0f ).normalized() );
874 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
878 text = QStringLiteral(
"north" );
879 textWidth = text.length() * fontSize * 0.75f;
880 QVector3D translation = minPos + QVector3D(
881 mCylinderLength * 0.5f + textWidth / 2.0f,
882 mCylinderLength * 1.01f,
883 mCylinderLength * 0.5f - textHeight / 2.0f );
885 rotation.rotate( 90.0f, QVector3D( -1.0f, 0.0f, 0.0f ).normalized() );
886 rotation.rotate( 180.0f, QVector3D( 0.0f, 0.0f, 1.0f ).normalized() );
887 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
890 for ( Qt3DExtras::QText2DEntity *l : std::as_const( mCubeLabels ) )
892 l->setParent( mCubeRoot );
896Qt3DExtras::QText2DEntity *Qgs3DAxis::addCubeText(
const QString &text,
float textHeight,
float textWidth,
const QFont &f,
const QMatrix4x4 &rotation,
const QVector3D &translation )
898 Qt3DExtras::QText2DEntity *textEntity =
new Qt3DExtras::QText2DEntity;
899 textEntity->setObjectName(
"3DAxis_cube_label_" + text );
900 textEntity->setFont( f );
901 textEntity->setHeight( textHeight );
902 textEntity->setWidth( textWidth );
903 textEntity->setColor( QColor( 192, 192, 192 ) );
904 textEntity->setText( text );
906 Qt3DCore::QTransform *textFrontTransform =
new Qt3DCore::QTransform();
907 textFrontTransform->setMatrix( rotation );
908 textFrontTransform->setTranslation( translation );
909 textEntity->addComponent( textFrontTransform );
914void Qgs3DAxis::createAxis( Qt::Axis axisType )
916 float cylinderRadius = 0.05f * mCylinderLength;
917 float coneLength = 0.3f * mCylinderLength;
918 float coneBottomRadius = 0.1f * mCylinderLength;
920 QQuaternion rotation;
923 Qt3DExtras::QText2DEntity *text =
nullptr;
924 Qt3DCore::QTransform *textTransform =
nullptr;
929 case Qt::Axis::XAxis:
930 mTextX =
new Qt3DExtras::QText2DEntity( );
931 mTextX->setParent( mTwoDLabelSceneEntity );
932 connect( mTextX, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextXChanged );
933 mTextTransformX =
new Qt3DCore::QTransform();
934 mTextCoordX = QVector3D( mCylinderLength + coneLength / 2.0f, 0.0f, 0.0f );
936 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 1.0f ), -90.0f );
939 textTransform = mTextTransformX;
940 name =
"3DAxis_axisX";
943 case Qt::Axis::YAxis:
944 mTextY =
new Qt3DExtras::QText2DEntity( );
945 mTextY->setParent( mTwoDLabelSceneEntity );
946 connect( mTextY, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextYChanged );
947 mTextTransformY =
new Qt3DCore::QTransform();
948 mTextCoordY = QVector3D( 0.0f, mCylinderLength + coneLength / 2.0f, 0.0f );
950 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 0.0f ), 0.0f );
953 textTransform = mTextTransformY;
954 name =
"3DAxis_axisY";
957 case Qt::Axis::ZAxis:
958 mTextZ =
new Qt3DExtras::QText2DEntity( );
959 mTextZ->setParent( mTwoDLabelSceneEntity );
960 connect( mTextZ, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextZChanged );
961 mTextTransformZ =
new Qt3DCore::QTransform();
962 mTextCoordZ = QVector3D( 0.0f, 0.0f, mCylinderLength + coneLength / 2.0f );
964 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 1.0f, 0.0f, 0.0f ), 90.0f );
967 textTransform = mTextTransformZ;
968 name =
"3DAxis_axisZ";
976 Qt3DCore::QEntity *cylinder =
new Qt3DCore::QEntity( mAxisRoot );
977 cylinder->setObjectName( name );
979 Qt3DExtras::QCylinderMesh *cylinderMesh =
new Qt3DExtras::QCylinderMesh;
980 cylinderMesh->setRadius( cylinderRadius );
981 cylinderMesh->setLength( mCylinderLength );
982 cylinderMesh->setRings( 10 );
983 cylinderMesh->setSlices( 4 );
984 cylinder->addComponent( cylinderMesh );
986 Qt3DExtras::QPhongMaterial *cylinderMaterial =
new Qt3DExtras::QPhongMaterial( cylinder );
987 cylinderMaterial->setAmbient( color );
988 cylinderMaterial->setShininess( 0 );
989 cylinder->addComponent( cylinderMaterial );
991 Qt3DCore::QTransform *cylinderTransform =
new Qt3DCore::QTransform;
992 QMatrix4x4 transformMatrixCylinder;
993 transformMatrixCylinder.rotate( rotation );
994 transformMatrixCylinder.translate( QVector3D( 0.0f, mCylinderLength / 2.0f, 0.0f ) );
995 cylinderTransform->setMatrix( transformMatrixCylinder );
996 cylinder->addComponent( cylinderTransform );
999 Qt3DCore::QEntity *coneEntity =
new Qt3DCore::QEntity( mAxisRoot );
1000 coneEntity->setObjectName( name );
1001 Qt3DExtras::QConeMesh *coneMesh =
new Qt3DExtras::QConeMesh;
1002 coneMesh->setLength( coneLength );
1003 coneMesh->setBottomRadius( coneBottomRadius );
1004 coneMesh->setTopRadius( 0.0f );
1005 coneMesh->setRings( 10 );
1006 coneMesh->setSlices( 4 );
1007 coneEntity->addComponent( coneMesh );
1009 Qt3DExtras::QPhongMaterial *coneMaterial =
new Qt3DExtras::QPhongMaterial( coneEntity );
1010 coneMaterial->setAmbient( color );
1011 coneMaterial->setShininess( 0 );
1012 coneEntity->addComponent( coneMaterial );
1014 Qt3DCore::QTransform *coneTransform =
new Qt3DCore::QTransform;
1015 QMatrix4x4 transformMatrixCone;
1016 transformMatrixCone.rotate( rotation );
1017 transformMatrixCone.translate( QVector3D( 0.0f, mCylinderLength, 0.0f ) );
1018 coneTransform->setMatrix( transformMatrixCone );
1019 coneEntity->addComponent( coneTransform );
1022 text->setColor( QColor( 192, 192, 192, 192 ) );
1023 text->addComponent( textTransform );
1029 onAxisViewportSizeUpdate();
1032void Qgs3DAxis::onAxisViewportSizeUpdate(
int )
1036 double windowWidth = ( double )mParentWindow->width();
1037 double windowHeight = ( double )mParentWindow->height();
1042 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window w/h: %1px / %2px" )
1043 .arg( windowWidth ).arg( windowHeight ), 2 );
1044 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window physicalDpi %1 (%2, %3)" )
1045 .arg( mParentWindow->screen()->physicalDotsPerInch() )
1046 .arg( mParentWindow->screen()->physicalDotsPerInchX() )
1047 .arg( mParentWindow->screen()->physicalDotsPerInchY() ), 2 );
1048 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window logicalDotsPerInch %1 (%2, %3)" )
1049 .arg( mParentWindow->screen()->logicalDotsPerInch() )
1050 .arg( mParentWindow->screen()->logicalDotsPerInchX() )
1051 .arg( mParentWindow->screen()->logicalDotsPerInchY() ), 2 );
1053 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window pixel ratio %1" )
1054 .arg( mParentWindow->screen()->devicePixelRatio() ), 2 );
1065 double defaultViewportPixelSize = ( ( double )settings.
defaultViewportSize() / 25.4 ) * 92.0;
1069 double viewportPixelSize = defaultViewportPixelSize + ( ( double )settings.
defaultViewportSize() / 25.4 )
1070 * ( mParentWindow->screen()->physicalDotsPerInch() - 92.0 ) * 0.7;
1071 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate viewportPixelSize %1" ).arg( viewportPixelSize ), 2 );
1072 double widthRatio = viewportPixelSize / windowWidth;
1073 double heightRatio = widthRatio * windowWidth / windowHeight;
1075 QgsDebugMsgLevel( QString(
"3DAxis viewport ratios width: %1% / height: %2%" ).arg( widthRatio ).arg( heightRatio ), 2 );
1077 if ( heightRatio * windowHeight < viewportPixelSize )
1079 heightRatio = viewportPixelSize / windowHeight;
1080 widthRatio = heightRatio * windowHeight / windowWidth;
1081 QgsDebugMsgLevel( QString(
"3DAxis viewport, height too small, ratios adjusted to width: %1% / height: %2%" ).arg( widthRatio ).arg( heightRatio ), 2 );
1086 QgsDebugMsgLevel(
"viewport takes too much place into the 3d view, disabling it", 2 );
1088 mAxisViewport->setEnabled(
false );
1089 setEnableCube(
false );
1090 setEnableAxis(
false );
1095 mAxisScaleFactor = viewportPixelSize / defaultViewportPixelSize;
1096 QgsDebugMsgLevel( QString(
"3DAxis viewport mAxisScaleFactor %1" ).arg( mAxisScaleFactor ), 2 );
1098 if ( ! mAxisViewport->isEnabled() )
1101 setEnableAxis(
true );
1103 setEnableCube(
true );
1105 mAxisViewport->setEnabled(
true );
1107 float xRatio = 1.0f;
1108 float yRatio = 1.0f;
1112 xRatio = 0.5f - widthRatio / 2.0f;
1114 xRatio = 1.0f - widthRatio;
1118 else if ( settings.
verticalPosition() == Qt::AnchorPoint::AnchorVerticalCenter )
1119 yRatio = 0.5f - heightRatio / 2.0f;
1121 yRatio = 1.0f - heightRatio;
1123 QgsDebugMsgLevel( QString(
"Qgs3DAxis: update viewport: %1 x %2 x %3 x %4" ).arg( xRatio ).arg( yRatio ).arg( widthRatio ).arg( heightRatio ), 2 );
1124 mAxisViewport->setNormalizedRect( QRectF( xRatio, yRatio, widthRatio, heightRatio ) );
1128 mTwoDLabelCamera->lens()->setOrthographicProjection(
1129 -windowWidth / 2.0f, windowWidth / 2.0f,
1130 -windowHeight / 2.0f, windowHeight / 2.0f,
1131 mTwoDLabelCamera->lens()->nearPlane(), mTwoDLabelCamera->lens()->farPlane() );
1133 updateAxisLabelPosition();
1138void Qgs3DAxis::onCameraUpdate( )
1140 Qt3DRender::QCamera *parentCamera = mCameraController->
camera();
1142 if ( parentCamera->viewVector() != mPreviousVector
1143 && !std::isnan( parentCamera->viewVector().x() )
1144 && !std::isnan( parentCamera->viewVector().y() )
1145 && !std::isnan( parentCamera->viewVector().z() ) )
1147 mPreviousVector = parentCamera->viewVector();
1148 QVector3D mainCameraShift = parentCamera->viewVector().normalized();
1149 float zy_swap = mainCameraShift.y();
1150 mainCameraShift.setY( mainCameraShift.z() );
1151 mainCameraShift.setZ( -zy_swap );
1152 mainCameraShift.setX( -mainCameraShift.x() );
1154 if ( mAxisCamera->projectionType() == Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection )
1156 mAxisCamera->setPosition( mainCameraShift );
1160 mAxisCamera->setPosition( mainCameraShift * mCylinderLength * 10.0 );
1163 if ( mAxisRoot->isEnabled() )
1165 updateAxisLabelPosition();
1170void Qgs3DAxis::updateAxisLabelPosition()
1172 if ( mTextTransformX && mTextTransformY && mTextTransformZ )
1175 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1176 mParentWindow->size() ) );
1177 onTextXChanged( mTextX->text() );
1180 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1181 mParentWindow->size() ) );
1182 onTextYChanged( mTextY->text() );
1185 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1186 mParentWindow->size() ) );
1187 onTextZChanged( mTextZ->text() );
1191void Qgs3DAxis::onTextXChanged(
const QString &text )
1193 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1194 f.setWeight( QFont::Weight::Black );
1195 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1196 mTextX->setFont( f );
1197 mTextX->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1198 mTextX->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1201void Qgs3DAxis::onTextYChanged(
const QString &text )
1203 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1204 f.setWeight( QFont::Weight::Black );
1205 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1206 mTextY->setFont( f );
1207 mTextY->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1208 mTextY->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1211void Qgs3DAxis::onTextZChanged(
const QString &text )
1213 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1214 f.setWeight( QFont::Weight::Black );
1215 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1216 mTextZ->setFont( f );
1217 mTextZ->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1218 mTextZ->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1230 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
1231 mPositionAttribute->setBuffer( mVertexBuffer );
1232 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
1233 mPositionAttribute->setVertexSize( 3 );
1234 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
1237 mGeom->addAttribute( mPositionAttribute );
1239 setInstanceCount( 1 );
1240 setIndexOffset( 0 );
1241 setFirstInstance( 0 );
1242 setPrimitiveType( Qt3DRender::QGeometryRenderer::Lines );
1243 setGeometry( mGeom );
1250 QByteArray vertexBufferData;
1251 vertexBufferData.resize( vertices.size() * 3 *
sizeof(
float ) );
1252 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
1254 for (
const QVector3D &v : std::as_const( vertices ) )
1256 rawVertexArray[idx++] = v.x();
1257 rawVertexArray[idx++] = v.y();
1258 rawVertexArray[idx++] = v.z();
1261 mVertexBuffer->setData( vertexBufferData );
1262 setVertexCount( vertices.count() );
Contains the configuration of a 3d axis.
void setMode(Qgs3DAxisSettings::Mode type)
Sets the type of the 3daxis.
double maxViewportRatio() const
Returns the maximal axis viewport ratio (see Qt3DRender::QViewport::normalizedRect())
Mode
Axis representation enum.
@ Crs
Respect CRS directions.
@ Cube
Abstract cube mode.
Qt::AnchorPoint verticalPosition() const
Returns the vertical position for the 3d axis.
void setHorizontalPosition(Qt::AnchorPoint position)
Sets the horizontal position for the 3d axis.
int defaultViewportSize() const
Returns the default axis viewport size in millimeters.
Qgs3DAxisSettings::Mode mode() const
Returns the type of the 3daxis.
Qt::AnchorPoint horizontalPosition() const
Returns the horizontal position for the 3d axis.
void setVerticalPosition(Qt::AnchorPoint position)
Sets the vertical position for the 3d axis.
Qgs3DAxis(Qt3DExtras::Qt3DWindow *parentWindow, Qt3DCore::QEntity *parent3DScene, Qgs3DMapScene *mapScene, QgsCameraController *camera, Qgs3DMapSettings *map)
Defaul Qgs3DAxis constructor.
QVector3D from3DTo2DLabelPosition(const QVector3D &sourcePos, Qt3DRender::QCamera *sourceCamera, Qt3DRender::QViewport *sourceViewport, Qt3DRender::QCamera *destCamera, Qt3DRender::QViewport *destViewport, const QSize &destSize)
project a 3D position from sourceCamera (in sourceViewport) to a 2D position for destCamera (in destV...
void onAxisSettingsChanged()
Force update of the axis and the viewport when a setting has changed.
QgsAbstract3DEngine * engine()
Returns the abstract 3D engine.
QgsTerrainEntity * terrainEntity()
Returns terrain entity (may be temporarily nullptr)
Qgs3DAxisSettings get3DAxisSettings() const
Returns the current configuration of 3d axis.
float terrainElevationOffset() const
Returns the elevation offset of the terrain (used to move the terrain up or down)
void set3DAxisSettings(const Qgs3DAxisSettings &axisSettings, bool force=false)
Sets the current configuration of 3d axis.
bool terrainRenderingEnabled() const
Returns whether the 2D terrain surface will be rendered.
void axisSettingsChanged()
Emitted when 3d axis rendering settings are changed.
~Qgs3DWiredMesh() override
Qgs3DWiredMesh(Qt3DCore::QNode *parent=nullptr)
Defaul Qgs3DWiredMesh constructor.
void setVertices(const QList< QVector3D > &vertices)
add or replace mesh vertices coordinates
QList< QVector3D > verticesForLines() const
Returns a list of pairs of vertices (useful for display of bounding boxes)
Qt3DRender::QCamera * camera
void cameraChanged()
Emitted when camera has been updated.
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.
static QString axisDirectionToAbbreviatedString(Qgis::CrsAxisDirection axis)
Returns a translated abbreviation representing an axis direction.
QList< Qgis::CrsAxisDirection > axisOrdering() const
Returns an ordered list of the axis directions reflecting the native axis order for the CRS.
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
static void warning(const QString &msg)
Goes to qWarning.
The QgsMapSettings class contains configuration for rendering of the map.
double dpiTarget() const
Returns the target DPI (dots per inch) to be taken into consideration when rendering.
float devicePixelRatio() const
Returns the device pixel ratio.
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
double z() const
Returns Z coordinate.
QVector3D toVector3D() const
Converts the current object to QVector3D.
double x() const
Returns X coordinate.
void set(double x, double y, double z)
Sets vector coordinates.
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry
#define QgsDebugMsgLevel(str, level)
const QgsCoordinateReferenceSystem & crs