Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3d] Measurement tool #30299

Merged
merged 59 commits into from
Jul 8, 2019
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
c065e9e
Add measurement tool bar.
ismailsunni Jun 10, 2019
ae12659
Add class for measure line.
ismailsunni Jun 10, 2019
a4922ad
Get coordinate of clicked point.
ismailsunni Jun 10, 2019
743bfc8
Add clicked point to string line.
ismailsunni Jun 13, 2019
b094e7f
Store clicekd points to layer.
ismailsunni Jun 13, 2019
1b76805
Try to render the measurement line.
ismailsunni Jun 13, 2019
1f9fcda
Render the measurement line (with some problems).
ismailsunni Jun 14, 2019
a132e75
Store points in vector.
ismailsunni Jun 16, 2019
4ca01d1
Make identify and measure tool exlusive to each other.
ismailsunni Jun 16, 2019
a928b61
Add measurement dialog.
ismailsunni Jun 16, 2019
20836bf
Fix only one action must active.
ismailsunni Jun 16, 2019
36116e2
Some code suggestion from Martin.
ismailsunni Jun 17, 2019
6e7fb1c
Revert code to show the line.
ismailsunni Jun 20, 2019
f583b53
Show segment length and the total.
ismailsunni Jun 20, 2019
08affad
Implement close dialog means restart 3d measurement.
ismailsunni Jun 20, 2019
64a67b5
Add new button.
ismailsunni Jun 20, 2019
495b8ad
Add unit combo box.
ismailsunni Jun 20, 2019
d78c67d
Fix shadowing private member of class.
ismailsunni Jun 20, 2019
6b45df3
Add slot to combo box unit changes.
ismailsunni Jun 20, 2019
893934e
Hide ellipsoid and cartesian radio button.
ismailsunni Jun 20, 2019
73fce21
Add measure line for QgsPoint.
ismailsunni Jun 20, 2019
dd08644
Add unit changes feature.
ismailsunni Jun 20, 2019
8c134ec
Add help (pointed to 2D measurement tool).
ismailsunni Jun 20, 2019
4222bb2
Add finish measurement using right click.
ismailsunni Jun 20, 2019
7313b7a
Remove keypress event, it does not make sense.
ismailsunni Jun 20, 2019
54bf924
Add remove-last-point with middle button.
ismailsunni Jun 20, 2019
9ab0961
Add crsChanged event.
ismailsunni Jun 20, 2019
2299ef9
Remove confusing tooltip.
ismailsunni Jun 20, 2019
37851df
Add pan (camera control) action tool for clear state of 3d map tool.
ismailsunni Jun 20, 2019
1c4b7a1
Change 3D identify tool cursor.
ismailsunni Jun 20, 2019
52ecd33
Fix distance 2D to 3D.
ismailsunni Jun 23, 2019
96b5e97
Remove unclear method.
ismailsunni Jun 23, 2019
1dc3c0b
Add unit test for measureLine3D.
ismailsunni Jun 23, 2019
78d59b0
Add header.
ismailsunni Jun 23, 2019
d4c13b8
Add 3D measurement setting.
ismailsunni Jun 23, 2019
8550f2c
Make extra 3D renderers refresh the scene when they are updated
wonder-sk Jun 24, 2019
1dd6aad
Set Altitude clamping to absolute.
ismailsunni Jun 28, 2019
dd42b0f
Remove options for 3D measurement line.
ismailsunni Jun 28, 2019
604fa07
Remove help button in 3D measurement dialog.
ismailsunni Jun 28, 2019
aea2b21
Merge duplicate code for handle clicked position.
ismailsunni Jun 28, 2019
e3fe10d
Use color for 3d measure line from 2d one.
ismailsunni Jun 28, 2019
070e395
Remove unneeded reimplementation method.
ismailsunni Jun 28, 2019
d733929
Remove 2D canvas reference.
ismailsunni Jun 29, 2019
5e1cbd0
Unify update measurement layer.
ismailsunni Jun 30, 2019
f77eb90
Create measurement layer once.
ismailsunni Jun 30, 2019
f0003a7
Use data provider to change the geometry.
ismailsunni Jun 30, 2019
e959eff
Add length3D for QgsLineString.
ismailsunni Jun 30, 2019
1c3cdb2
Simplify distance calculation and presentation. Remove QgsDistanceAre…
ismailsunni Jun 30, 2019
a9d5338
Descaled z value based on the terrain vertical scale.
ismailsunni Jun 30, 2019
6a1aeeb
Remove line when tool is deactivated.
ismailsunni Jun 30, 2019
4b3eacc
Enable changing the line color from setting, but after re-activation.
ismailsunni Jun 30, 2019
fd02211
Update color of measurement line after saving option.
ismailsunni Jun 30, 2019
99ccf83
Remove debug message.
ismailsunni Jun 30, 2019
de85302
Remove 3D length calculation from distancearea.
ismailsunni Jun 30, 2019
06493ef
Merge remote-tracking branch 'origin/master' into measurement-tool
ismailsunni Jun 30, 2019
d02d621
Handle 2D case for length3D, more unit test, and docstring.
ismailsunni Jul 1, 2019
109afac
Fix typos.
ismailsunni Jul 1, 2019
cea418a
Addressing Martin's and Nyall's review.
ismailsunni Jul 2, 2019
b2f9093
Remove setMeasurement to avoid confussion.
ismailsunni Jul 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions python/core/auto_generated/geometry/qgslinestring.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,14 @@ segment in the line.

