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 camPos = mCameraController->
camera()->position();
752 QgsRayCastingUtils::Ray3D ray( camPos, pos.
toVector3D() - camPos, mCameraController->
camera()->farPlane() );
753 const QVector<QgsRayCastingUtils::RayHit> hits = mMapScene->
terrainEntity()->rayIntersection( ray, QgsRayCastingUtils::RayCastContext() );
754 if ( !hits.isEmpty() )
756 elevation = hits.at( 0 ).pos.y();
757 QgsDebugMsgLevel( QString(
"Computed elevation from terrain: %1" ).arg( elevation ), 2 );
771void Qgs3DAxis::createCube( )
773 QVector3D minPos = QVector3D( -mCylinderLength * 0.5f, -mCylinderLength * 0.5f, -mCylinderLength * 0.5f );
776 Qt3DCore::QEntity *cubeLineEntity =
new Qt3DCore::QEntity( mCubeRoot );
777 cubeLineEntity->setObjectName(
"3DAxis_cubeline" );
779 QgsAABB box =
QgsAABB( -mCylinderLength * 0.5f, -mCylinderLength * 0.5f, -mCylinderLength * 0.5f,
780 mCylinderLength * 0.5f, mCylinderLength * 0.5f, mCylinderLength * 0.5f );
782 cubeLineEntity->addComponent( cubeLine );
784 Qt3DExtras::QPhongMaterial *cubeLineMaterial =
new Qt3DExtras::QPhongMaterial;
785 cubeLineMaterial->setAmbient( Qt::white );
786 cubeLineEntity->addComponent( cubeLineMaterial );
789 Qt3DExtras::QCuboidMesh *cubeMesh =
new Qt3DExtras::QCuboidMesh;
790 cubeMesh->setObjectName(
"3DAxis_cubemesh" );
791 cubeMesh->setXExtent( mCylinderLength );
792 cubeMesh->setYExtent( mCylinderLength );
793 cubeMesh->setZExtent( mCylinderLength );
794 mCubeRoot->addComponent( cubeMesh );
796 Qt3DExtras::QPhongMaterial *cubeMaterial =
new Qt3DExtras::QPhongMaterial( mCubeRoot );
797 cubeMaterial->setAmbient( QColor( 100, 100, 100, 50 ) );
798 cubeMaterial->setShininess( 100 );
799 mCubeRoot->addComponent( cubeMaterial );
801 Qt3DCore::QTransform *cubeTransform =
new Qt3DCore::QTransform;
802 QMatrix4x4 transformMatrixcube;
804 transformMatrixcube.translate( minPos + QVector3D( mCylinderLength * 0.5f, mCylinderLength * 0.5f, mCylinderLength * 0.5f ) );
805 cubeTransform->setMatrix( transformMatrixcube );
806 mCubeRoot->addComponent( cubeTransform );
810 int fontSize = 0.75 * mFontSize;
811 float textHeight = fontSize * 1.5f;
813 QFont f = QFontDatabase::systemFont( QFontDatabase::FixedFont );
814 f.setPointSize( fontSize );
815 f.setWeight( QFont::Weight::Black );
818 text = QStringLiteral(
"top" );
819 textWidth = text.length() * fontSize * 0.75f;
820 QVector3D translation = minPos + QVector3D(
821 mCylinderLength * 0.5f - textWidth / 2.0f,
822 mCylinderLength * 0.5f - textHeight / 2.0f,
823 mCylinderLength * 1.01f );
825 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
829 text = QStringLiteral(
"btm" );
830 textWidth = text.length() * fontSize * 0.75f;
831 QVector3D translation = minPos + QVector3D(
832 mCylinderLength * 0.5f - textWidth / 2.0f,
833 mCylinderLength * 0.5f + textHeight / 2.0f,
834 -mCylinderLength * 0.01f );
836 rotation.rotate( 180.0f, QVector3D( 1.0f, 0.0f, 0.0f ).normalized() );
837 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
841 text = QStringLiteral(
"west" );
842 textWidth = text.length() * fontSize * 0.75f;
843 QVector3D translation = minPos + QVector3D(
844 - mCylinderLength * 0.01f,
845 mCylinderLength * 0.5f + textWidth / 2.0f,
846 mCylinderLength * 0.5f - textHeight / 2.0f );
848 rotation.rotate( 90.0f, QVector3D( 0.0f, -1.0f, 0.0f ).normalized() );
849 rotation.rotate( 90.0f, QVector3D( 0.0f, 0.0f, -1.0f ).normalized() );
850 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
854 text = QStringLiteral(
"east" );
855 textWidth = text.length() * fontSize * 0.75f;
856 QVector3D translation = minPos + QVector3D(
857 mCylinderLength * 1.01f,
858 mCylinderLength * 0.5f - textWidth / 2.0f,
859 mCylinderLength * 0.5f - textHeight / 2.0f );
861 rotation.rotate( 90.0f, QVector3D( 0.0f, 1.0f, 0.0f ).normalized() );
862 rotation.rotate( 90.0f, QVector3D( 0.0f, 0.0f, 1.0f ).normalized() );
863 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
867 text = QStringLiteral(
"south" );
868 textWidth = text.length() * fontSize * 0.75f;
869 QVector3D translation = minPos + QVector3D(
870 mCylinderLength * 0.5f - textWidth / 2.0f,
871 - mCylinderLength * 0.01f,
872 mCylinderLength * 0.5f - textHeight / 2.0f );
874 rotation.rotate( 90.0f, QVector3D( 1.0f, 0.0f, 0.0f ).normalized() );
875 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
879 text = QStringLiteral(
"north" );
880 textWidth = text.length() * fontSize * 0.75f;
881 QVector3D translation = minPos + QVector3D(
882 mCylinderLength * 0.5f + textWidth / 2.0f,
883 mCylinderLength * 1.01f,
884 mCylinderLength * 0.5f - textHeight / 2.0f );
886 rotation.rotate( 90.0f, QVector3D( -1.0f, 0.0f, 0.0f ).normalized() );
887 rotation.rotate( 180.0f, QVector3D( 0.0f, 0.0f, 1.0f ).normalized() );
888 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
891 for ( Qt3DExtras::QText2DEntity *l : std::as_const( mCubeLabels ) )
893 l->setParent( mCubeRoot );
897Qt3DExtras::QText2DEntity *Qgs3DAxis::addCubeText(
const QString &text,
float textHeight,
float textWidth,
const QFont &f,
const QMatrix4x4 &rotation,
const QVector3D &translation )
899 Qt3DExtras::QText2DEntity *textEntity =
new Qt3DExtras::QText2DEntity;
900 textEntity->setObjectName(
"3DAxis_cube_label_" + text );
901 textEntity->setFont( f );
902 textEntity->setHeight( textHeight );
903 textEntity->setWidth( textWidth );
904 textEntity->setColor( QColor( 192, 192, 192 ) );
905 textEntity->setText( text );
907 Qt3DCore::QTransform *textFrontTransform =
new Qt3DCore::QTransform();
908 textFrontTransform->setMatrix( rotation );
909 textFrontTransform->setTranslation( translation );
910 textEntity->addComponent( textFrontTransform );
915void Qgs3DAxis::createAxis( Qt::Axis axisType )
917 float cylinderRadius = 0.05f * mCylinderLength;
918 float coneLength = 0.3f * mCylinderLength;
919 float coneBottomRadius = 0.1f * mCylinderLength;
921 QQuaternion rotation;
924 Qt3DExtras::QText2DEntity *text =
nullptr;
925 Qt3DCore::QTransform *textTransform =
nullptr;
930 case Qt::Axis::XAxis:
931 mTextX =
new Qt3DExtras::QText2DEntity( );
932 mTextX->setParent( mTwoDLabelSceneEntity );
933 connect( mTextX, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextXChanged );
934 mTextTransformX =
new Qt3DCore::QTransform();
935 mTextCoordX = QVector3D( mCylinderLength + coneLength / 2.0f, 0.0f, 0.0f );
937 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 1.0f ), -90.0f );
940 textTransform = mTextTransformX;
941 name =
"3DAxis_axisX";
944 case Qt::Axis::YAxis:
945 mTextY =
new Qt3DExtras::QText2DEntity( );
946 mTextY->setParent( mTwoDLabelSceneEntity );
947 connect( mTextY, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextYChanged );
948 mTextTransformY =
new Qt3DCore::QTransform();
949 mTextCoordY = QVector3D( 0.0f, mCylinderLength + coneLength / 2.0f, 0.0f );
951 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 0.0f ), 0.0f );
954 textTransform = mTextTransformY;
955 name =
"3DAxis_axisY";
958 case Qt::Axis::ZAxis:
959 mTextZ =
new Qt3DExtras::QText2DEntity( );
960 mTextZ->setParent( mTwoDLabelSceneEntity );
961 connect( mTextZ, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextZChanged );
962 mTextTransformZ =
new Qt3DCore::QTransform();
963 mTextCoordZ = QVector3D( 0.0f, 0.0f, mCylinderLength + coneLength / 2.0f );
965 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 1.0f, 0.0f, 0.0f ), 90.0f );
968 textTransform = mTextTransformZ;
969 name =
"3DAxis_axisZ";
977 Qt3DCore::QEntity *cylinder =
new Qt3DCore::QEntity( mAxisRoot );
978 cylinder->setObjectName( name );
980 Qt3DExtras::QCylinderMesh *cylinderMesh =
new Qt3DExtras::QCylinderMesh;
981 cylinderMesh->setRadius( cylinderRadius );
982 cylinderMesh->setLength( mCylinderLength );
983 cylinderMesh->setRings( 10 );
984 cylinderMesh->setSlices( 4 );
985 cylinder->addComponent( cylinderMesh );
987 Qt3DExtras::QPhongMaterial *cylinderMaterial =
new Qt3DExtras::QPhongMaterial( cylinder );
988 cylinderMaterial->setAmbient( color );
989 cylinderMaterial->setShininess( 0 );
990 cylinder->addComponent( cylinderMaterial );
992 Qt3DCore::QTransform *cylinderTransform =
new Qt3DCore::QTransform;
993 QMatrix4x4 transformMatrixCylinder;
994 transformMatrixCylinder.rotate( rotation );
995 transformMatrixCylinder.translate( QVector3D( 0.0f, mCylinderLength / 2.0f, 0.0f ) );
996 cylinderTransform->setMatrix( transformMatrixCylinder );
997 cylinder->addComponent( cylinderTransform );
1000 Qt3DCore::QEntity *coneEntity =
new Qt3DCore::QEntity( mAxisRoot );
1001 coneEntity->setObjectName( name );
1002 Qt3DExtras::QConeMesh *coneMesh =
new Qt3DExtras::QConeMesh;
1003 coneMesh->setLength( coneLength );
1004 coneMesh->setBottomRadius( coneBottomRadius );
1005 coneMesh->setTopRadius( 0.0f );
1006 coneMesh->setRings( 10 );
1007 coneMesh->setSlices( 4 );
1008 coneEntity->addComponent( coneMesh );
1010 Qt3DExtras::QPhongMaterial *coneMaterial =
new Qt3DExtras::QPhongMaterial( coneEntity );
1011 coneMaterial->setAmbient( color );
1012 coneMaterial->setShininess( 0 );
1013 coneEntity->addComponent( coneMaterial );
1015 Qt3DCore::QTransform *coneTransform =
new Qt3DCore::QTransform;
1016 QMatrix4x4 transformMatrixCone;
1017 transformMatrixCone.rotate( rotation );
1018 transformMatrixCone.translate( QVector3D( 0.0f, mCylinderLength, 0.0f ) );
1019 coneTransform->setMatrix( transformMatrixCone );
1020 coneEntity->addComponent( coneTransform );
1023 text->setColor( QColor( 192, 192, 192, 192 ) );
1024 text->addComponent( textTransform );
1030 onAxisViewportSizeUpdate();
1033void Qgs3DAxis::onAxisViewportSizeUpdate(
int )
1037 double windowWidth = ( double )mParentWindow->width();
1038 double windowHeight = ( double )mParentWindow->height();
1043 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window w/h: %1px / %2px" )
1044 .arg( windowWidth ).arg( windowHeight ), 2 );
1045 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window physicalDpi %1 (%2, %3)" )
1046 .arg( mParentWindow->screen()->physicalDotsPerInch() )
1047 .arg( mParentWindow->screen()->physicalDotsPerInchX() )
1048 .arg( mParentWindow->screen()->physicalDotsPerInchY() ), 2 );
1049 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window logicalDotsPerInch %1 (%2, %3)" )
1050 .arg( mParentWindow->screen()->logicalDotsPerInch() )
1051 .arg( mParentWindow->screen()->logicalDotsPerInchX() )
1052 .arg( mParentWindow->screen()->logicalDotsPerInchY() ), 2 );
1054 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window pixel ratio %1" )
1055 .arg( mParentWindow->screen()->devicePixelRatio() ), 2 );
1066 double defaultViewportPixelSize = ( ( double )settings.
defaultViewportSize() / 25.4 ) * 92.0;
1070 double viewportPixelSize = defaultViewportPixelSize + ( ( double )settings.
defaultViewportSize() / 25.4 )
1071 * ( mParentWindow->screen()->physicalDotsPerInch() - 92.0 ) * 0.7;
1072 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate viewportPixelSize %1" ).arg( viewportPixelSize ), 2 );
1073 double widthRatio = viewportPixelSize / windowWidth;
1074 double heightRatio = widthRatio * windowWidth / windowHeight;
1076 QgsDebugMsgLevel( QString(
"3DAxis viewport ratios width: %1% / height: %2%" ).arg( widthRatio ).arg( heightRatio ), 2 );
1078 if ( heightRatio * windowHeight < viewportPixelSize )
1080 heightRatio = viewportPixelSize / windowHeight;
1081 widthRatio = heightRatio * windowHeight / windowWidth;
1082 QgsDebugMsgLevel( QString(
"3DAxis viewport, height too small, ratios adjusted to width: %1% / height: %2%" ).arg( widthRatio ).arg( heightRatio ), 2 );
1087 QgsDebugMsgLevel(
"viewport takes too much place into the 3d view, disabling it", 2 );
1089 mAxisViewport->setEnabled(
false );
1090 setEnableCube(
false );
1091 setEnableAxis(
false );
1096 mAxisScaleFactor = viewportPixelSize / defaultViewportPixelSize;
1097 QgsDebugMsgLevel( QString(
"3DAxis viewport mAxisScaleFactor %1" ).arg( mAxisScaleFactor ), 2 );
1099 if ( ! mAxisViewport->isEnabled() )
1102 setEnableAxis(
true );
1104 setEnableCube(
true );
1106 mAxisViewport->setEnabled(
true );
1108 float xRatio = 1.0f;
1109 float yRatio = 1.0f;
1113 xRatio = 0.5f - widthRatio / 2.0f;
1115 xRatio = 1.0f - widthRatio;
1119 else if ( settings.
verticalPosition() == Qt::AnchorPoint::AnchorVerticalCenter )
1120 yRatio = 0.5f - heightRatio / 2.0f;
1122 yRatio = 1.0f - heightRatio;
1124 QgsDebugMsgLevel( QString(
"Qgs3DAxis: update viewport: %1 x %2 x %3 x %4" ).arg( xRatio ).arg( yRatio ).arg( widthRatio ).arg( heightRatio ), 2 );
1125 mAxisViewport->setNormalizedRect( QRectF( xRatio, yRatio, widthRatio, heightRatio ) );
1129 mTwoDLabelCamera->lens()->setOrthographicProjection(
1130 -windowWidth / 2.0f, windowWidth / 2.0f,
1131 -windowHeight / 2.0f, windowHeight / 2.0f,
1132 mTwoDLabelCamera->lens()->nearPlane(), mTwoDLabelCamera->lens()->farPlane() );
1134 updateAxisLabelPosition();
1139void Qgs3DAxis::onCameraUpdate( )
1141 Qt3DRender::QCamera *parentCamera = mCameraController->
camera();
1143 if ( parentCamera->viewVector() != mPreviousVector
1144 && !std::isnan( parentCamera->viewVector().x() )
1145 && !std::isnan( parentCamera->viewVector().y() )
1146 && !std::isnan( parentCamera->viewVector().z() ) )
1148 mPreviousVector = parentCamera->viewVector();
1149 QVector3D mainCameraShift = parentCamera->viewVector().normalized();
1150 float zy_swap = mainCameraShift.y();
1151 mainCameraShift.setY( mainCameraShift.z() );
1152 mainCameraShift.setZ( -zy_swap );
1153 mainCameraShift.setX( -mainCameraShift.x() );
1155 if ( mAxisCamera->projectionType() == Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection )
1157 mAxisCamera->setPosition( mainCameraShift );
1161 mAxisCamera->setPosition( mainCameraShift * mCylinderLength * 10.0 );
1164 if ( mAxisRoot->isEnabled() )
1166 updateAxisLabelPosition();
1171void Qgs3DAxis::updateAxisLabelPosition()
1173 if ( mTextTransformX && mTextTransformY && mTextTransformZ )
1176 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1177 mParentWindow->size() ) );
1178 onTextXChanged( mTextX->text() );
1181 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1182 mParentWindow->size() ) );
1183 onTextYChanged( mTextY->text() );
1186 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1187 mParentWindow->size() ) );
1188 onTextZChanged( mTextZ->text() );
1192void Qgs3DAxis::onTextXChanged(
const QString &text )
1194 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1195 f.setWeight( QFont::Weight::Black );
1196 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1197 mTextX->setFont( f );
1198 mTextX->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1199 mTextX->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1202void Qgs3DAxis::onTextYChanged(
const QString &text )
1204 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1205 f.setWeight( QFont::Weight::Black );
1206 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1207 mTextY->setFont( f );
1208 mTextY->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1209 mTextY->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1212void Qgs3DAxis::onTextZChanged(
const QString &text )
1214 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1215 f.setWeight( QFont::Weight::Black );
1216 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1217 mTextZ->setFont( f );
1218 mTextZ->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1219 mTextZ->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1231 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
1232 mPositionAttribute->setBuffer( mVertexBuffer );
1233 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
1234 mPositionAttribute->setVertexSize( 3 );
1235 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
1238 mGeom->addAttribute( mPositionAttribute );
1240 setInstanceCount( 1 );
1241 setIndexOffset( 0 );
1242 setFirstInstance( 0 );
1243 setPrimitiveType( Qt3DRender::QGeometryRenderer::Lines );
1244 setGeometry( mGeom );
1251 QByteArray vertexBufferData;
1252 vertexBufferData.resize( vertices.size() * 3 *
sizeof(
float ) );
1253 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
1255 for (
const QVector3D &v : std::as_const( vertices ) )
1257 rawVertexArray[idx++] = v.x();
1258 rawVertexArray[idx++] = v.y();
1259 rawVertexArray[idx++] = v.z();
1262 mVertexBuffer->setData( vertexBufferData );
1263 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)
Default 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() const
Returns camera that is being controlled.
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.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
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