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,
66 , mMapScene( mapScene )
67 , mCameraController( cameraCtrl )
70 mAxisViewport = constructAxisViewport( parent3DScene );
73 mTwoDLabelViewport = constructLabelViewport( parent3DScene, QRectF( 0.0f, 0.0f, 1.0f, 1.0f ) );
77 connect( mCanvas, &Qgs3DMapCanvas::widthChanged,
this, &Qgs3DAxis::onAxisViewportSizeUpdate );
78 connect( mCanvas, &Qgs3DMapCanvas::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 mCanvas->installEventFilter(
this );
113bool Qgs3DAxis::eventFilter( QObject *watched, QEvent *event )
115 if ( watched != mCanvas )
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() ) / mCanvas->width(),
150 (
float )mouseEvent->pos().y() / mCanvas->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 && mCanvas->cursor() == Qt::ArrowCursor )
171 mCanvas->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() &&
206 ( hits.at( i ).entity() == mCubeRoot ||
207 hits.at( i ).entity() == mAxisRoot ||
208 hits.at( i ).entity()->parent() == mCubeRoot ||
209 hits.at( i ).entity()->parent() == mAxisRoot ) )
216 if ( mLastClickedButton == Qt::NoButton )
218 if ( mHitsFound != -1 )
220 if ( mCanvas->cursor() != Qt::ArrowCursor )
222 mPreviousCursor = mCanvas->cursor();
223 mCanvas->setCursor( Qt::ArrowCursor );
228 else if ( mLastClickedButton == Qt::MouseButton::RightButton && mHitsFound != -1 )
230 displayMenuAt( mLastClickedPos );
232 else if ( mLastClickedButton == Qt::MouseButton::LeftButton )
236 if ( mHitsFound != -1 )
238 if ( hits.at( mHitsFound ).entity() == mCubeRoot || hits.at( mHitsFound ).entity()->parent() == mCubeRoot )
240 switch ( hits.at( mHitsFound ).primitiveIndex() / 2 )
244 onCameraViewChangeEast();
249 onCameraViewChangeWest();
254 onCameraViewChangeNorth();
259 onCameraViewChangeSouth();
264 onCameraViewChangeTop();
269 onCameraViewChangeBottom();
280Qt3DRender::QViewport *Qgs3DAxis::constructAxisViewport( Qt3DCore::QEntity *parent3DScene )
282 Qt3DRender::QViewport *axisViewport =
new Qt3DRender::QViewport;
286 mAxisSceneEntity =
new Qt3DCore::QEntity;
287 mAxisSceneEntity->setParent( parent3DScene );
288 mAxisSceneEntity->setObjectName(
"3DAxis_SceneEntity" );
290 mAxisSceneLayer =
new Qt3DRender::QLayer;
291 mAxisSceneLayer->setObjectName(
"3DAxis_SceneLayer" );
292 mAxisSceneLayer->setParent( mAxisSceneEntity );
293 mAxisSceneLayer->setRecursive(
true );
295 mAxisCamera =
new Qt3DRender::QCamera;
296 mAxisCamera->setParent( mAxisSceneEntity );
297 mAxisCamera->setProjectionType( mCameraController->
camera()->projectionType() );
298 mAxisCamera->lens()->setFieldOfView( mCameraController->
camera()->lens()->fieldOfView() * 0.5f );
300 mAxisCamera->setUpVector( QVector3D( 0.0f, 0.0f, 1.0f ) );
301 mAxisCamera->setViewCenter( QVector3D( 0.0f, 0.0f, 0.0f ) );
304 Qt3DRender::QLayer *axisLayer =
new Qt3DRender::QLayer;
305 axisLayer->setRecursive(
true );
306 mAxisSceneEntity->addComponent( axisLayer );
308 Qt3DRender::QLayerFilter *axisLayerFilter =
new Qt3DRender::QLayerFilter( axisViewport );
309 axisLayerFilter->addLayer( axisLayer );
311 Qt3DRender::QCameraSelector *axisCameraSelector =
new Qt3DRender::QCameraSelector;
312 axisCameraSelector->setParent( axisLayerFilter );
313 axisCameraSelector->setCamera( mAxisCamera );
317 Qt3DRender::QSortPolicy *sortPolicy =
new Qt3DRender::QSortPolicy( axisCameraSelector );
318 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes = QVector<Qt3DRender::QSortPolicy::SortType>();
319 sortTypes << Qt3DRender::QSortPolicy::BackToFront;
320 sortPolicy->setSortTypes( sortTypes );
322 Qt3DRender::QClearBuffers *clearBuffers =
new Qt3DRender::QClearBuffers( sortPolicy );
323 clearBuffers->setBuffers( Qt3DRender::QClearBuffers::DepthBuffer );
329Qt3DRender::QViewport *Qgs3DAxis::constructLabelViewport( Qt3DCore::QEntity *parent3DScene,
const QRectF &parentViewportSize )
331 Qt3DRender::QViewport *twoDViewport =
new Qt3DRender::QViewport;
333 twoDViewport->setNormalizedRect( parentViewportSize );
335 mTwoDLabelSceneEntity =
new Qt3DCore::QEntity;
336 mTwoDLabelSceneEntity->setParent( parent3DScene );
337 mTwoDLabelSceneEntity->setEnabled(
true );
339 mTwoDLabelCamera =
new Qt3DRender::QCamera;
340 mTwoDLabelCamera->setParent( mTwoDLabelSceneEntity );
341 mTwoDLabelCamera->setProjectionType( Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection );
342 mTwoDLabelCamera->lens()->setOrthographicProjection(
343 -mCanvas->width() / 2.0f, mCanvas->width() / 2.0f,
344 -mCanvas->height() / 2.0f, mCanvas->height() / 2.0f,
347 mTwoDLabelCamera->setUpVector( QVector3D( 0.0f, 0.0f, 1.0f ) );
348 mTwoDLabelCamera->setViewCenter( QVector3D( 0.0f, 0.0f, 0.0f ) );
350 mTwoDLabelCamera->setPosition( QVector3D( 0.0f, 0.0f, 100.0f ) );
352 Qt3DRender::QLayer *twoDLayer =
new Qt3DRender::QLayer;
353 twoDLayer->setRecursive(
true );
354 mTwoDLabelSceneEntity->addComponent( twoDLayer );
356 Qt3DRender::QLayerFilter *twoDLayerFilter =
new Qt3DRender::QLayerFilter( twoDViewport );
357 twoDLayerFilter->addLayer( twoDLayer );
359 Qt3DRender::QCameraSelector *twoDCameraSelector =
new Qt3DRender::QCameraSelector;
360 twoDCameraSelector->setParent( twoDLayerFilter );
361 twoDCameraSelector->setCamera( mTwoDLabelCamera );
365 Qt3DRender::QSortPolicy *sortPolicy =
new Qt3DRender::QSortPolicy( twoDCameraSelector );
366 QVector<Qt3DRender::QSortPolicy::SortType> sortTypes = QVector<Qt3DRender::QSortPolicy::SortType>();
367 sortTypes << Qt3DRender::QSortPolicy::BackToFront;
368 sortPolicy->setSortTypes( sortTypes );
370 Qt3DRender::QClearBuffers *clearBuffers =
new Qt3DRender::QClearBuffers( sortPolicy );
371 clearBuffers->setBuffers( Qt3DRender::QClearBuffers::DepthBuffer );
378 Qt3DRender::QCamera *sourceCamera, Qt3DRender::QViewport *sourceViewport,
379 Qt3DRender::QCamera *destCamera, Qt3DRender::QViewport *destViewport,
380 const QSize &destSize )
382 QVector3D destPos = sourcePos.project( sourceCamera->viewMatrix(),
383 destCamera->projectionMatrix(),
385 destViewport->normalizedRect().width() * destSize.width(),
386 destViewport->normalizedRect().height() * destSize.height() ) );
387 QPointF axisCenter = sourceViewport->normalizedRect().center();
388 QPointF labelCenter = destViewport->normalizedRect().center();
389 QVector3D viewTranslation = QVector3D( ( axisCenter - labelCenter ).x() * destSize.width(),
390 ( axisCenter - labelCenter ).y() * destSize.height(),
392 destPos -= QVector3D( labelCenter.x() * destSize.width(),
393 labelCenter.y() * destSize.height(),
395 destPos.setX( destPos.x() + viewTranslation.x() );
396 destPos.setY( destPos.y() - viewTranslation.y() );
397 destPos.setZ( 0.0f );
401 std::ostringstream os;
402 os <<
"Qgs3DAxis::from3DTo2DLabelPosition: sourcePos: " << sourcePos.toPoint()
403 <<
" with translation: " << viewTranslation.toPoint()
404 <<
" corrected to pos: " << destPos.toPoint();
410void Qgs3DAxis::setEnableCube(
bool show )
412 mCubeRoot->setEnabled( show );
415 mCubeRoot->setParent( mAxisSceneEntity );
419 mCubeRoot->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
423void Qgs3DAxis::setEnableAxis(
bool show )
425 mAxisRoot->setEnabled( show );
428 mAxisRoot->setParent( mAxisSceneEntity );
432 mAxisRoot->setParent(
static_cast<Qt3DCore::QEntity *
>(
nullptr ) );
435 mTextX->setEnabled( show );
436 mTextY->setEnabled( show );
437 mTextZ->setEnabled( show );
440void Qgs3DAxis::createAxisScene()
442 if ( mAxisRoot ==
nullptr || mCubeRoot ==
nullptr )
444 mAxisRoot =
new Qt3DCore::QEntity;
445 mAxisRoot->setParent( mAxisSceneEntity );
446 mAxisRoot->setObjectName(
"3DAxis_AxisRoot" );
447 mAxisRoot->addComponent( mAxisSceneLayer );
449 createAxis( Qt::Axis::XAxis );
450 createAxis( Qt::Axis::YAxis );
451 createAxis( Qt::Axis::ZAxis );
453 mCubeRoot =
new Qt3DCore::QEntity;
454 mCubeRoot->setParent( mAxisSceneEntity );
455 mCubeRoot->setObjectName(
"3DAxis_CubeRoot" );
456 mCubeRoot->addComponent( mAxisSceneLayer );
465 mAxisSceneEntity->setEnabled(
false );
466 setEnableAxis(
false );
467 setEnableCube(
false );
471 mAxisSceneEntity->setEnabled(
true );
474 setEnableCube(
false );
475 setEnableAxis(
true );
477 const QList< Qgis::CrsAxisDirection > axisDirections = mCrs.
axisOrdering();
479 if ( axisDirections.length() > 0 )
482 mTextY->setText(
"X?" );
484 if ( axisDirections.length() > 1 )
487 mTextY->setText(
"Y?" );
489 if ( axisDirections.length() > 2 )
492 mTextZ->setText( QStringLiteral(
"up" ) );
496 setEnableCube(
true );
497 setEnableAxis(
false );
501 setEnableCube(
false );
502 setEnableAxis(
true );
503 mTextX->setText(
"X?" );
504 mTextY->setText(
"Y?" );
505 mTextZ->setText(
"Z?" );
508 updateAxisLabelPosition();
512void Qgs3DAxis::createKeyboardShortCut()
517 QWidget *mapCanvas =
dynamic_cast<QWidget *
>( eng->parent() );
518 if ( mapCanvas ==
nullptr )
524 QShortcut *shortcutHome =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_1 ), mapCanvas );
525 connect( shortcutHome, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeHome();} );
527 QShortcut *shortcutTop =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_5 ), mapCanvas );
528 connect( shortcutTop, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeTop();} );
530 QShortcut *shortcutNorth =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_8 ), mapCanvas );
531 connect( shortcutNorth, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeNorth();} );
533 QShortcut *shortcutEast =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_6 ), mapCanvas );
534 connect( shortcutEast, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeEast();} );
536 QShortcut *shortcutSouth =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_2 ), mapCanvas );
537 connect( shortcutSouth, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeSouth();} );
539 QShortcut *shortcutWest =
new QShortcut( QKeySequence( Qt::CTRL + Qt::Key_4 ), mapCanvas );
540 connect( shortcutWest, &QShortcut::activated,
this, [
this]( ) {onCameraViewChangeWest();} );
545void Qgs3DAxis::createMenu()
550 QAction *typeOffAct =
new QAction( tr(
"&Off" ), mMenu );
551 typeOffAct->setCheckable(
true );
552 typeOffAct->setStatusTip( tr(
"Disable 3D axis" ) );
556 typeOffAct->setChecked(
true );
559 QAction *typeCrsAct =
new QAction( tr(
"Coordinate Reference &System" ), mMenu );
560 typeCrsAct->setCheckable(
true );
561 typeCrsAct->setStatusTip( tr(
"Coordinate Reference System 3D axis" ) );
565 typeCrsAct->setChecked(
true );
568 QAction *typeCubeAct =
new QAction( tr(
"&Cube" ), mMenu );
569 typeCubeAct->setCheckable(
true );
570 typeCubeAct->setStatusTip( tr(
"Cube 3D axis" ) );
574 typeCubeAct->setChecked(
true );
577 QActionGroup *typeGroup =
new QActionGroup( mMenu );
578 typeGroup->addAction( typeOffAct );
579 typeGroup->addAction( typeCrsAct );
580 typeGroup->addAction( typeCubeAct );
586 QMenu *typeMenu =
new QMenu( QStringLiteral(
"Axis Type" ), mMenu );
587 Q_ASSERT( typeMenu );
588 typeMenu->addAction( typeOffAct );
589 typeMenu->addAction( typeCrsAct );
590 typeMenu->addAction( typeCubeAct );
591 mMenu->addMenu( typeMenu );
594 QAction *hPosLeftAct =
new QAction( tr(
"&Left" ), mMenu );
595 hPosLeftAct->setCheckable(
true );
599 hPosLeftAct->setChecked(
true );
602 QAction *hPosMiddleAct =
new QAction( tr(
"&Center" ), mMenu );
603 hPosMiddleAct->setCheckable(
true );
607 hPosMiddleAct->setChecked(
true );
610 QAction *hPosRightAct =
new QAction( tr(
"&Right" ), mMenu );
611 hPosRightAct->setCheckable(
true );
615 hPosRightAct->setChecked(
true );
618 QActionGroup *hPosGroup =
new QActionGroup( mMenu );
619 hPosGroup->addAction( hPosLeftAct );
620 hPosGroup->addAction( hPosMiddleAct );
621 hPosGroup->addAction( hPosRightAct );
623 connect( hPosLeftAct, &QAction::triggered,
this, [
this](
bool ) {onAxisHorizPositionChanged( Qt::AnchorPoint::AnchorLeft );} );
624 connect( hPosMiddleAct, &QAction::triggered,
this, [
this](
bool ) {onAxisHorizPositionChanged( Qt::AnchorPoint::AnchorHorizontalCenter );} );
625 connect( hPosRightAct, &QAction::triggered,
this, [
this](
bool ) {onAxisHorizPositionChanged( Qt::AnchorPoint::AnchorRight );} );
627 QMenu *horizPosMenu =
new QMenu( QStringLiteral(
"Horizontal Position" ), mMenu );
628 horizPosMenu->addAction( hPosLeftAct );
629 horizPosMenu->addAction( hPosMiddleAct );
630 horizPosMenu->addAction( hPosRightAct );
631 mMenu->addMenu( horizPosMenu );
634 QAction *vPosTopAct =
new QAction( tr(
"&Top" ), mMenu );
635 vPosTopAct->setCheckable(
true );
639 vPosTopAct->setChecked(
true );
642 QAction *vPosMiddleAct =
new QAction( tr(
"&Middle" ), mMenu );
643 vPosMiddleAct->setCheckable(
true );
647 vPosMiddleAct->setChecked(
true );
650 QAction *vPosBottomAct =
new QAction( tr(
"&Bottom" ), mMenu );
651 vPosBottomAct->setCheckable(
true );
655 vPosBottomAct->setChecked(
true );
658 QActionGroup *vPosGroup =
new QActionGroup( mMenu );
659 vPosGroup->addAction( vPosTopAct );
660 vPosGroup->addAction( vPosMiddleAct );
661 vPosGroup->addAction( vPosBottomAct );
663 connect( vPosTopAct, &QAction::triggered,
this, [
this](
bool ) {onAxisVertPositionChanged( Qt::AnchorPoint::AnchorTop );} );
664 connect( vPosMiddleAct, &QAction::triggered,
this, [
this](
bool ) {onAxisVertPositionChanged( Qt::AnchorPoint::AnchorVerticalCenter );} );
665 connect( vPosBottomAct, &QAction::triggered,
this, [
this](
bool ) {onAxisVertPositionChanged( Qt::AnchorPoint::AnchorBottom );} );
667 QMenu *vertPosMenu =
new QMenu( QStringLiteral(
"Vertical Position" ), mMenu );
668 vertPosMenu->addAction( vPosTopAct );
669 vertPosMenu->addAction( vPosMiddleAct );
670 vertPosMenu->addAction( vPosBottomAct );
671 mMenu->addMenu( vertPosMenu );
674 QAction *viewHomeAct =
new QAction( tr(
"&Home" ) +
"\t Ctrl+1", mMenu );
675 QAction *viewTopAct =
new QAction( tr(
"&Top" ) +
"\t Ctrl+5", mMenu );
676 QAction *viewNorthAct =
new QAction( tr(
"&North" ) +
"\t Ctrl+8", mMenu );
677 QAction *viewEastAct =
new QAction( tr(
"&East" ) +
"\t Ctrl+6", mMenu );
678 QAction *viewSouthAct =
new QAction( tr(
"&South" ) +
"\t Ctrl+2", mMenu );
679 QAction *viewWestAct =
new QAction( tr(
"&West" ) +
"\t Ctrl+4", mMenu );
680 QAction *viewBottomAct =
new QAction( tr(
"&Bottom" ), mMenu );
682 connect( viewHomeAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeHome );
683 connect( viewTopAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeTop );
684 connect( viewNorthAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeNorth );
685 connect( viewEastAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeEast );
686 connect( viewSouthAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeSouth );
687 connect( viewWestAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeWest );
688 connect( viewBottomAct, &QAction::triggered,
this, &Qgs3DAxis::onCameraViewChangeBottom );
690 QMenu *viewMenu =
new QMenu( QStringLiteral(
"Camera View" ), mMenu );
691 viewMenu->addAction( viewHomeAct );
692 viewMenu->addAction( viewTopAct );
693 viewMenu->addAction( viewNorthAct );
694 viewMenu->addAction( viewEastAct );
695 viewMenu->addAction( viewSouthAct );
696 viewMenu->addAction( viewWestAct );
697 viewMenu->addAction( viewBottomAct );
698 mMenu->addMenu( viewMenu );
704void Qgs3DAxis::hideMenu()
706 if ( mMenu && mMenu->isVisible() )
710void Qgs3DAxis::displayMenuAt(
const QPoint &sourcePos )
712 if ( mMenu ==
nullptr )
717 mMenu->popup( mCanvas->mapToGlobal( sourcePos ) );
727void Qgs3DAxis::onAxisHorizPositionChanged( Qt::AnchorPoint pos )
734void Qgs3DAxis::onAxisVertPositionChanged( Qt::AnchorPoint pos )
741void Qgs3DAxis::onCameraViewChange(
float pitch,
float yaw )
744 double elevation = 0.0;
748 QVector3D camPos = mCameraController->
camera()->position();
749 QgsRayCastingUtils::Ray3D ray( camPos, pos.
toVector3D() - camPos, mCameraController->
camera()->farPlane() );
750 const QVector<QgsRayCastingUtils::RayHit> hits = mMapScene->
terrainEntity()->rayIntersection( ray, QgsRayCastingUtils::RayCastContext() );
751 if ( !hits.isEmpty() )
753 elevation = hits.at( 0 ).pos.y();
754 QgsDebugMsgLevel( QString(
"Computed elevation from terrain: %1" ).arg( elevation ), 2 );
768void Qgs3DAxis::createCube( )
770 QVector3D minPos = QVector3D( -mCylinderLength * 0.5f, -mCylinderLength * 0.5f, -mCylinderLength * 0.5f );
773 Qt3DCore::QEntity *cubeLineEntity =
new Qt3DCore::QEntity( mCubeRoot );
774 cubeLineEntity->setObjectName(
"3DAxis_cubeline" );
776 QgsAABB box =
QgsAABB( -mCylinderLength * 0.5f, -mCylinderLength * 0.5f, -mCylinderLength * 0.5f,
777 mCylinderLength * 0.5f, mCylinderLength * 0.5f, mCylinderLength * 0.5f );
779 cubeLineEntity->addComponent( cubeLine );
781 Qt3DExtras::QPhongMaterial *cubeLineMaterial =
new Qt3DExtras::QPhongMaterial;
782 cubeLineMaterial->setAmbient( Qt::white );
783 cubeLineEntity->addComponent( cubeLineMaterial );
786 Qt3DExtras::QCuboidMesh *cubeMesh =
new Qt3DExtras::QCuboidMesh;
787 cubeMesh->setObjectName(
"3DAxis_cubemesh" );
788 cubeMesh->setXExtent( mCylinderLength );
789 cubeMesh->setYExtent( mCylinderLength );
790 cubeMesh->setZExtent( mCylinderLength );
791 mCubeRoot->addComponent( cubeMesh );
793 Qt3DExtras::QPhongMaterial *cubeMaterial =
new Qt3DExtras::QPhongMaterial( mCubeRoot );
794 cubeMaterial->setAmbient( QColor( 100, 100, 100, 50 ) );
795 cubeMaterial->setShininess( 100 );
796 mCubeRoot->addComponent( cubeMaterial );
798 Qt3DCore::QTransform *cubeTransform =
new Qt3DCore::QTransform;
799 QMatrix4x4 transformMatrixcube;
801 transformMatrixcube.translate( minPos + QVector3D( mCylinderLength * 0.5f, mCylinderLength * 0.5f, mCylinderLength * 0.5f ) );
802 cubeTransform->setMatrix( transformMatrixcube );
803 mCubeRoot->addComponent( cubeTransform );
807 int fontSize = 0.75 * mFontSize;
808 float textHeight = fontSize * 1.5f;
810 QFont f = QFontDatabase::systemFont( QFontDatabase::FixedFont );
811 f.setPointSize( fontSize );
812 f.setWeight( QFont::Weight::Black );
815 text = QStringLiteral(
"top" );
816 textWidth = text.length() * fontSize * 0.75f;
817 QVector3D translation = minPos + QVector3D(
818 mCylinderLength * 0.5f - textWidth / 2.0f,
819 mCylinderLength * 0.5f - textHeight / 2.0f,
820 mCylinderLength * 1.01f );
822 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
826 text = QStringLiteral(
"btm" );
827 textWidth = text.length() * fontSize * 0.75f;
828 QVector3D translation = minPos + QVector3D(
829 mCylinderLength * 0.5f - textWidth / 2.0f,
830 mCylinderLength * 0.5f + textHeight / 2.0f,
831 -mCylinderLength * 0.01f );
833 rotation.rotate( 180.0f, QVector3D( 1.0f, 0.0f, 0.0f ).normalized() );
834 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
838 text = QStringLiteral(
"west" );
839 textWidth = text.length() * fontSize * 0.75f;
840 QVector3D translation = minPos + QVector3D(
841 - mCylinderLength * 0.01f,
842 mCylinderLength * 0.5f + textWidth / 2.0f,
843 mCylinderLength * 0.5f - textHeight / 2.0f );
845 rotation.rotate( 90.0f, QVector3D( 0.0f, -1.0f, 0.0f ).normalized() );
846 rotation.rotate( 90.0f, QVector3D( 0.0f, 0.0f, -1.0f ).normalized() );
847 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
851 text = QStringLiteral(
"east" );
852 textWidth = text.length() * fontSize * 0.75f;
853 QVector3D translation = minPos + QVector3D(
854 mCylinderLength * 1.01f,
855 mCylinderLength * 0.5f - textWidth / 2.0f,
856 mCylinderLength * 0.5f - textHeight / 2.0f );
858 rotation.rotate( 90.0f, QVector3D( 0.0f, 1.0f, 0.0f ).normalized() );
859 rotation.rotate( 90.0f, QVector3D( 0.0f, 0.0f, 1.0f ).normalized() );
860 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
864 text = QStringLiteral(
"south" );
865 textWidth = text.length() * fontSize * 0.75f;
866 QVector3D translation = minPos + QVector3D(
867 mCylinderLength * 0.5f - textWidth / 2.0f,
868 - mCylinderLength * 0.01f,
869 mCylinderLength * 0.5f - textHeight / 2.0f );
871 rotation.rotate( 90.0f, QVector3D( 1.0f, 0.0f, 0.0f ).normalized() );
872 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
876 text = QStringLiteral(
"north" );
877 textWidth = text.length() * fontSize * 0.75f;
878 QVector3D translation = minPos + QVector3D(
879 mCylinderLength * 0.5f + textWidth / 2.0f,
880 mCylinderLength * 1.01f,
881 mCylinderLength * 0.5f - textHeight / 2.0f );
883 rotation.rotate( 90.0f, QVector3D( -1.0f, 0.0f, 0.0f ).normalized() );
884 rotation.rotate( 180.0f, QVector3D( 0.0f, 0.0f, 1.0f ).normalized() );
885 mCubeLabels << addCubeText( text, textHeight, textWidth, f, rotation, translation );
888 for ( Qt3DExtras::QText2DEntity *l : std::as_const( mCubeLabels ) )
890 l->setParent( mCubeRoot );
894Qt3DExtras::QText2DEntity *Qgs3DAxis::addCubeText(
const QString &text,
float textHeight,
float textWidth,
const QFont &f,
const QMatrix4x4 &rotation,
const QVector3D &translation )
896 Qt3DExtras::QText2DEntity *textEntity =
new Qt3DExtras::QText2DEntity;
897 textEntity->setObjectName(
"3DAxis_cube_label_" + text );
898 textEntity->setFont( f );
899 textEntity->setHeight( textHeight );
900 textEntity->setWidth( textWidth );
901 textEntity->setColor( QColor( 192, 192, 192 ) );
902 textEntity->setText( text );
904 Qt3DCore::QTransform *textFrontTransform =
new Qt3DCore::QTransform();
905 textFrontTransform->setMatrix( rotation );
906 textFrontTransform->setTranslation( translation );
907 textEntity->addComponent( textFrontTransform );
912void Qgs3DAxis::createAxis( Qt::Axis axisType )
914 float cylinderRadius = 0.05f * mCylinderLength;
915 float coneLength = 0.3f * mCylinderLength;
916 float coneBottomRadius = 0.1f * mCylinderLength;
918 QQuaternion rotation;
921 Qt3DExtras::QText2DEntity *text =
nullptr;
922 Qt3DCore::QTransform *textTransform =
nullptr;
927 case Qt::Axis::XAxis:
928 mTextX =
new Qt3DExtras::QText2DEntity( );
929 mTextX->setParent( mTwoDLabelSceneEntity );
930 connect( mTextX, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextXChanged );
931 mTextTransformX =
new Qt3DCore::QTransform();
932 mTextCoordX = QVector3D( mCylinderLength + coneLength / 2.0f, 0.0f, 0.0f );
934 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 1.0f ), -90.0f );
937 textTransform = mTextTransformX;
938 name =
"3DAxis_axisX";
941 case Qt::Axis::YAxis:
942 mTextY =
new Qt3DExtras::QText2DEntity( );
943 mTextY->setParent( mTwoDLabelSceneEntity );
944 connect( mTextY, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextYChanged );
945 mTextTransformY =
new Qt3DCore::QTransform();
946 mTextCoordY = QVector3D( 0.0f, mCylinderLength + coneLength / 2.0f, 0.0f );
948 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 0.0f, 0.0f, 0.0f ), 0.0f );
951 textTransform = mTextTransformY;
952 name =
"3DAxis_axisY";
955 case Qt::Axis::ZAxis:
956 mTextZ =
new Qt3DExtras::QText2DEntity( );
957 mTextZ->setParent( mTwoDLabelSceneEntity );
958 connect( mTextZ, &Qt3DExtras::QText2DEntity::textChanged,
this, &Qgs3DAxis::onTextZChanged );
959 mTextTransformZ =
new Qt3DCore::QTransform();
960 mTextCoordZ = QVector3D( 0.0f, 0.0f, mCylinderLength + coneLength / 2.0f );
962 rotation = QQuaternion::fromAxisAndAngle( QVector3D( 1.0f, 0.0f, 0.0f ), 90.0f );
965 textTransform = mTextTransformZ;
966 name =
"3DAxis_axisZ";
974 Qt3DCore::QEntity *cylinder =
new Qt3DCore::QEntity( mAxisRoot );
975 cylinder->setObjectName( name );
977 Qt3DExtras::QCylinderMesh *cylinderMesh =
new Qt3DExtras::QCylinderMesh;
978 cylinderMesh->setRadius( cylinderRadius );
979 cylinderMesh->setLength( mCylinderLength );
980 cylinderMesh->setRings( 10 );
981 cylinderMesh->setSlices( 4 );
982 cylinder->addComponent( cylinderMesh );
984 Qt3DExtras::QPhongMaterial *cylinderMaterial =
new Qt3DExtras::QPhongMaterial( cylinder );
985 cylinderMaterial->setAmbient( color );
986 cylinderMaterial->setShininess( 0 );
987 cylinder->addComponent( cylinderMaterial );
989 Qt3DCore::QTransform *cylinderTransform =
new Qt3DCore::QTransform;
990 QMatrix4x4 transformMatrixCylinder;
991 transformMatrixCylinder.rotate( rotation );
992 transformMatrixCylinder.translate( QVector3D( 0.0f, mCylinderLength / 2.0f, 0.0f ) );
993 cylinderTransform->setMatrix( transformMatrixCylinder );
994 cylinder->addComponent( cylinderTransform );
997 Qt3DCore::QEntity *coneEntity =
new Qt3DCore::QEntity( mAxisRoot );
998 coneEntity->setObjectName( name );
999 Qt3DExtras::QConeMesh *coneMesh =
new Qt3DExtras::QConeMesh;
1000 coneMesh->setLength( coneLength );
1001 coneMesh->setBottomRadius( coneBottomRadius );
1002 coneMesh->setTopRadius( 0.0f );
1003 coneMesh->setRings( 10 );
1004 coneMesh->setSlices( 4 );
1005 coneEntity->addComponent( coneMesh );
1007 Qt3DExtras::QPhongMaterial *coneMaterial =
new Qt3DExtras::QPhongMaterial( coneEntity );
1008 coneMaterial->setAmbient( color );
1009 coneMaterial->setShininess( 0 );
1010 coneEntity->addComponent( coneMaterial );
1012 Qt3DCore::QTransform *coneTransform =
new Qt3DCore::QTransform;
1013 QMatrix4x4 transformMatrixCone;
1014 transformMatrixCone.rotate( rotation );
1015 transformMatrixCone.translate( QVector3D( 0.0f, mCylinderLength, 0.0f ) );
1016 coneTransform->setMatrix( transformMatrixCone );
1017 coneEntity->addComponent( coneTransform );
1020 text->setColor( QColor( 192, 192, 192, 192 ) );
1021 text->addComponent( textTransform );
1027 onAxisViewportSizeUpdate();
1030void Qgs3DAxis::onAxisViewportSizeUpdate(
int )
1034 double windowWidth = ( double )mCanvas->width();
1035 double windowHeight = ( double )mCanvas->height();
1040 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window w/h: %1px / %2px" )
1041 .arg( windowWidth ).arg( windowHeight ), 2 );
1042 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window physicalDpi %1 (%2, %3)" )
1043 .arg( mCanvas->screen()->physicalDotsPerInch() )
1044 .arg( mCanvas->screen()->physicalDotsPerInchX() )
1045 .arg( mCanvas->screen()->physicalDotsPerInchY() ), 2 );
1046 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window logicalDotsPerInch %1 (%2, %3)" )
1047 .arg( mCanvas->screen()->logicalDotsPerInch() )
1048 .arg( mCanvas->screen()->logicalDotsPerInchX() )
1049 .arg( mCanvas->screen()->logicalDotsPerInchY() ), 2 );
1051 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate window pixel ratio %1" )
1052 .arg( mCanvas->screen()->devicePixelRatio() ), 2 );
1063 double defaultViewportPixelSize = ( ( double )settings.
defaultViewportSize() / 25.4 ) * 92.0;
1067 double viewportPixelSize = defaultViewportPixelSize + ( ( double )settings.
defaultViewportSize() / 25.4 )
1068 * ( mCanvas->screen()->physicalDotsPerInch() - 92.0 ) * 0.7;
1069 QgsDebugMsgLevel( QString(
"onAxisViewportSizeUpdate viewportPixelSize %1" ).arg( viewportPixelSize ), 2 );
1070 double widthRatio = viewportPixelSize / windowWidth;
1071 double heightRatio = widthRatio * windowWidth / windowHeight;
1073 QgsDebugMsgLevel( QString(
"3DAxis viewport ratios width: %1% / height: %2%" ).arg( widthRatio ).arg( heightRatio ), 2 );
1075 if ( heightRatio * windowHeight < viewportPixelSize )
1077 heightRatio = viewportPixelSize / windowHeight;
1078 widthRatio = heightRatio * windowHeight / windowWidth;
1079 QgsDebugMsgLevel( QString(
"3DAxis viewport, height too small, ratios adjusted to width: %1% / height: %2%" ).arg( widthRatio ).arg( heightRatio ), 2 );
1084 QgsDebugMsgLevel(
"viewport takes too much place into the 3d view, disabling it", 2 );
1086 mAxisViewport->setEnabled(
false );
1087 setEnableCube(
false );
1088 setEnableAxis(
false );
1093 mAxisScaleFactor = viewportPixelSize / defaultViewportPixelSize;
1094 QgsDebugMsgLevel( QString(
"3DAxis viewport mAxisScaleFactor %1" ).arg( mAxisScaleFactor ), 2 );
1096 if ( ! mAxisViewport->isEnabled() )
1099 setEnableAxis(
true );
1101 setEnableCube(
true );
1103 mAxisViewport->setEnabled(
true );
1105 float xRatio = 1.0f;
1106 float yRatio = 1.0f;
1110 xRatio = 0.5f - widthRatio / 2.0f;
1112 xRatio = 1.0f - widthRatio;
1116 else if ( settings.
verticalPosition() == Qt::AnchorPoint::AnchorVerticalCenter )
1117 yRatio = 0.5f - heightRatio / 2.0f;
1119 yRatio = 1.0f - heightRatio;
1121 QgsDebugMsgLevel( QString(
"Qgs3DAxis: update viewport: %1 x %2 x %3 x %4" ).arg( xRatio ).arg( yRatio ).arg( widthRatio ).arg( heightRatio ), 2 );
1122 mAxisViewport->setNormalizedRect( QRectF( xRatio, yRatio, widthRatio, heightRatio ) );
1126 mTwoDLabelCamera->lens()->setOrthographicProjection(
1127 -windowWidth / 2.0f, windowWidth / 2.0f,
1128 -windowHeight / 2.0f, windowHeight / 2.0f,
1129 mTwoDLabelCamera->lens()->nearPlane(), mTwoDLabelCamera->lens()->farPlane() );
1131 updateAxisLabelPosition();
1136void Qgs3DAxis::onCameraUpdate( )
1138 Qt3DRender::QCamera *parentCamera = mCameraController->
camera();
1140 if ( parentCamera->viewVector() != mPreviousVector
1141 && !std::isnan( parentCamera->viewVector().x() )
1142 && !std::isnan( parentCamera->viewVector().y() )
1143 && !std::isnan( parentCamera->viewVector().z() ) )
1145 mPreviousVector = parentCamera->viewVector();
1146 QVector3D mainCameraShift = parentCamera->viewVector().normalized();
1147 float zy_swap = mainCameraShift.y();
1148 mainCameraShift.setY( mainCameraShift.z() );
1149 mainCameraShift.setZ( -zy_swap );
1150 mainCameraShift.setX( -mainCameraShift.x() );
1152 if ( mAxisCamera->projectionType() == Qt3DRender::QCameraLens::ProjectionType::OrthographicProjection )
1154 mAxisCamera->setPosition( mainCameraShift );
1158 mAxisCamera->setPosition( mainCameraShift * mCylinderLength * 10.0 );
1161 if ( mAxisRoot->isEnabled() )
1163 updateAxisLabelPosition();
1168void Qgs3DAxis::updateAxisLabelPosition()
1170 if ( mTextTransformX && mTextTransformY && mTextTransformZ )
1173 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1174 mCanvas->size() ) );
1175 onTextXChanged( mTextX->text() );
1178 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1179 mCanvas->size() ) );
1180 onTextYChanged( mTextY->text() );
1183 mAxisViewport, mTwoDLabelCamera, mTwoDLabelViewport,
1184 mCanvas->size() ) );
1185 onTextZChanged( mTextZ->text() );
1189void Qgs3DAxis::onTextXChanged(
const QString &text )
1191 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1192 f.setWeight( QFont::Weight::Black );
1193 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1194 mTextX->setFont( f );
1195 mTextX->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1196 mTextX->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1199void Qgs3DAxis::onTextYChanged(
const QString &text )
1201 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1202 f.setWeight( QFont::Weight::Black );
1203 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1204 mTextY->setFont( f );
1205 mTextY->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1206 mTextY->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1209void Qgs3DAxis::onTextZChanged(
const QString &text )
1211 QFont f = QFont(
"monospace", mAxisScaleFactor * mFontSize );
1212 f.setWeight( QFont::Weight::Black );
1213 f.setStyleStrategy( QFont::StyleStrategy::ForceOutline );
1214 mTextZ->setFont( f );
1215 mTextZ->setWidth( mAxisScaleFactor * mFontSize * text.length() );
1216 mTextZ->setHeight( mAxisScaleFactor * mFontSize * 1.5f );
1228 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
1229 mPositionAttribute->setBuffer( mVertexBuffer );
1230 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
1231 mPositionAttribute->setVertexSize( 3 );
1232 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
1235 mGeom->addAttribute( mPositionAttribute );
1237 setInstanceCount( 1 );
1238 setIndexOffset( 0 );
1239 setFirstInstance( 0 );
1240 setPrimitiveType( Qt3DRender::QGeometryRenderer::Lines );
1241 setGeometry( mGeom );
1248 QByteArray vertexBufferData;
1249 vertexBufferData.resize( vertices.size() * 3 *
sizeof(
float ) );
1250 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
1252 for (
const QVector3D &v : std::as_const( vertices ) )
1254 rawVertexArray[idx++] = v.x();
1255 rawVertexArray[idx++] = v.y();
1256 rawVertexArray[idx++] = v.z();
1259 mVertexBuffer->setData( vertexBufferData );
1260 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.
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.
Qgs3DAxis(Qgs3DMapCanvas *canvas, Qt3DCore::QEntity *parent3DScene, Qgs3DMapScene *mapScene, QgsCameraController *camera, Qgs3DMapSettings *map)
Default Qgs3DAxis constructor.
Qt3DRender::QFrameGraphNode * activeFrameGraph() const
Returns the node of the active frame graph.
QgsAbstract3DEngine * engine() const
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