virtual double length() const;


double length3D() const;
%Docstring
Returns the length in 3D world of the line string.
If it is not a 3D line string, return its 2D length.

.. seealso:: :py:func:`length`
%End
virtual QgsPoint startPoint() const;

virtual QgsPoint endPoint() const;
Expand Down
59 changes: 39 additions & 20 deletions src/3d/qgs3dmapscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,11 @@ Qgs3DMapScene::Qgs3DMapScene( const Qgs3DMapSettings &map, QgsAbstract3DEngine *
connect( &map, &Qgs3DMapSettings::terrainShadingChanged, this, &Qgs3DMapScene::createTerrain );
connect( &map, &Qgs3DMapSettings::pointLightsChanged, this, &Qgs3DMapScene::updateLights );
connect( &map, &Qgs3DMapSettings::fieldOfViewChanged, this, &Qgs3DMapScene::updateCameraLens );
connect( &map, &Qgs3DMapSettings::renderersChanged, this, &Qgs3DMapScene::onRenderersChanged );

// create entities of renderers

Q_FOREACH ( const QgsAbstract3DRenderer *renderer, map.renderers() )
{
Qt3DCore::QEntity *newEntity = renderer->createEntity( map );
newEntity->setParent( this );
}
onRenderersChanged();

// listen to changes of layers in order to add/remove 3D renderer entities
connect( &map, &Qgs3DMapSettings::layersChanged, this, &Qgs3DMapScene::onLayersChanged );
Expand Down Expand Up @@ -415,9 +412,6 @@ void Qgs3DMapScene::onBackgroundColorChanged()

void Qgs3DMapScene::onLayerEntityPickEvent( Qt3DRender::QPickEvent *event )
{
if ( event->button() != Qt3DRender::QPickEvent::LeftButton )
return;

Qt3DRender::QPickTriangleEvent *triangleEvent = qobject_cast<Qt3DRender::QPickTriangleEvent *>( event );
if ( !triangleEvent )
return;
Expand Down Expand Up @@ -456,7 +450,7 @@ void Qgs3DMapScene::onLayerEntityPickEvent( Qt3DRender::QPickEvent *event )
break;
}
}
pickHandler->handlePickOnVectorLayer( vlayer, fid, event->worldIntersection() );
pickHandler->handlePickOnVectorLayer( vlayer, fid, event->worldIntersection(), event );
}

}
Expand Down Expand Up @@ -497,6 +491,26 @@ void Qgs3DMapScene::updateCameraLens()
onCameraChanged();
}

void Qgs3DMapScene::onRenderersChanged()
{
// remove entities (if any)
qDeleteAll( mRenderersEntities.values() );
mRenderersEntities.clear();

// re-add entities from new set of renderers
const QList<QgsAbstract3DRenderer *> renderers = mMap.renderers();
for ( const QgsAbstract3DRenderer *renderer : renderers )
{
Qt3DCore::QEntity *newEntity = renderer->createEntity( mMap );
if ( newEntity )
{
newEntity->setParent( this );
finalizeNewEntity( newEntity );
mRenderersEntities[renderer] = newEntity;
}
}
}

void Qgs3DMapScene::onLayerRenderer3DChanged()
{
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
Expand Down Expand Up @@ -573,17 +587,7 @@ void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )
connect( picker, &Qt3DRender::QObjectPicker::pressed, this, &Qgs3DMapScene::onLayerEntityPickEvent );
}

// this is probably not the best place for material-specific configuration,
// maybe this could be more generalized when other materials need some specific treatment
for ( QgsLineMaterial *lm : newEntity->findChildren<QgsLineMaterial *>() )
{
connect( mCameraController, &QgsCameraController::viewportChanged, lm, [lm, this]
{
lm->setViewportSize( mCameraController->viewport().size() );
} );

lm->setViewportSize( cameraController()->viewport().size() );
}
finalizeNewEntity( newEntity );
}
}

