From 85caa70e76bc6d9b29245c21906a969c85692d7c Mon Sep 17 00:00:00 2001 From: Ismail Sunni Date: Tue, 29 Oct 2019 22:55:00 +0100 Subject: [PATCH] [FEATURE] Add z distance (#31451) * Add z-distance in 3d measurement tool. * Refactor code for adding new item in 3d measurement tool. * Fix right click stop the measurement but not reset the table. * Add horisontal distance. * Remove unit in the header. * Add widgets for 3d measurement tool * Calculate total horisontal distance. * Refactor showing total distance. * Handle check box behaviours. * Save state of the checkboxes. * Rename variable for consistency. * Set proper title for 3d measurement tool. * horisontal to horizontal. * use one extra distance. * Remove checkbox for other distance. --- src/app/3d/qgs3dmaptoolmeasureline.cpp | 2 + src/app/3d/qgs3dmeasuredialog.cpp | 151 ++++++++++++++++------- src/app/3d/qgs3dmeasuredialog.h | 24 ++++ src/app/qgsmeasuredialog.cpp | 4 + src/ui/qgsmeasurebase.ui | 161 ++++++++++++++----------- 5 files changed, 228 insertions(+), 114 deletions(-) diff --git a/src/app/3d/qgs3dmaptoolmeasureline.cpp b/src/app/3d/qgs3dmaptoolmeasureline.cpp index 35442dbeb12..47fd5935222 100644 --- a/src/app/3d/qgs3dmaptoolmeasureline.cpp +++ b/src/app/3d/qgs3dmaptoolmeasureline.cpp @@ -159,6 +159,7 @@ void Qgs3DMapToolMeasureLine::handleClick( Qt3DRender::QPickEvent *event, const { // Finish measurement mDone = true; + restart(); } else if ( event->button() == Qt3DRender::QPickEvent::MiddleButton ) { @@ -239,6 +240,7 @@ void Qgs3DMapToolMeasureLine::restart() mPoints.clear(); mDone = true; updateMeasurementLayer(); + mDialog->resetTable(); } void Qgs3DMapToolMeasureLine::undo() diff --git a/src/app/3d/qgs3dmeasuredialog.cpp b/src/app/3d/qgs3dmeasuredialog.cpp index 6a91b014427..f165ca994b8 100644 --- a/src/app/3d/qgs3dmeasuredialog.cpp +++ b/src/app/3d/qgs3dmeasuredialog.cpp @@ -30,6 +30,8 @@ Qgs3DMeasureDialog::Qgs3DMeasureDialog( Qgs3DMapToolMeasureLine *tool, Qt::Windo { setupUi( this ); + setWindowTitle( tr( " 3D Measurement Tool" ) ); + // New button QPushButton *newButton = new QPushButton( tr( "&New" ) ); buttonBox->addButton( newButton, QDialogButtonBox::ActionRole ); @@ -43,6 +45,9 @@ Qgs3DMeasureDialog::Qgs3DMeasureDialog( Qgs3DMapToolMeasureLine *tool, Qt::Windo mEllipsoidal->hide(); groupBox->hide(); + // Update text for 3D specific + totalDistanceLabel->setText( tr( "Total 3D Distance" ) ); + // Initialize unit combo box // Add a configuration button QPushButton *cb = new QPushButton( tr( "&Configuration" ) ); @@ -82,20 +87,15 @@ void Qgs3DMeasureDialog::addPoint() if ( !mTool->done() ) { // Add new entry in the table - QTreeWidgetItem *item = new QTreeWidgetItem( QStringList( QLocale().toString( 0.0, 'f', mDecimalPlaces ) ) ); - item->setTextAlignment( 0, Qt::AlignRight ); - mTable->addTopLevelItem( item ); - mTable->scrollToItem( item ); - - item->setText( 0, QString::number( convertLength( lastDistance(), mDisplayedDistanceUnit ) ) ); + addMeasurement( lastDistance(), lastVerticalDistance(), lastHorizontalDistance() ); mTotal += lastDistance(); - editTotal->setText( formatDistance( convertLength( mTotal, mDisplayedDistanceUnit ) ) ); + mHorizontalTotal += lastHorizontalDistance(); + updateTotal(); } } else { - // Update total with new displayed unit - editTotal->setText( formatDistance( convertLength( mTotal, mDisplayedDistanceUnit ) ) ); + updateTotal(); } } @@ -106,6 +106,20 @@ double Qgs3DMeasureDialog::lastDistance() return lastPoint.distance3D( secondLastPoint ); } +double Qgs3DMeasureDialog::lastVerticalDistance() +{ + QgsPoint lastPoint = mTool->points().rbegin()[0]; + QgsPoint secondLastPoint = mTool->points().rbegin()[1]; + return lastPoint.z() - secondLastPoint.z(); +} + +double Qgs3DMeasureDialog::lastHorizontalDistance() +{ + QgsPoint lastPoint = mTool->points().rbegin()[0]; + QgsPoint secondLastPoint = mTool->points().rbegin()[1]; + return lastPoint.distance( secondLastPoint ); +} + void Qgs3DMeasureDialog::repopulateComboBoxUnits() { mUnitsCombo->addItem( QgsUnitTypes::toString( QgsUnitTypes::DistanceMeters ), QgsUnitTypes::DistanceMeters ); @@ -130,8 +144,8 @@ void Qgs3DMeasureDialog::removeLastPoint() // Update total distance QgsLineString measureLine( mTool->points() ); mTotal = measureLine.length3D(); - // Update total with new displayed unit - editTotal->setText( formatDistance( convertLength( mTotal, mDisplayedDistanceUnit ) ) ); + mHorizontalTotal = measureLine.length(); + updateTotal(); } } @@ -145,11 +159,7 @@ void Qgs3DMeasureDialog::reject() void Qgs3DMeasureDialog::restart() { mTool->restart(); - - mTable->clear(); - mTotal = 0.; - // Update total with new displayed unit - editTotal->setText( formatDistance( convertLength( mTotal, mDisplayedDistanceUnit ) ) ); + resetTable(); } void Qgs3DMeasureDialog::closeEvent( QCloseEvent *e ) @@ -167,41 +177,15 @@ void Qgs3DMeasureDialog::updateSettings() mDisplayedDistanceUnit = QgsUnitTypes::decodeDistanceUnit( settings.value( QStringLiteral( "qgis/measure/displayunits" ), QgsUnitTypes::encodeUnit( QgsUnitTypes::DistanceUnknownUnit ) ).toString() ); - mTable->setHeaderLabels( QStringList( tr( "Segments [%1]" ).arg( QgsUnitTypes::toString( mDisplayedDistanceUnit ) ) ) ); - // Choose unit in the combobox + setupTableHeader(); mUnitsCombo->setCurrentIndex( mUnitsCombo->findData( mDisplayedDistanceUnit ) ); } void Qgs3DMeasureDialog::unitsChanged( int index ) { mDisplayedDistanceUnit = static_cast< QgsUnitTypes::DistanceUnit >( mUnitsCombo->itemData( index ).toInt() ); - // Set the table header to show displayed unit - mTable->setHeaderLabels( QStringList( tr( "Segments [%1]" ).arg( QgsUnitTypes::toString( mDisplayedDistanceUnit ) ) ) ); - - // Reset table - mTable->clear(); - - // Repopulate the table based on new displayed unit - QVector::const_iterator it; - bool isFirstPoint = true; // first point - QgsPoint p1, p2; - QVector< QgsPoint > tmpPoints = mTool->points(); - for ( it = tmpPoints.constBegin(); it != tmpPoints.constEnd(); ++it ) - { - p2 = *it; - if ( !isFirstPoint ) - { - double distance = p1.distance3D( p2 ); - QTreeWidgetItem *item = new QTreeWidgetItem( QStringList( QLocale().toString( convertLength( distance, mDisplayedDistanceUnit ), 'f', mDecimalPlaces ) ) ); - item->setTextAlignment( 0, Qt::AlignRight ); - mTable->addTopLevelItem( item ); - mTable->scrollToItem( item ); - } - p1 = p2; - isFirstPoint = false; - } - // Update total with new displayed unit - editTotal->setText( formatDistance( convertLength( mTotal, mDisplayedDistanceUnit ) ) ); + updateTable(); + updateTotal(); } double Qgs3DMeasureDialog::convertLength( double length, QgsUnitTypes::DistanceUnit toUnit ) const @@ -226,3 +210,80 @@ void Qgs3DMeasureDialog::openConfigTab() { QgisApp::instance()->showOptionsDialog( this, QStringLiteral( "mOptionsPageMapTools" ) ); } + +void Qgs3DMeasureDialog::setupTableHeader() +{ + // Set the table header to show displayed unit + QStringList headers; + headers << tr( "Horizontal Distance" ); + headers << tr( "Vertical Distance" ); + headers << tr( "3D Distance" ); + + QTreeWidgetItem *headerItem = new QTreeWidgetItem( headers ); + for ( int i = 0; i < headers.count(); ++i ) + { + headerItem->setTextAlignment( i, Qt::AlignRight ); + } + mTable->setHeaderItem( headerItem ); + for ( int i = 0; i < headers.count(); ++i ) + { + mTable->resizeColumnToContents( i ); + } +} + +void Qgs3DMeasureDialog::addMeasurement( double distance, double verticalDistance, double horizontalDistance ) +{ + QStringList content; + content << QLocale().toString( convertLength( horizontalDistance, mDisplayedDistanceUnit ), 'f', mDecimalPlaces ); + content << QLocale().toString( convertLength( verticalDistance, mDisplayedDistanceUnit ), 'f', mDecimalPlaces ); + content << QLocale().toString( convertLength( distance, mDisplayedDistanceUnit ), 'f', mDecimalPlaces ); + QTreeWidgetItem *item = new QTreeWidgetItem( content ); + for ( int i = 0; i < content.count(); ++i ) + { + item->setTextAlignment( i, Qt::AlignRight ); + } + mTable->addTopLevelItem( item ); + mTable->scrollToItem( item ); +} + +void Qgs3DMeasureDialog::updateTotal() +{ + // Update total with new displayed unit + editTotal->setText( formatDistance( convertLength( mTotal, mDisplayedDistanceUnit ) ) ); + editHorizontalTotal->setText( formatDistance( convertLength( mHorizontalTotal, mDisplayedDistanceUnit ) ) ); +} + +void Qgs3DMeasureDialog::updateTable() +{ + setupTableHeader(); + + // Reset table + mTable->clear(); + + // Repopulate the table based on new displayed unit + QVector::const_iterator it; + bool isFirstPoint = true; // first point + QgsPoint p1, p2; + QVector< QgsPoint > tmpPoints = mTool->points(); + for ( it = tmpPoints.constBegin(); it != tmpPoints.constEnd(); ++it ) + { + p2 = *it; + if ( !isFirstPoint ) + { + double distance = p1.distance3D( p2 ); + double verticalDistance = p2.z() - p1.z(); + double horizontalDistance = p1.distance( p2 ); + addMeasurement( distance, verticalDistance, horizontalDistance ); + } + p1 = p2; + isFirstPoint = false; + } +} + +void Qgs3DMeasureDialog::resetTable() +{ + mTable->clear(); + mTotal = 0.; + mHorizontalTotal = 0.; + updateTotal(); +} diff --git a/src/app/3d/qgs3dmeasuredialog.h b/src/app/3d/qgs3dmeasuredialog.h index 507426d921f..a46d031f56c 100644 --- a/src/app/3d/qgs3dmeasuredialog.h +++ b/src/app/3d/qgs3dmeasuredialog.h @@ -45,12 +45,21 @@ class Qgs3DMeasureDialog : public QDialog, private Ui::QgsMeasureBase //! Get last distance in map distance unit double lastDistance(); + //! Get last Z value distance in map distance unit + double lastVerticalDistance(); + + //! Get last horizontal value distance in map distance unit + double lastHorizontalDistance(); + //! Populating unit combo box void repopulateComboBoxUnits(); //! Remove last point void removeLastPoint(); + // Clear the content of the table + void resetTable(); + public slots: void reject() override; @@ -71,6 +80,9 @@ class Qgs3DMeasureDialog : public QDialog, private Ui::QgsMeasureBase //! Total length in map distance unit double mTotal = 0.0; + //! Total horizontal length in map distance unit + double mHorizontalTotal = 0.0; + //! Number of decimal places we want. int mDecimalPlaces = 3; @@ -91,6 +103,18 @@ class Qgs3DMeasureDialog : public QDialog, private Ui::QgsMeasureBase //! Open configuration tab void openConfigTab(); + + //! Setup the header of the table + void setupTableHeader(); + + //! Add measurement (3d-distance, vertical distance, horizontal distance) to the table + void addMeasurement( double distance, double verticalDistance, double horizontalDistance ); + + //! Update total value + void updateTotal(); + + //! Update table based on current setting + void updateTable(); }; #endif // QGS3DMEASUREDIALOG_H diff --git a/src/app/qgsmeasuredialog.cpp b/src/app/qgsmeasuredialog.cpp index 9e1e930144f..63da1a417d6 100644 --- a/src/app/qgsmeasuredialog.cpp +++ b/src/app/qgsmeasuredialog.cpp @@ -42,6 +42,10 @@ QgsMeasureDialog::QgsMeasureDialog( QgsMeasureTool *tool, Qt::WindowFlags f ) QgsGui::instance()->enableAutoGeometryRestore( this ); connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsMeasureDialog::showHelp ); + // hide 3D related options + editHorizontalTotal->hide(); + totalHorizontalDistanceLabel->hide(); + QPushButton *nb = new QPushButton( tr( "&New" ) ); buttonBox->addButton( nb, QDialogButtonBox::ActionRole ); connect( nb, &QAbstractButton::clicked, this, &QgsMeasureDialog::restart ); diff --git a/src/ui/qgsmeasurebase.ui b/src/ui/qgsmeasurebase.ui index e9195e8a00d..051df490d9f 100644 --- a/src/ui/qgsmeasurebase.ui +++ b/src/ui/qgsmeasurebase.ui @@ -6,8 +6,8 @@ 0 0 - 359 - 301 + 462 + 376 @@ -39,51 +39,6 @@ 6 - - - - Total - - - editTotal - - - - - - - - 75 - true - - - - Qt::AlignRight - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 41 - 25 - - - - - - - @@ -105,27 +60,76 @@ - - + + + + Total + + + editTotal + + + + + - Qt::Vertical + Qt::Horizontal + + + QSizePolicy::Fixed - 40 - 20 + 41 + 25 - - - - QDialogButtonBox::Close|QDialogButtonBox::Help + + + + Total Horizontal Distance - + + + + + 75 + true + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + Ellipsoidal + + + true + + + + + + + Cartesian + + + false + + + + Info @@ -144,26 +148,45 @@ - - - - Cartesian - - - false + + + + + + + QDialogButtonBox::Close|QDialogButtonBox::Help - - - - Ellipsoidal + + + + + 75 + true + - + + Qt::AlignRight + + true + + + + Qt::Vertical + + + + 40 + 20 + + + +