Expand Down Expand Up @@ -611,6 +615,21 @@ void Qgs3DMapScene::removeLayerEntity( QgsMapLayer *layer )
}
}

void Qgs3DMapScene::finalizeNewEntity( Qt3DCore::QEntity *newEntity )
{
// this is probably not the best place for material-specific configuration,
// maybe this could be more generalized when other materials need some specific treatment
for ( QgsLineMaterial *lm : newEntity->findChildren<QgsLineMaterial *>() )
{
connect( mCameraController, &QgsCameraController::viewportChanged, lm, [lm, this]
{
lm->setViewportSize( mCameraController->viewport().size() );
} );

lm->setViewportSize( cameraController()->viewport().size() );
}
}

void Qgs3DMapScene::addCameraViewCenterEntity( Qt3DRender::QCamera *camera )
{
mEntityCameraViewCenter = new Qt3DCore::QEntity;
Expand Down
4 changes: 4 additions & 0 deletions src/3d/qgs3dmapscene.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace Qt3DExtras
}

class QgsAbstract3DEngine;
class QgsAbstract3DRenderer;
class QgsMapLayer;
class QgsCameraController;
class Qgs3DMapScenePickHandler;
Expand Down Expand Up @@ -108,6 +109,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
void onLayerEntityPickEvent( Qt3DRender::QPickEvent *event );
void updateLights();
void updateCameraLens();
void onRenderersChanged();
private:
void addLayerEntity( QgsMapLayer *layer );
void removeLayerEntity( QgsMapLayer *layer );
Expand All @@ -116,6 +118,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
void updateSceneState();
void updateScene();
bool updateCameraNearFarPlanes();
void finalizeNewEntity( Qt3DCore::QEntity *newEntity );

private:
const Qgs3DMapSettings &mMap;
Expand All @@ -129,6 +132,7 @@ class _3D_EXPORT Qgs3DMapScene : public Qt3DCore::QEntity
Qt3DCore::QEntity *mEntityCameraViewCenter = nullptr;
//! Keeps track of entities that belong to a particular layer
QMap<QgsMapLayer *, Qt3DCore::QEntity *> mLayerEntities;
QMap<const QgsAbstract3DRenderer *, Qt3DCore::QEntity *> mRenderersEntities;
bool mTerrainUpdateScheduled = false;
SceneState mSceneState = Ready;
//! List of currently registered pick handlers (used by identify tool)
Expand Down
3 changes: 2 additions & 1 deletion src/3d/qgs3dmapscenepickhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define QGS3DMAPSCENEPICKHANDLER_H

#include "qgsfeatureid.h"
#include <Qt3DRender/QPickEvent>

class QVector3D;
class QgsVectorLayer;
Expand All @@ -37,7 +38,7 @@ class Qgs3DMapScenePickHandler
virtual ~Qgs3DMapScenePickHandler() = default;

//! Called when user clicked a 3D entity belonging to a feature of a vector layer
virtual void handlePickOnVectorLayer( QgsVectorLayer *vlayer, QgsFeatureId id, const QVector3D &worldIntersection ) = 0;
virtual void handlePickOnVectorLayer( QgsVectorLayer *vlayer, QgsFeatureId id, const QVector3D &worldIntersection, Qt3DRender::QPickEvent *event ) = 0;
};

#endif // QGS3DMAPSCENEPICKHANDLER_H
4 changes: 4 additions & 0 deletions src/3d/qgs3dmapsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,11 @@ void Qgs3DMapSettings::setTerrainMapTheme( const QString &theme )

void Qgs3DMapSettings::setRenderers( const QList<QgsAbstract3DRenderer *> &renderers )
{
qDeleteAll( mRenderers );

mRenderers = renderers;

emit renderersChanged();
}

void Qgs3DMapSettings::setShowTerrainBoundingBoxes( bool enabled )
Expand Down
7 changes: 7 additions & 0 deletions src/3d/qgs3dmapsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,13 @@ class _3D_EXPORT Qgs3DMapSettings : public QObject
* \since QGIS 3.6
*/
void terrainMapThemeChanged();

/**
* Emitted when the list of map's extra renderers have been modified
* \since QGIS 3.10
*/
void renderersChanged();

//! Emitted when the flag whether terrain's bounding boxes are shown has changed
void showTerrainBoundingBoxesChanged();
//! Emitted when the flag whether terrain's tile info is shown has changed
Expand Down
36 changes: 36 additions & 0 deletions src/app/3d/qgs3dmapcanvasdockwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "qgs3danimationwidget.h"
#include "qgs3dmapsettings.h"
#include "qgs3dmaptoolidentify.h"
#include "qgs3dmaptoolmeasureline.h"
#include "qgs3dutils.h"


Expand All @@ -51,6 +52,9 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
QToolBar *toolBar = new QToolBar( contentsWidget );
toolBar->setIconSize( QgisApp::instance()->iconSize( true ) );

QAction *actionCameraControl = toolBar->addAction( QIcon( QgsApplication::iconPath( "mActionPan.svg" ) ),
tr( "Camera Control" ), this, &Qgs3DMapCanvasDockWidget::cameraControl );
actionCameraControl->setCheckable( true );

toolBar->addAction( QgsApplication::getThemeIcon( QStringLiteral( "mActionZoomFullExtent.svg" ) ),
tr( "Zoom Full" ), this, &Qgs3DMapCanvasDockWidget::resetView );
Expand All @@ -71,6 +75,18 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )
tr( "Identify" ), this, &Qgs3DMapCanvasDockWidget::identify );
actionIdentify->setCheckable( true );

QAction *actionMeasurementTool = toolBar->addAction( QIcon( QgsApplication::iconPath( "mActionMeasure.svg" ) ),
tr( "Measurement Line" ), this, &Qgs3DMapCanvasDockWidget::measureLine );
actionMeasurementTool->setCheckable( true );

// Create action group to make the action exclusive
QActionGroup *actionGroup = new QActionGroup( this );
actionGroup->addAction( actionCameraControl );
actionGroup->addAction( actionIdentify );
actionGroup->addAction( actionMeasurementTool );
actionGroup->setExclusive( true );
actionCameraControl->setChecked( true );

QAction *actionAnim = toolBar->addAction( QIcon( QgsApplication::iconPath( "mTaskRunning.svg" ) ),
tr( "Animations" ), this, &Qgs3DMapCanvasDockWidget::toggleAnimations );
actionAnim->setCheckable( true );
Expand All @@ -95,6 +111,8 @@ Qgs3DMapCanvasDockWidget::Qgs3DMapCanvasDockWidget( QWidget *parent )

mMapToolIdentify = new Qgs3DMapToolIdentify( mCanvas );

mMapToolMeasureLine = new Qgs3DMapToolMeasureLine( mCanvas );

mLabelPendingJobs = new QLabel( this );
mProgressPendingJobs = new QProgressBar( this );
mProgressPendingJobs->setRange( 0, 0 );
Expand Down Expand Up @@ -150,6 +168,15 @@ void Qgs3DMapCanvasDockWidget::toggleAnimations()
}
}

void Qgs3DMapCanvasDockWidget::cameraControl()
{
QAction *action = qobject_cast<QAction *>( sender() );
if ( !action )
return;

mCanvas->setMapTool( nullptr );
}

void Qgs3DMapCanvasDockWidget::identify()
{
QAction *action = qobject_cast<QAction *>( sender() );
Expand All @@ -159,6 +186,15 @@ void Qgs3DMapCanvasDockWidget::identify()
mCanvas->setMapTool( action->isChecked() ? mMapToolIdentify : nullptr );
}

void Qgs3DMapCanvasDockWidget::measureLine()
{
QAction *action = qobject_cast<QAction *>( sender() );
if ( !action )
return;

mCanvas->setMapTool( action->isChecked() ? mMapToolMeasureLine : nullptr );
}

void Qgs3DMapCanvasDockWidget::toggleNavigationWidget( bool visibility )
{
mCanvas->setOnScreenNavigationVisibility( visibility );
Expand Down
6 changes: 6 additions & 0 deletions src/app/3d/qgs3dmapcanvasdockwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Qgs3DAnimationWidget;
class Qgs3DMapCanvas;
class Qgs3DMapSettings;
class Qgs3DMapToolIdentify;
class Qgs3DMapToolMeasureLine;
class QgsMapCanvas;


Expand All @@ -42,12 +43,16 @@ class Qgs3DMapCanvasDockWidget : public QgsDockWidget
Qgs3DMapCanvas *mapCanvas3D() { return mCanvas; }
Qgs3DAnimationWidget *animationWidget() { return mAnimationWidget; }

Qgs3DMapToolMeasureLine *measurementLineTool() { return mMapToolMeasureLine; }

private slots:
void resetView();
void configure();
void saveAsImage();
void toggleAnimations();
void cameraControl();
void identify();
void measureLine();
void toggleNavigationWidget( bool visibility );

void onMainCanvasLayersChanged();
Expand All @@ -61,6 +66,7 @@ class Qgs3DMapCanvasDockWidget : public QgsDockWidget
QProgressBar *mProgressPendingJobs = nullptr;
QLabel *mLabelPendingJobs = nullptr;
Qgs3DMapToolIdentify *mMapToolIdentify = nullptr;
Qgs3DMapToolMeasureLine *mMapToolMeasureLine = nullptr;
};

#endif // QGS3DMAPCANVASDOCKWIDGET_H
5 changes: 5 additions & 0 deletions src/app/3d/qgs3dmaptool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ QCursor Qgs3DMapTool::cursor() const
{
return Qt::CrossCursor;
}

Qgs3DMapCanvas *Qgs3DMapTool::canvas()
{
return mCanvas;
}
2 changes: 2 additions & 0 deletions src/app/3d/qgs3dmaptool.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class Qgs3DMapTool : public QObject
*/
virtual bool allowsCameraControls() const { return true; }

Qgs3DMapCanvas *canvas();

protected:
Qgs3DMapCanvas *mCanvas = nullptr;
};
Expand Down
25 changes: 17 additions & 8 deletions src/app/3d/qgs3dmaptoolidentify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "qgs3dmaptoolidentify.h"

#include "qgsapplication.h"
#include "qgs3dmapcanvas.h"
#include "qgs3dmapscene.h"
#include "qgs3dutils.h"
Expand All @@ -35,21 +36,24 @@ class Qgs3DMapToolIdentifyPickHandler : public Qgs3DMapScenePickHandler
{
public:
Qgs3DMapToolIdentifyPickHandler( Qgs3DMapToolIdentify *identifyTool ): mIdentifyTool( identifyTool ) {}
void handlePickOnVectorLayer( QgsVectorLayer *vlayer, QgsFeatureId id, const QVector3D &worldIntersection ) override;
void handlePickOnVectorLayer( QgsVectorLayer *vlayer, QgsFeatureId id, const QVector3D &worldIntersection, Qt3DRender::QPickEvent *event ) override;
private:
Qgs3DMapToolIdentify *mIdentifyTool = nullptr;
};


void Qgs3DMapToolIdentifyPickHandler::handlePickOnVectorLayer( QgsVectorLayer *vlayer, QgsFeatureId id, const QVector3D &worldIntersection )
void Qgs3DMapToolIdentifyPickHandler::handlePickOnVectorLayer( QgsVectorLayer *vlayer, QgsFeatureId id, const QVector3D &worldIntersection, Qt3DRender::QPickEvent *event )
{
QgsVector3D mapCoords = Qgs3DUtils::worldToMapCoordinates( QgsVector3D( worldIntersection.x(),
worldIntersection.y(),
worldIntersection.z() ), mIdentifyTool->mCanvas->map()->origin() );
QgsPoint pt( mapCoords.x(), mapCoords.y(), mapCoords.z() );
if ( event->button() == Qt3DRender::QPickEvent::LeftButton )
{
QgsVector3D mapCoords = Qgs3DUtils::worldToMapCoordinates( QgsVector3D( worldIntersection.x(),
worldIntersection.y(),
worldIntersection.z() ), mIdentifyTool->mCanvas->map()->origin() );
QgsPoint pt( mapCoords.x(), mapCoords.y(), mapCoords.z() );

QgsMapToolIdentifyAction *identifyTool2D = QgisApp::instance()->identifyMapTool();
identifyTool2D->showResultsForFeature( vlayer, id, pt );
QgsMapToolIdentifyAction *identifyTool2D = QgisApp::instance()->identifyMapTool();
identifyTool2D->showResultsForFeature( vlayer, id, pt );
}
}


Expand Down Expand Up @@ -95,6 +99,11 @@ void Qgs3DMapToolIdentify::deactivate()
mCanvas->scene()->unregisterPickHandler( mPickHandler.get() );
}

QCursor Qgs3DMapToolIdentify::cursor() const
{
return QgsApplication::getThemeCursor( QgsApplication::Cursor::Identify );
}

void Qgs3DMapToolIdentify::onTerrainPicked( Qt3DRender::QPickEvent *event )
{
if ( event->button() != Qt3DRender::QPickEvent::LeftButton )
Expand Down
2 changes: 2 additions & 0 deletions src/app/3d/qgs3dmaptoolidentify.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class Qgs3DMapToolIdentify : public Qgs3DMapTool
void activate() override;
void deactivate() override;

QCursor cursor() const override;

private slots:
void onTerrainPicked( Qt3DRender::QPickEvent *event );
void onTerrainEntityChanged();
Expand Down
Loading