From 45ca0eb52b4666da5f2572b01dd947996434e67e Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 09:52:38 +0000 Subject: [PATCH 01/23] Fixes #17576 Avoid crash during node editor cleanup --- src/app/vertextool/qgsvertextool.cpp | 10 +++++++++- src/app/vertextool/qgsvertextool.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/app/vertextool/qgsvertextool.cpp b/src/app/vertextool/qgsvertextool.cpp index 45639417ed15..4ba25e895e85 100644 --- a/src/app/vertextool/qgsvertextool.cpp +++ b/src/app/vertextool/qgsvertextool.cpp @@ -984,7 +984,7 @@ void QgsVertexTool::showVertexEditor() //#spellok mVertexEditor.reset( new QgsVertexEditor( m.layer(), mSelectedFeature.get(), mCanvas ) ); QgisApp::instance()->addDockWidget( Qt::LeftDockWidgetArea, mVertexEditor.get() ); connect( mVertexEditor.get(), &QgsVertexEditor::deleteSelectedRequested, this, &QgsVertexTool::deleteVertexEditorSelection ); - connect( mSelectedFeature.get()->vlayer(), &QgsVectorLayer::featureDeleted, this, [ = ]( QgsFeatureId id ) { if ( mSelectedFeature.get()->featureId() == id ) cleanupVertexEditor(); } ); + connect( mSelectedFeature.get()->vlayer(), &QgsVectorLayer::featureDeleted, this, &QgsVertexTool::cleanEditor ); } void QgsVertexTool::cleanupVertexEditor() @@ -2161,3 +2161,11 @@ void QgsVertexTool::stopRangeVertexSelection() mSelectionMethod = SelectionNormal; setHighlightedVertices( QList() ); } + +void QgsVertexTool::cleanEditor( QgsFeatureId id ) +{ + if ( mSelectedFeature.get() && mSelectedFeature.get()->featureId() == id ) + { + cleanupVertexEditor(); + }; +} diff --git a/src/app/vertextool/qgsvertextool.h b/src/app/vertextool/qgsvertextool.h index a0f089184c88..fd6d50b71690 100644 --- a/src/app/vertextool/qgsvertextool.h +++ b/src/app/vertextool/qgsvertextool.h @@ -97,6 +97,8 @@ class APP_EXPORT QgsVertexTool : public QgsMapToolAdvancedDigitizing void startRangeVertexSelection(); + void cleanEditor( QgsFeatureId id ); + private: void buildDragBandsForVertices( const QSet &movingVertices, const QgsPointXY &dragVertexMapPoint ); From 7a698f234d4850c21fb4e432570fd81a2dc0836b Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 09:57:25 +0000 Subject: [PATCH 02/23] Fixes #17574 Add Z support in AddCircularString map tools --- python/gui/qgsmaptoolcapture.sip.in | 13 ++++++ .../qgsmaptoolcircularstringcurvepoint.cpp | 2 +- src/app/qgsmaptoolcircularstringradius.cpp | 6 +-- src/core/geometry/qgsgeometryutils.cpp | 18 ++++++++ src/gui/qgsmaptoolcapture.cpp | 45 +++++++++++++++++++ src/gui/qgsmaptoolcapture.h | 12 +++++ 6 files changed, 92 insertions(+), 4 deletions(-) diff --git a/python/gui/qgsmaptoolcapture.sip.in b/python/gui/qgsmaptoolcapture.sip.in index 62505fc1bd99..3f9b74e6d54c 100644 --- a/python/gui/qgsmaptoolcapture.sip.in +++ b/python/gui/qgsmaptoolcapture.sip.in @@ -102,6 +102,19 @@ convenient method to clean members int fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ); + QgsPoint pointFromPointXY( const QgsPointXY &point ) const; +%Docstring + Creates a QgsPoint with ZM support if necessary (according to the + WkbType of the current layer) from a QgsPointXY. + + \param point A QgsPointXY to convert + + :return: a point if ZM support if necessary + +.. versionadded:: 3.0 + :rtype: QgsPoint +%End + int addVertex( const QgsPointXY &point ); int addVertex( const QgsPointXY &mapPoint, const QgsPointLocator::Match &match ); diff --git a/src/app/qgsmaptoolcircularstringcurvepoint.cpp b/src/app/qgsmaptoolcircularstringcurvepoint.cpp index 725ae7987710..221c5de521d7 100644 --- a/src/app/qgsmaptoolcircularstringcurvepoint.cpp +++ b/src/app/qgsmaptoolcircularstringcurvepoint.cpp @@ -29,7 +29,7 @@ QgsMapToolCircularStringCurvePoint::QgsMapToolCircularStringCurvePoint( QgsMapTo void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { diff --git a/src/app/qgsmaptoolcircularstringradius.cpp b/src/app/qgsmaptoolcircularstringradius.cpp index 39850c170583..6f8fd1ee913a 100644 --- a/src/app/qgsmaptoolcircularstringradius.cpp +++ b/src/app/qgsmaptoolcircularstringradius.cpp @@ -43,7 +43,7 @@ void QgsMapToolCircularStringRadius::deactivate() void QgsMapToolCircularStringRadius::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -55,7 +55,7 @@ void QgsMapToolCircularStringRadius::cadCanvasReleaseEvent( QgsMapMouseEvent *e { if ( mPoints.size() % 2 ) { - mTemporaryEndPoint = mapPoint; + mTemporaryEndPoint = pointFromPointXY( mapPoint ); //initial radius is distance( tempPoint - mPoints.last ) / 2.0 double minRadius = std::sqrt( QgsGeometryUtils::sqrDistance2D( mPoints.last(), mTemporaryEndPoint ) ) / 2.0; @@ -136,7 +136,7 @@ void QgsMapToolCircularStringRadius::recalculateTempRubberBand( const QgsPointXY else { rubberBandPoints.append( mPoints.last() ); - rubberBandPoints.append( QgsPoint( mousePosition ) ); + rubberBandPoints.append( pointFromPointXY( mousePosition ) ); } QgsCircularString *cString = new QgsCircularString(); cString->setPoints( rubberBandPoints ); diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index c7e6136fd7cb..07b5e0342049 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -604,6 +604,24 @@ bool QgsGeometryUtils::segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2, } result = possibleMidPoints.at( minDistIndex ); + + // add z support if necessary + if ( p1.is3D() && p2.is3D() ) + { + result.convertTo( p1.wkbType() ); + result.setZ( ( p1.z() + p2.z() ) / 2. ); + } + else if ( p1.is3D() && !p2.is3D() ) + { + result.convertTo( p1.wkbType() ); + result.setZ( p1.z() ); + } + else if ( !p1.is3D() && p2.is3D() ) + { + result.convertTo( p2.wkbType() ); + result.setZ( p2.z() ); + } + return true; } diff --git a/src/gui/qgsmaptoolcapture.cpp b/src/gui/qgsmaptoolcapture.cpp index 93dcc06d9ab7..cf9f4fad4c06 100644 --- a/src/gui/qgsmaptoolcapture.cpp +++ b/src/gui/qgsmaptoolcapture.cpp @@ -768,3 +768,48 @@ void QgsMapToolCapture::setPoints( const QVector &pointList ) mSnappingMatches.append( QgsPointLocator::Match() ); } +QgsPoint QgsMapToolCapture::pointFromPointXY( const QgsPointXY &point ) const +{ + QgsPoint newPoint( QgsWkbTypes::Point, point.x(), point.y() ); + + // get current layer + QgsVectorLayer *vlayer = qobject_cast( mCanvas->currentLayer() ); + if ( !vlayer ) + { + return newPoint; + } + + // convert to the corresponding type for a full ZM support + QgsWkbTypes::Type type = vlayer->wkbType(); + if ( QgsWkbTypes::hasZ( type ) && !QgsWkbTypes::hasM( type ) ) + { + newPoint.convertTo( QgsWkbTypes::PointZ ); + } + else if ( !QgsWkbTypes::hasZ( type ) && QgsWkbTypes::hasM( type ) ) + { + newPoint.convertTo( QgsWkbTypes::PointM ); + } + else if ( QgsWkbTypes::hasZ( type ) && QgsWkbTypes::hasM( type ) ) + { + newPoint.convertTo( QgsWkbTypes::PointZM ); + } + + // set default value for Z if necessary + if ( QgsWkbTypes::hasZ( newPoint.wkbType() ) ) + newPoint.setZ( defaultZValue() ); + + return newPoint; +} + +#ifdef Q_OS_WIN +bool QgsMapToolCapture::eventFilter( QObject *obj, QEvent *event ) +{ + if ( event->type() != QEvent::ContextMenu ) + return false; + + if ( --mSkipNextContextMenuEvent == 0 ) + obj->removeEventFilter( this ); + + return mSkipNextContextMenuEvent >= 0; +} +#endif diff --git a/src/gui/qgsmaptoolcapture.h b/src/gui/qgsmaptoolcapture.h index 1582bd4fba98..36580d12bb5f 100644 --- a/src/gui/qgsmaptoolcapture.h +++ b/src/gui/qgsmaptoolcapture.h @@ -147,6 +147,18 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing // TODO QGIS 3.0 returns an enum instead of a magic constant int fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ); + /** + * Creates a QgsPoint with ZM support if necessary (according to the + * WkbType of the current layer) from a QgsPointXY. + * + * \param point A QgsPointXY to convert + * + * \returns a point if ZM support if necessary + * + * \since QGIS 3.0 + */ + QgsPoint pointFromPointXY( const QgsPointXY &point ) const; + /** * Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates) * \returns 0 in case of success, 1 if current layer is not a vector layer, 2 if coordinate transformation failed From 4e7291783fe3c97273e1ecfb2848ddb8abe4e589 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 14:25:39 +0000 Subject: [PATCH 03/23] Add Z support for AddCircle map tools --- src/app/qgsmaptoolcircle2points.cpp | 4 +-- src/app/qgsmaptoolcircle2tangentspoint.cpp | 12 ++++---- src/app/qgsmaptoolcircle2tangentspoint.h | 2 +- src/app/qgsmaptoolcircle3points.cpp | 4 +-- src/app/qgsmaptoolcircle3tangents.cpp | 16 +++++----- src/app/qgsmaptoolcirclecenterpoint.cpp | 4 +-- src/core/geometry/qgscircle.cpp | 29 +++++++++++++++--- src/core/geometry/qgsgeometryutils.cpp | 35 ++++++++++++++++++---- src/core/geometry/qgstriangle.cpp | 26 +++++++++++++--- 9 files changed, 97 insertions(+), 35 deletions(-) diff --git a/src/app/qgsmaptoolcircle2points.cpp b/src/app/qgsmaptoolcircle2points.cpp index c605ac8ad9cb..1fff078329eb 100644 --- a/src/app/qgsmaptoolcircle2points.cpp +++ b/src/app/qgsmaptoolcircle2points.cpp @@ -28,7 +28,7 @@ QgsMapToolCircle2Points::QgsMapToolCircle2Points( QgsMapToolCapture *parentTool, void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -52,7 +52,7 @@ void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { mCircle = QgsCircle().from2Points( mPoints.at( 0 ), mapPoint ); diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index bc3813f8d7de..28401347b436 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -43,7 +43,7 @@ QgsMapToolCircle2TangentsPoint::~QgsMapToolCircle2TangentsPoint() void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -56,8 +56,8 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e if ( match.isValid() ) { match.edgePoints( p1, p2 ); - mPoints.append( QgsPoint( p1 ) ); - mPoints.append( QgsPoint( p2 ) ); + mPoints.append( pointFromPointXY( p1 ) ); + mPoints.append( pointFromPointXY( p2 ) ); } } if ( mPoints.size() == 4 ) @@ -100,7 +100,7 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -123,8 +123,8 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) match.edgePoints( p1, p2 ); std::unique_ptr line( new QgsLineString() ); - line->addVertex( QgsPoint( p1 ) ); - line->addVertex( QgsPoint( p2 ) ); + line->addVertex( pointFromPointXY( p1 ) ); + line->addVertex( pointFromPointXY( p2 ) ); mTempRubberBand->setGeometry( line.release() ); mTempRubberBand->show(); diff --git a/src/app/qgsmaptoolcircle2tangentspoint.h b/src/app/qgsmaptoolcircle2tangentspoint.h index dde598249965..5a4b451c70c6 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.h +++ b/src/app/qgsmaptoolcircle2tangentspoint.h @@ -49,7 +49,7 @@ class QgsMapToolCircle2TangentsPoint: public QgsMapToolAddCircle QSpinBox *mRadiusSpinBox = nullptr; int mRadius = 0; - QVector mCenters; + QVector mCenters; QVector mRubberBands; }; diff --git a/src/app/qgsmaptoolcircle3points.cpp b/src/app/qgsmaptoolcircle3points.cpp index a5d26737cfdc..be87b489cb62 100644 --- a/src/app/qgsmaptoolcircle3points.cpp +++ b/src/app/qgsmaptoolcircle3points.cpp @@ -29,7 +29,7 @@ QgsMapToolCircle3Points::QgsMapToolCircle3Points( QgsMapToolCapture *parentTool, void QgsMapToolCircle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -53,7 +53,7 @@ void QgsMapToolCircle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { diff --git a/src/app/qgsmaptoolcircle3tangents.cpp b/src/app/qgsmaptoolcircle3tangents.cpp index 966e3a0660c3..dc6cfb349d5f 100644 --- a/src/app/qgsmaptoolcircle3tangents.cpp +++ b/src/app/qgsmaptoolcircle3tangents.cpp @@ -32,7 +32,7 @@ QgsMapToolCircle3Tangents::QgsMapToolCircle3Tangents( QgsMapToolCapture *parentT void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -43,8 +43,8 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) if ( match.isValid() && ( mPoints.size() <= 2 * 2 ) ) { match.edgePoints( p1, p2 ); - mPoints.append( QgsPoint( p1 ) ); - mPoints.append( QgsPoint( p2 ) ); + mPoints.append( pointFromPointXY( p1 ) ); + mPoints.append( pointFromPointXY( p2 ) ); } } else if ( e->button() == Qt::RightButton ) @@ -52,8 +52,8 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) if ( match.isValid() && ( mPoints.size() == 4 ) ) { match.edgePoints( p1, p2 ); - mPoints.append( QgsPoint( p1 ) ); - mPoints.append( QgsPoint( p2 ) ); + mPoints.append( pointFromPointXY( p1 ) ); + mPoints.append( pointFromPointXY( p2 ) ); mCircle = QgsCircle().from3Tangents( mPoints.at( 0 ), mPoints.at( 1 ), mPoints.at( 2 ), mPoints.at( 3 ), mPoints.at( 4 ), mPoints.at( 5 ) ); if ( mCircle.isEmpty() ) { @@ -73,7 +73,7 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle3Tangents::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -94,8 +94,8 @@ void QgsMapToolCircle3Tangents::cadCanvasMoveEvent( QgsMapMouseEvent *e ) match.edgePoints( p1, p2 ); std::unique_ptr line( new QgsLineString() ); - line->addVertex( QgsPoint( p1 ) ); - line->addVertex( QgsPoint( p2 ) ); + line->addVertex( pointFromPointXY( p1 ) ); + line->addVertex( pointFromPointXY( p2 ) ); mTempRubberBand->setGeometry( line.release() ); mTempRubberBand->show(); diff --git a/src/app/qgsmaptoolcirclecenterpoint.cpp b/src/app/qgsmaptoolcirclecenterpoint.cpp index 3aba2dd17dbe..f8cd74256da7 100644 --- a/src/app/qgsmaptoolcirclecenterpoint.cpp +++ b/src/app/qgsmaptoolcirclecenterpoint.cpp @@ -29,7 +29,7 @@ QgsMapToolCircleCenterPoint::QgsMapToolCircleCenterPoint( QgsMapToolCapture *par void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -54,7 +54,7 @@ void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircleCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { mCircle = QgsCircle().fromCenterPoint( mPoints.at( 0 ), mapPoint ); diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index 2d4f203579ee..046d50be48e8 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -138,6 +138,27 @@ QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, cons double aSlope = yDelta_a / xDelta_a; double bSlope = yDelta_b / xDelta_b; + // set z cooridnate for center + double z = std::numeric_limits::quiet_NaN(); + if ( p1.is3D() ) + { + z = p1.z(); + } + else if ( p2.is3D() ) + { + z = p2.z(); + } + else if ( p3.is3D() ) + { + z = p3.z(); + } + + if ( ! std::isnan( z ) ) + { + center.convertTo( QgsWkbTypes::addZ( center.wkbType() ) ); + center.setZ( z ); + } + if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) ) { center.setX( 0.5 * ( p2.x() + p3.x() ) ); @@ -249,10 +270,10 @@ void QgsCircle::setSemiMinorAxis( const double semiMinorAxis ) QVector QgsCircle::northQuadrant() const { QVector quad; - quad.append( QgsPoint( mCenter.x(), mCenter.y() + mSemiMajorAxis ) ); - quad.append( QgsPoint( mCenter.x() + mSemiMajorAxis, mCenter.y() ) ); - quad.append( QgsPoint( mCenter.x(), mCenter.y() - mSemiMajorAxis ) ); - quad.append( QgsPoint( mCenter.x() - mSemiMajorAxis, mCenter.y() ) ); + quad.append( QgsPoint( mCenter.x(), mCenter.y() + mSemiMajorAxis, mCenter.z() ) ); + quad.append( QgsPoint( mCenter.x() + mSemiMajorAxis, mCenter.y(), mCenter.z() ) ); + quad.append( QgsPoint( mCenter.x(), mCenter.y() - mSemiMajorAxis, mCenter.z() ) ); + quad.append( QgsPoint( mCenter.x() - mSemiMajorAxis, mCenter.y(), mCenter.z() ) ); return quad; } diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index 07b5e0342049..f99f58e8d63b 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -248,6 +248,24 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v1, const intersection = QgsPoint( p1.x() + v1.x() * k, p1.y() + v1.y() * k ); + // z support for inter point + double z = std::numeric_limits::quiet_NaN(); + if ( p1.is3D() ) + { + z = p1.z(); + } + else if ( q1.is3D() ) + { + z = q1.z(); + } + + if ( ! std::isnan( z ) ) + { + inter.convertTo( QgsWkbTypes::addZ( inter.wkbType() ) ); + inter.setZ( z ); + } + + return true; } @@ -606,20 +624,25 @@ bool QgsGeometryUtils::segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2, result = possibleMidPoints.at( minDistIndex ); // add z support if necessary + double z = std::numeric_limits::quiet_NaN(); + if ( p1.is3D() && p2.is3D() ) { - result.convertTo( p1.wkbType() ); - result.setZ( ( p1.z() + p2.z() ) / 2. ); + z = ( p1.z() + p2.z() ) / 2.; } else if ( p1.is3D() && !p2.is3D() ) { - result.convertTo( p1.wkbType() ); - result.setZ( p1.z() ); + z = p1.z(); } else if ( !p1.is3D() && p2.is3D() ) { - result.convertTo( p2.wkbType() ); - result.setZ( p2.z() ); + z = p2.z(); + } + + if ( ! std::isnan( z ) ) + { + result.convertTo( QgsWkbTypes::addZ( result.wkbType() ) ); + result.setZ( z ); } return true; diff --git a/src/core/geometry/qgstriangle.cpp b/src/core/geometry/qgstriangle.cpp index 5b4e561f2fd8..cdd8e69d239f 100644 --- a/src/core/geometry/qgstriangle.cpp +++ b/src/core/geometry/qgstriangle.cpp @@ -574,7 +574,28 @@ QgsPoint QgsTriangle::inscribedCenter() const l.at( 1 ) * vertexAt( 0 ).y() + l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter(); - return QgsPoint( x, y ); + double z = std::numeric_limits::quiet_NaN(); + if ( vertexAt( 0 ).is3D() ) + { + z = vertexAt( 0 ).z(); + } + else if ( vertexAt( 1 ).is3D() ) + { + z = vertexAt( 1 ).z(); + } + else if ( vertexAt( 2 ).is3D() ) + { + z = vertexAt( 2 ).z(); + } + + QgsPoint center( x, y ); + if ( !std::isnan( z ) ) + { + center.convertTo( QgsWkbTypes::PointZ ); + center.setZ( z ); + } + + return center; } double QgsTriangle::inscribedRadius() const @@ -590,6 +611,3 @@ QgsCircle QgsTriangle::inscribedCircle() const return QgsCircle(); return QgsCircle( inscribedCenter(), inscribedRadius() ); } - - - From 5d921cc9b2136d434650345bceda9e0515f6a478 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 14:26:54 +0000 Subject: [PATCH 04/23] Fixes crash in map tool --- src/app/qgsmaptoolcircle2tangentspoint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index 28401347b436..b13bac5615e5 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -131,7 +131,7 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) } } - if ( mPoints.size() == 4 ) + if ( mPoints.size() == 4 && !mCenters.isEmpty() ) { QgsPoint center = QgsPoint( mCenters.at( 0 ) ); const double currentDist = mapPoint.distanceSquared( center ); From d3b9c9838372bff179be4316845f829ce98175e3 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 14:50:44 +0000 Subject: [PATCH 05/23] Rename pointFromPointXY to fromPointXY --- python/gui/qgsmaptoolcapture.sip.in | 2 +- src/app/qgsmaptoolcircle2points.cpp | 4 ++-- src/app/qgsmaptoolcircle2tangentspoint.cpp | 12 ++++++------ src/app/qgsmaptoolcircle3points.cpp | 4 ++-- src/app/qgsmaptoolcircle3tangents.cpp | 16 ++++++++-------- src/app/qgsmaptoolcirclecenterpoint.cpp | 4 ++-- src/app/qgsmaptoolcircularstringcurvepoint.cpp | 2 +- src/app/qgsmaptoolcircularstringradius.cpp | 6 +++--- src/gui/qgsmaptoolcapture.cpp | 2 +- src/gui/qgsmaptoolcapture.h | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/python/gui/qgsmaptoolcapture.sip.in b/python/gui/qgsmaptoolcapture.sip.in index 3f9b74e6d54c..5e808b82345c 100644 --- a/python/gui/qgsmaptoolcapture.sip.in +++ b/python/gui/qgsmaptoolcapture.sip.in @@ -102,7 +102,7 @@ convenient method to clean members int fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ); - QgsPoint pointFromPointXY( const QgsPointXY &point ) const; + QgsPoint fromPointXY( const QgsPointXY &point ) const; %Docstring Creates a QgsPoint with ZM support if necessary (according to the WkbType of the current layer) from a QgsPointXY. diff --git a/src/app/qgsmaptoolcircle2points.cpp b/src/app/qgsmaptoolcircle2points.cpp index 1fff078329eb..62619e481c3e 100644 --- a/src/app/qgsmaptoolcircle2points.cpp +++ b/src/app/qgsmaptoolcircle2points.cpp @@ -28,7 +28,7 @@ QgsMapToolCircle2Points::QgsMapToolCircle2Points( QgsMapToolCapture *parentTool, void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -52,7 +52,7 @@ void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { mCircle = QgsCircle().from2Points( mPoints.at( 0 ), mapPoint ); diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index b13bac5615e5..51a4974d8660 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -43,7 +43,7 @@ QgsMapToolCircle2TangentsPoint::~QgsMapToolCircle2TangentsPoint() void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -56,8 +56,8 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e if ( match.isValid() ) { match.edgePoints( p1, p2 ); - mPoints.append( pointFromPointXY( p1 ) ); - mPoints.append( pointFromPointXY( p2 ) ); + mPoints.append( fromPointXY( p1 ) ); + mPoints.append( fromPointXY( p2 ) ); } } if ( mPoints.size() == 4 ) @@ -100,7 +100,7 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -123,8 +123,8 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) match.edgePoints( p1, p2 ); std::unique_ptr line( new QgsLineString() ); - line->addVertex( pointFromPointXY( p1 ) ); - line->addVertex( pointFromPointXY( p2 ) ); + line->addVertex( fromPointXY( p1 ) ); + line->addVertex( fromPointXY( p2 ) ); mTempRubberBand->setGeometry( line.release() ); mTempRubberBand->show(); diff --git a/src/app/qgsmaptoolcircle3points.cpp b/src/app/qgsmaptoolcircle3points.cpp index be87b489cb62..5d284e5f92a0 100644 --- a/src/app/qgsmaptoolcircle3points.cpp +++ b/src/app/qgsmaptoolcircle3points.cpp @@ -29,7 +29,7 @@ QgsMapToolCircle3Points::QgsMapToolCircle3Points( QgsMapToolCapture *parentTool, void QgsMapToolCircle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -53,7 +53,7 @@ void QgsMapToolCircle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { diff --git a/src/app/qgsmaptoolcircle3tangents.cpp b/src/app/qgsmaptoolcircle3tangents.cpp index dc6cfb349d5f..78d6bc351da5 100644 --- a/src/app/qgsmaptoolcircle3tangents.cpp +++ b/src/app/qgsmaptoolcircle3tangents.cpp @@ -32,7 +32,7 @@ QgsMapToolCircle3Tangents::QgsMapToolCircle3Tangents( QgsMapToolCapture *parentT void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -43,8 +43,8 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) if ( match.isValid() && ( mPoints.size() <= 2 * 2 ) ) { match.edgePoints( p1, p2 ); - mPoints.append( pointFromPointXY( p1 ) ); - mPoints.append( pointFromPointXY( p2 ) ); + mPoints.append( fromPointXY( p1 ) ); + mPoints.append( fromPointXY( p2 ) ); } } else if ( e->button() == Qt::RightButton ) @@ -52,8 +52,8 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) if ( match.isValid() && ( mPoints.size() == 4 ) ) { match.edgePoints( p1, p2 ); - mPoints.append( pointFromPointXY( p1 ) ); - mPoints.append( pointFromPointXY( p2 ) ); + mPoints.append( fromPointXY( p1 ) ); + mPoints.append( fromPointXY( p2 ) ); mCircle = QgsCircle().from3Tangents( mPoints.at( 0 ), mPoints.at( 1 ), mPoints.at( 2 ), mPoints.at( 3 ), mPoints.at( 4 ), mPoints.at( 5 ) ); if ( mCircle.isEmpty() ) { @@ -73,7 +73,7 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle3Tangents::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -94,8 +94,8 @@ void QgsMapToolCircle3Tangents::cadCanvasMoveEvent( QgsMapMouseEvent *e ) match.edgePoints( p1, p2 ); std::unique_ptr line( new QgsLineString() ); - line->addVertex( pointFromPointXY( p1 ) ); - line->addVertex( pointFromPointXY( p2 ) ); + line->addVertex( fromPointXY( p1 ) ); + line->addVertex( fromPointXY( p2 ) ); mTempRubberBand->setGeometry( line.release() ); mTempRubberBand->show(); diff --git a/src/app/qgsmaptoolcirclecenterpoint.cpp b/src/app/qgsmaptoolcirclecenterpoint.cpp index f8cd74256da7..912f322bc3b9 100644 --- a/src/app/qgsmaptoolcirclecenterpoint.cpp +++ b/src/app/qgsmaptoolcirclecenterpoint.cpp @@ -29,7 +29,7 @@ QgsMapToolCircleCenterPoint::QgsMapToolCircleCenterPoint( QgsMapToolCapture *par void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -54,7 +54,7 @@ void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircleCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { mCircle = QgsCircle().fromCenterPoint( mPoints.at( 0 ), mapPoint ); diff --git a/src/app/qgsmaptoolcircularstringcurvepoint.cpp b/src/app/qgsmaptoolcircularstringcurvepoint.cpp index 221c5de521d7..6df902877b82 100644 --- a/src/app/qgsmaptoolcircularstringcurvepoint.cpp +++ b/src/app/qgsmaptoolcircularstringcurvepoint.cpp @@ -29,7 +29,7 @@ QgsMapToolCircularStringCurvePoint::QgsMapToolCircularStringCurvePoint( QgsMapTo void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { diff --git a/src/app/qgsmaptoolcircularstringradius.cpp b/src/app/qgsmaptoolcircularstringradius.cpp index 6f8fd1ee913a..42186c3cd533 100644 --- a/src/app/qgsmaptoolcircularstringradius.cpp +++ b/src/app/qgsmaptoolcircularstringradius.cpp @@ -43,7 +43,7 @@ void QgsMapToolCircularStringRadius::deactivate() void QgsMapToolCircularStringRadius::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = pointFromPointXY( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -55,7 +55,7 @@ void QgsMapToolCircularStringRadius::cadCanvasReleaseEvent( QgsMapMouseEvent *e { if ( mPoints.size() % 2 ) { - mTemporaryEndPoint = pointFromPointXY( mapPoint ); + mTemporaryEndPoint = fromPointXY( mapPoint ); //initial radius is distance( tempPoint - mPoints.last ) / 2.0 double minRadius = std::sqrt( QgsGeometryUtils::sqrDistance2D( mPoints.last(), mTemporaryEndPoint ) ) / 2.0; @@ -136,7 +136,7 @@ void QgsMapToolCircularStringRadius::recalculateTempRubberBand( const QgsPointXY else { rubberBandPoints.append( mPoints.last() ); - rubberBandPoints.append( pointFromPointXY( mousePosition ) ); + rubberBandPoints.append( fromPointXY( mousePosition ) ); } QgsCircularString *cString = new QgsCircularString(); cString->setPoints( rubberBandPoints ); diff --git a/src/gui/qgsmaptoolcapture.cpp b/src/gui/qgsmaptoolcapture.cpp index cf9f4fad4c06..cea448008eeb 100644 --- a/src/gui/qgsmaptoolcapture.cpp +++ b/src/gui/qgsmaptoolcapture.cpp @@ -768,7 +768,7 @@ void QgsMapToolCapture::setPoints( const QVector &pointList ) mSnappingMatches.append( QgsPointLocator::Match() ); } -QgsPoint QgsMapToolCapture::pointFromPointXY( const QgsPointXY &point ) const +QgsPoint QgsMapToolCapture::fromPointXY( const QgsPointXY &point ) const { QgsPoint newPoint( QgsWkbTypes::Point, point.x(), point.y() ); diff --git a/src/gui/qgsmaptoolcapture.h b/src/gui/qgsmaptoolcapture.h index 36580d12bb5f..b764610c31b3 100644 --- a/src/gui/qgsmaptoolcapture.h +++ b/src/gui/qgsmaptoolcapture.h @@ -157,7 +157,7 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing * * \since QGIS 3.0 */ - QgsPoint pointFromPointXY( const QgsPointXY &point ) const; + QgsPoint fromPointXY( const QgsPointXY &point ) const; /** * Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates) From 79cdaa6092b17417c9a1b5dd6b90e550cff66156 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 15:32:34 +0000 Subject: [PATCH 06/23] Add Z support for AddEllipse map tools --- src/app/qgsmaptoolellipsecenter2points.cpp | 4 ++-- src/app/qgsmaptoolellipsecenterpoint.cpp | 4 ++-- src/app/qgsmaptoolellipseextent.cpp | 4 ++-- src/app/qgsmaptoolellipsefoci.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/app/qgsmaptoolellipsecenter2points.cpp b/src/app/qgsmaptoolellipsecenter2points.cpp index 8a1fd3f14cfb..d477cfb59e9c 100644 --- a/src/app/qgsmaptoolellipsecenter2points.cpp +++ b/src/app/qgsmaptoolellipsecenter2points.cpp @@ -30,7 +30,7 @@ QgsMapToolEllipseCenter2Points::QgsMapToolEllipseCenter2Points( QgsMapToolCaptur void QgsMapToolEllipseCenter2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -56,7 +56,7 @@ void QgsMapToolEllipseCenter2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolEllipseCenter2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { diff --git a/src/app/qgsmaptoolellipsecenterpoint.cpp b/src/app/qgsmaptoolellipsecenterpoint.cpp index 94d4ce3f7b48..8f265becdd0c 100644 --- a/src/app/qgsmaptoolellipsecenterpoint.cpp +++ b/src/app/qgsmaptoolellipsecenterpoint.cpp @@ -28,7 +28,7 @@ QgsMapToolEllipseCenterPoint::QgsMapToolEllipseCenterPoint( QgsMapToolCapture *p void QgsMapToolEllipseCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -52,7 +52,7 @@ void QgsMapToolEllipseCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolEllipseCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { mEllipse = QgsEllipse().fromCenterPoint( mPoints.at( 0 ), mapPoint ); diff --git a/src/app/qgsmaptoolellipseextent.cpp b/src/app/qgsmaptoolellipseextent.cpp index a3ccdbbba318..3177b33ead55 100644 --- a/src/app/qgsmaptoolellipseextent.cpp +++ b/src/app/qgsmaptoolellipseextent.cpp @@ -30,7 +30,7 @@ QgsMapToolEllipseExtent::QgsMapToolEllipseExtent( QgsMapToolCapture *parentTool, void QgsMapToolEllipseExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -54,7 +54,7 @@ void QgsMapToolEllipseExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolEllipseExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { diff --git a/src/app/qgsmaptoolellipsefoci.cpp b/src/app/qgsmaptoolellipsefoci.cpp index 1fc1a33249e0..0319a786b812 100644 --- a/src/app/qgsmaptoolellipsefoci.cpp +++ b/src/app/qgsmaptoolellipsefoci.cpp @@ -30,7 +30,7 @@ QgsMapToolEllipseFoci::QgsMapToolEllipseFoci( QgsMapToolCapture *parentTool, void QgsMapToolEllipseFoci::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -54,7 +54,7 @@ void QgsMapToolEllipseFoci::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolEllipseFoci::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { From 4c6d03cac63b626cafad42113f9d3f707906a971 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 16:35:12 +0000 Subject: [PATCH 07/23] Add Z support for AddRectangle map tools --- src/app/qgsmaptooladdrectangle.cpp | 17 +++++++++-------- src/app/qgsmaptooladdrectangle.h | 4 ++-- src/app/qgsmaptoolrectangle3points.cpp | 17 +++++++++-------- src/app/qgsmaptoolrectanglecenter.cpp | 8 ++++---- src/app/qgsmaptoolrectangleextent.cpp | 8 ++++---- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/app/qgsmaptooladdrectangle.cpp b/src/app/qgsmaptooladdrectangle.cpp index ad3a0cd74a36..78a2ad7654bd 100644 --- a/src/app/qgsmaptooladdrectangle.cpp +++ b/src/app/qgsmaptooladdrectangle.cpp @@ -84,12 +84,12 @@ void QgsMapToolAddRectangle::keyReleaseEvent( QKeyEvent *e ) QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOriented ) const { std::unique_ptr ext( new QgsLineString() ); - if ( mRectangle.isEmpty() ) + if ( mRectangle.toRectangle().isEmpty() ) { return ext.release(); } - QgsPoint x0( mRectangle.xMinimum(), mRectangle.yMinimum() ); + QgsPoint x0( mRectangle.xMinimum(), mRectangle.yMinimum(), mRectangle.zMinimum() ); QgsPoint x1, x2, x3; if ( isOriented ) @@ -101,10 +101,11 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien } else { - x1 = QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum() ); - x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() ); - x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() ); + x1 = QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum(), mRectangle.zMinimum() ); + x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum(), mRectangle.zMinimum() ); + x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum(), mRectangle.zMinimum() ); } + ext->addVertex( x0 ); ext->addVertex( x1 ); ext->addVertex( x2 ); @@ -117,7 +118,7 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien QgsPolygon *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) const { std::unique_ptr polygon( new QgsPolygon() ); - if ( mRectangle.isEmpty() ) + if ( mRectangle.toRectangle().isEmpty() ) { return polygon.release(); } @@ -129,7 +130,7 @@ QgsPolygon *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) void QgsMapToolAddRectangle::deactivate( const bool isOriented ) { - if ( !mParentTool || mRectangle.isEmpty() ) + if ( !mParentTool || mRectangle.toRectangle().isEmpty() ) { return; } @@ -162,5 +163,5 @@ void QgsMapToolAddRectangle::clean() mParentTool->deleteTempRubberBand(); } - mRectangle = QgsRectangle(); + mRectangle = QgsBox3d(); } diff --git a/src/app/qgsmaptooladdrectangle.h b/src/app/qgsmaptooladdrectangle.h index ced2c2103376..47b7cdc9f760 100644 --- a/src/app/qgsmaptooladdrectangle.h +++ b/src/app/qgsmaptooladdrectangle.h @@ -17,8 +17,8 @@ #define QGSMAPTOOLADDRECTANGLE_H #include "qgspolygon.h" -#include "qgsrectangle.h" #include "qgsmaptoolcapture.h" +#include "qgsbox3d.h" class QgsPolygon; @@ -51,7 +51,7 @@ class QgsMapToolAddRectangle: public QgsMapToolCapture //! The rubberband to show the rectangle currently working on QgsGeometryRubberBand *mTempRubberBand = nullptr; //! Rectangle - QgsRectangle mRectangle; + QgsBox3d mRectangle; //! Convenient method to export a QgsRectangle to a LineString QgsLineString *rectangleToLinestring( const bool isOriented = false ) const; diff --git a/src/app/qgsmaptoolrectangle3points.cpp b/src/app/qgsmaptoolrectangle3points.cpp index 0dfd51c2eb72..256d2f94df0b 100644 --- a/src/app/qgsmaptoolrectangle3points.cpp +++ b/src/app/qgsmaptoolrectangle3points.cpp @@ -31,7 +31,7 @@ QgsMapToolRectangle3Points::QgsMapToolRectangle3Points( QgsMapToolCapture *paren void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -56,7 +56,7 @@ void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { @@ -82,14 +82,15 @@ void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) setSide( side < 0 ? -1 : 1 ); - double xMin = mPoints.at( 0 ).x(); - double xMax = mPoints.at( 0 ).x() + distance2( ); + const double xMin = mPoints.at( 0 ).x(); + const double xMax = mPoints.at( 0 ).x() + distance2( ); - double yMin = mPoints.at( 0 ).y(); - double yMax = mPoints.at( 0 ).y() + distance1(); + const double yMin = mPoints.at( 0 ).y(); + const double yMax = mPoints.at( 0 ).y() + distance1(); - mRectangle = QgsRectangle( xMin, yMin, - xMax, yMax ); + const double z = mPoints.at( 0 ).z(); + + mRectangle = QgsBox3d( xMin, yMin, z, xMax, yMax, z ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon( true ) ); diff --git a/src/app/qgsmaptoolrectanglecenter.cpp b/src/app/qgsmaptoolrectanglecenter.cpp index f13a9727d414..897f855ae9a3 100644 --- a/src/app/qgsmaptoolrectanglecenter.cpp +++ b/src/app/qgsmaptoolrectanglecenter.cpp @@ -31,7 +31,7 @@ QgsMapToolRectangleCenter::QgsMapToolRectangleCenter( QgsMapToolCapture *parentT void QgsMapToolRectangleCenter::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -55,7 +55,7 @@ void QgsMapToolRectangleCenter::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolRectangleCenter::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { @@ -68,7 +68,7 @@ void QgsMapToolRectangleCenter::cadCanvasMoveEvent( QgsMapMouseEvent *e ) double xOffset = fabs( mapPoint.x() - mPoints.at( 0 ).x() ); double yOffset = fabs( mapPoint.y() - mPoints.at( 0 ).y() ); - mRectangle = QgsRectangle( QgsPoint( mPoints.at( 0 ).x() - xOffset, mPoints.at( 0 ).y() - yOffset ), QgsPoint( mPoints.at( 0 ).x() + xOffset, mPoints.at( 0 ).y() + yOffset ) ); + mRectangle = QgsBox3d( QgsPoint( mPoints.at( 0 ).x() - xOffset, mPoints.at( 0 ).y() - yOffset, mPoints.at( 0 ).z() ), QgsPoint( mPoints.at( 0 ).x() + xOffset, mPoints.at( 0 ).y() + yOffset, mPoints.at( 0 ).z() ) ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon() ); } @@ -77,7 +77,7 @@ void QgsMapToolRectangleCenter::cadCanvasMoveEvent( QgsMapMouseEvent *e ) double dist = mPoints.at( 0 ).distance( mapPoint ); double angle = mPoints.at( 0 ).azimuth( mapPoint ); - mRectangle = QgsRectangle( mPoints.at( 0 ).project( -dist, angle ), mPoints.at( 0 ).project( dist, angle ) ); + mRectangle = QgsBox3d( mPoints.at( 0 ).project( -dist, angle ), mPoints.at( 0 ).project( dist, angle ) ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon() ); } } diff --git a/src/app/qgsmaptoolrectangleextent.cpp b/src/app/qgsmaptoolrectangleextent.cpp index 6ecd89916f42..5ddc11dfcb38 100644 --- a/src/app/qgsmaptoolrectangleextent.cpp +++ b/src/app/qgsmaptoolrectangleextent.cpp @@ -31,7 +31,7 @@ QgsMapToolRectangleExtent::QgsMapToolRectangleExtent( QgsMapToolCapture *parentT void QgsMapToolRectangleExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -55,7 +55,7 @@ void QgsMapToolRectangleExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolRectangleExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { @@ -65,7 +65,7 @@ void QgsMapToolRectangleExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { if ( qgsDoubleNear( mCanvas->rotation(), 0.0 ) ) { - mRectangle = QgsRectangle( mPoints.at( 0 ), mapPoint ); + mRectangle = QgsBox3d( mPoints.at( 0 ), mapPoint ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon( ) ); } else @@ -73,7 +73,7 @@ void QgsMapToolRectangleExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) double dist = mPoints.at( 0 ).distance( mapPoint ); double angle = mPoints.at( 0 ).azimuth( mapPoint ); - mRectangle = QgsRectangle( mPoints.at( 0 ), mPoints.at( 0 ).project( dist, angle ) ); + mRectangle = QgsBox3d( mPoints.at( 0 ), mPoints.at( 0 ).project( dist, angle ) ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon() ); } } From 4bfc7b786e7c9db59f7644462a1a5244546bcc64 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 7 Dec 2017 16:42:08 +0000 Subject: [PATCH 08/23] Add Z support to AddRegularPolygon map tools --- src/app/qgsmaptoolregularpolygon2points.cpp | 4 ++-- src/app/qgsmaptoolregularpolygoncentercorner.cpp | 4 ++-- src/app/qgsmaptoolregularpolygoncenterpoint.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/qgsmaptoolregularpolygon2points.cpp b/src/app/qgsmaptoolregularpolygon2points.cpp index b86ef3936868..bac93850ece1 100644 --- a/src/app/qgsmaptoolregularpolygon2points.cpp +++ b/src/app/qgsmaptoolregularpolygon2points.cpp @@ -36,7 +36,7 @@ QgsMapToolRegularPolygon2Points::~QgsMapToolRegularPolygon2Points() void QgsMapToolRegularPolygon2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -65,7 +65,7 @@ void QgsMapToolRegularPolygon2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolRegularPolygon2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), mapPoint, mNumberSidesSpinBox->value() ); diff --git a/src/app/qgsmaptoolregularpolygoncentercorner.cpp b/src/app/qgsmaptoolregularpolygoncentercorner.cpp index a0c86d935cc0..41b631be4dab 100644 --- a/src/app/qgsmaptoolregularpolygoncentercorner.cpp +++ b/src/app/qgsmaptoolregularpolygoncentercorner.cpp @@ -33,7 +33,7 @@ QgsMapToolRegularPolygonCenterCorner::~QgsMapToolRegularPolygonCenterCorner() void QgsMapToolRegularPolygonCenterCorner::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -62,7 +62,7 @@ void QgsMapToolRegularPolygonCenterCorner::cadCanvasReleaseEvent( QgsMapMouseEve void QgsMapToolRegularPolygonCenterCorner::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { QgsRegularPolygon::ConstructionOption option = QgsRegularPolygon::InscribedCircle; diff --git a/src/app/qgsmaptoolregularpolygoncenterpoint.cpp b/src/app/qgsmaptoolregularpolygoncenterpoint.cpp index 3958fff1479e..de293b161116 100644 --- a/src/app/qgsmaptoolregularpolygoncenterpoint.cpp +++ b/src/app/qgsmaptoolregularpolygoncenterpoint.cpp @@ -33,7 +33,7 @@ QgsMapToolRegularPolygonCenterPoint::~QgsMapToolRegularPolygonCenterPoint() void QgsMapToolRegularPolygonCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( e->button() == Qt::LeftButton ) { @@ -62,7 +62,7 @@ void QgsMapToolRegularPolygonCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEven void QgsMapToolRegularPolygonCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint( e->mapPoint() ); + QgsPoint mapPoint = fromPointXY( e->mapPoint() ); if ( mTempRubberBand ) { QgsRegularPolygon::ConstructionOption option = QgsRegularPolygon::CircumscribedCircle; From d2ed783de2e48e1fa8dfb3ee211f14eb5e66afee Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Thu, 4 Jan 2018 13:46:22 +0000 Subject: [PATCH 09/23] Add test for z values on QgsMapToolAddFeature with LineStringZ --- tests/src/app/testqgsmaptooladdfeature.cpp | 58 +++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/tests/src/app/testqgsmaptooladdfeature.cpp b/tests/src/app/testqgsmaptooladdfeature.cpp index 8a68ffc8ceb0..e490fbda3d45 100644 --- a/tests/src/app/testqgsmaptooladdfeature.cpp +++ b/tests/src/app/testqgsmaptooladdfeature.cpp @@ -23,6 +23,7 @@ #include "qgsmaptooladdfeature.h" #include "qgsmapcanvastracer.h" #include "qgsproject.h" +#include "qgssettings.h" #include "qgsvectorlayer.h" @@ -81,6 +82,7 @@ class TestQgsMapToolAddFeature : public QObject void testNoTracing(); void testTracing(); void testTracingWithOffset(); + void testZ(); private: QPoint mapToScreen( double mapX, double mapY ) @@ -129,6 +131,7 @@ class TestQgsMapToolAddFeature : public QObject QAction *mEnableTracingAction = nullptr; QgsMapToolAddFeature *mCaptureTool = nullptr; QgsVectorLayer *mLayerLine = nullptr; + QgsVectorLayer *mLayerLineZ = nullptr; QgsFeatureId mFidLineF1 = 0; }; @@ -172,6 +175,20 @@ void TestQgsMapToolAddFeature::initTestCase() // just one added feature QCOMPARE( mLayerLine->undoStack()->index(), 1 ); + // make testing layers + mLayerLineZ = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayerLineZ->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayerLineZ ); + + QgsPolyline line2; + line2 << QgsPoint( 1, 1, 0 ) << QgsPoint( 2, 1, 1 ) << QgsPoint( 3, 2, 2 ) << QgsPoint( 1, 2, 3 ) << QgsPoint( 1, 1, 0 ); + QgsFeature lineF2; + lineF2.setGeometry( QgsGeometry::fromPolyline( line2 ) ); + + mLayerLineZ->startEditing(); + mLayerLineZ->addFeature( lineF2 ); + QCOMPARE( mLayerLineZ->featureCount(), ( long )1 ); + mCanvas->setFrameStyle( QFrame::NoFrame ); mCanvas->resize( 512, 512 ); mCanvas->setExtent( QgsRectangle( 0, 0, 8, 8 ) ); @@ -180,7 +197,7 @@ void TestQgsMapToolAddFeature::initTestCase() QCOMPARE( mCanvas->mapSettings().outputSize(), QSize( 512, 512 ) ); QCOMPARE( mCanvas->mapSettings().visibleExtent(), QgsRectangle( 0, 0, 8, 8 ) ); - mCanvas->setLayers( QList() << mLayerLine ); //<< mLayerPolygon << mLayerPoint ); + mCanvas->setLayers( QList() << mLayerLine << mLayerLineZ ); //<< mLayerPolygon << mLayerPoint ); mCanvas->setSnappingUtils( new QgsMapCanvasSnappingUtils( mCanvas, this ) ); @@ -346,6 +363,45 @@ void TestQgsMapToolAddFeature::testTracingWithOffset() mEnableTracingAction->setChecked( false ); } +void TestQgsMapToolAddFeature::testZ() +{ + mCanvas->setCurrentLayer( mLayerLineZ ); + + // test with default Z value = 333 + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); + + QSet oldFids = _existingFeatureIds( mLayerLineZ ); + mouseClick( 4, 0, Qt::LeftButton ); + mouseClick( 5, 0, Qt::LeftButton ); + mouseClick( 5, 1, Qt::LeftButton ); + mouseClick( 4, 1, Qt::LeftButton ); + mouseClick( 4, 1, Qt::RightButton ); + QgsFeatureId newFid = _newFeatureId( mLayerLineZ, oldFids ); + + QString wkt = "LineStringZ (4 0 333, 5 0 333, 5 1 333, 4 1 333)"; + QCOMPARE( mLayerLineZ->getFeature( newFid ).geometry(), QgsGeometry::fromWkt( wkt ) ); + + mLayerLine->undoStack()->undo(); + + // test with default Z value = 222 + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 222 ); + + oldFids = _existingFeatureIds( mLayerLineZ ); + mouseClick( 4, 0, Qt::LeftButton ); + mouseClick( 5, 0, Qt::LeftButton ); + mouseClick( 5, 1, Qt::LeftButton ); + mouseClick( 4, 1, Qt::LeftButton ); + mouseClick( 4, 1, Qt::RightButton ); + newFid = _newFeatureId( mLayerLineZ, oldFids ); + + wkt = "LineStringZ (4 0 222, 5 0 222, 5 1 222, 4 1 222)"; + QCOMPARE( mLayerLineZ->getFeature( newFid ).geometry(), QgsGeometry::fromWkt( wkt ) ); + + mLayerLine->undoStack()->undo(); + + mCanvas->setCurrentLayer( mLayerLine ); +} + QGSTEST_MAIN( TestQgsMapToolAddFeature ) #include "testqgsmaptooladdfeature.moc" From 47ba3a026edac8f2b60ea07a9513dbc753c3f4f9 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 08:32:33 +0000 Subject: [PATCH 10/23] Fixes variables' names --- src/app/qgsmaptoolcircle2tangentspoint.cpp | 8 ++++---- src/core/geometry/qgsgeometryutils.cpp | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index 51a4974d8660..6f8b564ee040 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -175,16 +175,16 @@ void QgsMapToolCircle2TangentsPoint::getPossibleCenter( ) QgsPoint inter; QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect ); - mCenters.append( QgsPointXY( inter ) ); + mCenters.append( QgsPoint( inter ) ); QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect ); - mCenters.append( QgsPointXY( inter ) ); + mCenters.append( QgsPoint( inter ) ); QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ), QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect ); - mCenters.append( QgsPointXY( inter ) ); + mCenters.append( QgsPoint( inter ) ); QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ), QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect ); - mCenters.append( QgsPointXY( inter ) ); + mCenters.append( QgsPoint( inter ) ); } } diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index f99f58e8d63b..e932f379b26c 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -254,18 +254,17 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v1, const { z = p1.z(); } - else if ( q1.is3D() ) + else if ( p2.is3D() ) { - z = q1.z(); + z = p2.z(); } if ( ! std::isnan( z ) ) { - inter.convertTo( QgsWkbTypes::addZ( inter.wkbType() ) ); - inter.setZ( z ); + intersection.convertTo( QgsWkbTypes::addZ( intersection.wkbType() ) ); + intersection.setZ( z ); } - return true; } From 916e4bae2ed0ef550f6a3b12a6035a3b9721f903 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 08:46:36 +0000 Subject: [PATCH 11/23] Add some tests for circular string map tools --- src/app/qgisapp.cpp | 1 + src/app/qgsmaptooladdcircularstring.h | 3 +- src/app/qgsmaptoolcircularstringcurvepoint.h | 3 +- src/app/qgsmaptoolcircularstringradius.h | 3 +- tests/src/app/CMakeLists.txt | 1 + .../src/app/testqgsmaptoolcircularstring.cpp | 133 ++++++++++++++++++ tests/src/app/testqgsmaptoolutils.h | 99 +++++++++++++ 7 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 tests/src/app/testqgsmaptoolcircularstring.cpp create mode 100644 tests/src/app/testqgsmaptoolutils.h diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index d7081ff03fca..6c9233293c1e 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -1311,6 +1311,7 @@ QgisApp::QgisApp() mMapCanvas->freeze(); mLayerTreeView = new QgsLayerTreeView( this ); mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas ); + mUserInputDockWidget = new QgsUserInputDockWidget( this ); mInfoBar = new QgsMessageBar( centralWidget() ); mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this ); mPanelMenu = new QMenu( this ); diff --git a/src/app/qgsmaptooladdcircularstring.h b/src/app/qgsmaptooladdcircularstring.h index ab9ad56f321e..d959b4714394 100644 --- a/src/app/qgsmaptooladdcircularstring.h +++ b/src/app/qgsmaptooladdcircularstring.h @@ -17,10 +17,11 @@ #define QGSMAPTOOLADDCIRCULARSTRING_H #include "qgsmaptoolcapture.h" +#include "qgis_app.h" class QgsGeometryRubberBand; -class QgsMapToolAddCircularString: public QgsMapToolCapture +class APP_EXPORT QgsMapToolAddCircularString: public QgsMapToolCapture { Q_OBJECT public: diff --git a/src/app/qgsmaptoolcircularstringcurvepoint.h b/src/app/qgsmaptoolcircularstringcurvepoint.h index bf4accaa099b..125af7a7fcda 100644 --- a/src/app/qgsmaptoolcircularstringcurvepoint.h +++ b/src/app/qgsmaptoolcircularstringcurvepoint.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLCIRCULARSTRINGCURVEPOINT_H #include "qgsmaptooladdcircularstring.h" +#include "qgis_app.h" -class QgsMapToolCircularStringCurvePoint: public QgsMapToolAddCircularString +class APP_EXPORT QgsMapToolCircularStringCurvePoint: public QgsMapToolAddCircularString { Q_OBJECT diff --git a/src/app/qgsmaptoolcircularstringradius.h b/src/app/qgsmaptoolcircularstringradius.h index 948789b057dd..68435f077abe 100644 --- a/src/app/qgsmaptoolcircularstringradius.h +++ b/src/app/qgsmaptoolcircularstringradius.h @@ -19,10 +19,11 @@ #include "qgsmaptooladdcircularstring.h" #include "qgspoint.h" +#include "qgis_app.h" class QDoubleSpinBox; -class QgsMapToolCircularStringRadius: public QgsMapToolAddCircularString +class APP_EXPORT QgsMapToolCircularStringRadius: public QgsMapToolAddCircularString { Q_OBJECT public: diff --git a/tests/src/app/CMakeLists.txt b/tests/src/app/CMakeLists.txt index 3f31e918868a..c969c6fb958b 100644 --- a/tests/src/app/CMakeLists.txt +++ b/tests/src/app/CMakeLists.txt @@ -99,6 +99,7 @@ ADD_QGIS_TEST(maptooladdfeature testqgsmaptooladdfeature.cpp) ADD_QGIS_TEST(maptoolidentifyaction testqgsmaptoolidentifyaction.cpp) ADD_QGIS_TEST(maptoolselect testqgsmaptoolselect.cpp) ADD_QGIS_TEST(maptoolreshape testqgsmaptoolreshape.cpp) +ADD_QGIS_TEST(maptoolcircularstringtest testqgsmaptoolcircularstring.cpp) ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp) ADD_QGIS_TEST(vertextool testqgsvertextool.cpp) ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp) diff --git a/tests/src/app/testqgsmaptoolcircularstring.cpp b/tests/src/app/testqgsmaptoolcircularstring.cpp new file mode 100644 index 000000000000..fa5d2a9f72cd --- /dev/null +++ b/tests/src/app/testqgsmaptoolcircularstring.cpp @@ -0,0 +1,133 @@ +/*************************************************************************** + testqgsmaptoolcircularstring.cpp + -------------------------------- + Date : January 2018 + Copyright : (C) 2018 by Paul Blottiere + Email : paul.blottiere@oslandia.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" + +#include "qgisapp.h" +#include "qgsgeometry.h" +#include "qgsmapcanvas.h" +#include "qgssettings.h" +#include "qgsvectorlayer.h" +#include "qgsmaptooladdfeature.h" + +#include "testqgsmaptoolutils.h" +#include "qgsmaptoolcircularstringcurvepoint.h" +#include "qgsmaptoolcircularstringradius.h" + + +class TestQgsMapToolCircularString : public QObject +{ + Q_OBJECT + + public: + TestQgsMapToolCircularString(); + + private slots: + void initTestCase(); + void cleanupTestCase(); + + void testAddCircularStringCurvePoint(); + void testAddCircularStringRadius(); + + private: + QgisApp *mQgisApp = nullptr; + QgsMapToolCapture *mParentTool = nullptr; + QgsMapCanvas *mCanvas = nullptr; + QgsVectorLayer *mLayer = nullptr; +}; + +TestQgsMapToolCircularString::TestQgsMapToolCircularString() = default; + + +//runs before all tests +void TestQgsMapToolCircularString::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + + mQgisApp = new QgisApp(); + + mCanvas = new QgsMapCanvas(); + mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:27700" ) ) ); + + // make testing layers + mLayer = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayer->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayer ); + + // set layers in canvas + mCanvas->setLayers( QList() << mLayer ); + mCanvas->setCurrentLayer( mLayer ); + + mParentTool = new QgsMapToolAddFeature( mCanvas, QgsMapToolCapture::CaptureLine ); +} + +void TestQgsMapToolCircularString::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsMapToolCircularString::testAddCircularStringCurvePoint() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); + mLayer->startEditing(); + + QgsMapToolCircularStringCurvePoint mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseClick( 1, 1, Qt::LeftButton ); + utils.mouseClick( 0, 2, Qt::LeftButton ); + utils.mouseClick( 0, 2, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "CompoundCurveZ (CircularStringZ (0 0 333, 1 1 333, 0 2 333))"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolCircularString::testAddCircularStringRadius() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 111 ); + mLayer->startEditing(); + + QgsMapToolCircularStringRadius mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseClick( 1, 1, Qt::LeftButton ); + utils.mouseClick( 0, 2, Qt::LeftButton ); + utils.mouseClick( 0, 2, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "CompoundCurveZ (CircularStringZ (0 0 111, 0.17912878474779187 0.82087121525220819 111, 1 1 111))"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +QGSTEST_MAIN( TestQgsMapToolCircularString ) +#include "testqgsmaptoolcircularstring.moc" diff --git a/tests/src/app/testqgsmaptoolutils.h b/tests/src/app/testqgsmaptoolutils.h new file mode 100644 index 000000000000..a4ca407eb3cc --- /dev/null +++ b/tests/src/app/testqgsmaptoolutils.h @@ -0,0 +1,99 @@ +/*************************************************************************** + testqgsmaptoolutils.h + --------------------- + Date : January 2018 + Copyright : (C) 2018 by Paul Blottiere + Email : paul.blottiere@oslandia.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" + +#include "qgisapp.h" +#include "qgsgeometry.h" +#include "qgsmapcanvas.h" +#include "qgsvectorlayer.h" + +/** + * \ingroup UnitTests + */ +class TestQgsMapToolAdvancedDigitizingUtils +{ + public: + TestQgsMapToolAdvancedDigitizingUtils( QgsMapToolAdvancedDigitizing *mapTool ) + : mMapTool( mapTool ) + { + } + + QSet existingFeatureIds() + { + QSet fids; + QgsVectorLayer *vl = qobject_cast( mMapTool->canvas()->currentLayer() ); + + if ( vl ) + { + QgsFeature f; + QgsFeatureIterator it = vl->getFeatures(); + while ( it.nextFeature( f ) ) + fids << f.id(); + } + + return fids; + } + + QgsFeatureId newFeatureId( QSet oldFids = QSet() ) + { + QSet newFids = existingFeatureIds(); + QSet diffFids = newFids.subtract( oldFids ); + Q_ASSERT( diffFids.count() == 1 ); + return *diffFids.constBegin(); + } + + QPoint mapToScreen( double mapX, double mapY ) + { + QgsPointXY pt = mMapTool->canvas()->mapSettings().mapToPixel().transform( mapX, mapY ); + return QPoint( std::round( pt.x() ), std::round( pt.y() ) ); + } + + void mouseMove( double mapX, double mapY ) + { + QgsMapMouseEvent e( mMapTool->canvas(), QEvent::MouseMove, mapToScreen( mapX, mapY ) ); + mMapTool->cadCanvasMoveEvent( &e ); + } + + void mousePress( double mapX, double mapY, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers() ) + { + QgsMapMouseEvent e1( mMapTool->canvas(), QEvent::MouseButtonPress, mapToScreen( mapX, mapY ), button, button, stateKey ); + mMapTool->cadCanvasPressEvent( &e1 ); + } + + void mouseRelease( double mapX, double mapY, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers() ) + { + QgsMapMouseEvent e2( mMapTool->canvas(), QEvent::MouseButtonRelease, mapToScreen( mapX, mapY ), button, Qt::MouseButton(), stateKey ); + mMapTool->cadCanvasReleaseEvent( &e2 ); + } + + void mouseClick( double mapX, double mapY, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers() ) + { + mousePress( mapX, mapY, button, stateKey ); + mouseRelease( mapX, mapY, button, stateKey ); + } + + void keyClick( int key ) + { + QKeyEvent e1( QEvent::KeyPress, key, Qt::KeyboardModifiers() ); + mMapTool->keyPressEvent( &e1 ); + + QKeyEvent e2( QEvent::KeyRelease, key, Qt::KeyboardModifiers() ); + mMapTool->keyReleaseEvent( &e2 ); + } + + private: + QgsMapToolAdvancedDigitizing *mMapTool = nullptr; +}; From 58610b429871d4c80a593717f1b35a7903e199cd Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 09:16:54 +0000 Subject: [PATCH 12/23] Add some tests for circle map tools --- src/app/qgsmaptooladdcircle.h | 3 +- src/app/qgsmaptoolcircle2points.h | 3 +- src/app/qgsmaptoolcircle3points.h | 3 +- src/app/qgsmaptoolcirclecenterpoint.h | 3 +- tests/src/app/CMakeLists.txt | 1 + tests/src/app/testqgsmaptoolcircle.cpp | 158 +++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 tests/src/app/testqgsmaptoolcircle.cpp diff --git a/src/app/qgsmaptooladdcircle.h b/src/app/qgsmaptooladdcircle.h index a5168495e1d6..5cb989077be9 100644 --- a/src/app/qgsmaptooladdcircle.h +++ b/src/app/qgsmaptooladdcircle.h @@ -18,6 +18,7 @@ #include "qgsmaptoolcapture.h" #include "qgscircle.h" +#include "qgis_app.h" class QgsGeometryRubberBand; @@ -26,7 +27,7 @@ struct EdgesOnlyFilter : public QgsPointLocator::MatchFilter bool acceptMatch( const QgsPointLocator::Match &m ) override { return m.hasEdge(); } }; -class QgsMapToolAddCircle: public QgsMapToolCapture +class APP_EXPORT QgsMapToolAddCircle: public QgsMapToolCapture { Q_OBJECT diff --git a/src/app/qgsmaptoolcircle2points.h b/src/app/qgsmaptoolcircle2points.h index 7a012740203b..cbbe99d0034e 100644 --- a/src/app/qgsmaptoolcircle2points.h +++ b/src/app/qgsmaptoolcircle2points.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLCIRCLE2POINTS_H #include "qgsmaptooladdcircle.h" +#include "qgis_app.h" -class QgsMapToolCircle2Points: public QgsMapToolAddCircle +class APP_EXPORT QgsMapToolCircle2Points: public QgsMapToolAddCircle { Q_OBJECT diff --git a/src/app/qgsmaptoolcircle3points.h b/src/app/qgsmaptoolcircle3points.h index 516231041cff..dbe680c069a1 100644 --- a/src/app/qgsmaptoolcircle3points.h +++ b/src/app/qgsmaptoolcircle3points.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLCIRCLE3POINTS_H #include "qgsmaptooladdcircle.h" +#include "qgis_app.h" -class QgsMapToolCircle3Points: public QgsMapToolAddCircle +class APP_EXPORT QgsMapToolCircle3Points: public QgsMapToolAddCircle { Q_OBJECT diff --git a/src/app/qgsmaptoolcirclecenterpoint.h b/src/app/qgsmaptoolcirclecenterpoint.h index 27ddfcdad72f..f60f0f36d622 100644 --- a/src/app/qgsmaptoolcirclecenterpoint.h +++ b/src/app/qgsmaptoolcirclecenterpoint.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLCIRCLECENTERPOINT_H #include "qgsmaptooladdcircle.h" +#include "qgis_app.h" -class QgsMapToolCircleCenterPoint: public QgsMapToolAddCircle +class APP_EXPORT QgsMapToolCircleCenterPoint: public QgsMapToolAddCircle { Q_OBJECT diff --git a/tests/src/app/CMakeLists.txt b/tests/src/app/CMakeLists.txt index c969c6fb958b..e954e72b4299 100644 --- a/tests/src/app/CMakeLists.txt +++ b/tests/src/app/CMakeLists.txt @@ -100,6 +100,7 @@ ADD_QGIS_TEST(maptoolidentifyaction testqgsmaptoolidentifyaction.cpp) ADD_QGIS_TEST(maptoolselect testqgsmaptoolselect.cpp) ADD_QGIS_TEST(maptoolreshape testqgsmaptoolreshape.cpp) ADD_QGIS_TEST(maptoolcircularstringtest testqgsmaptoolcircularstring.cpp) +ADD_QGIS_TEST(maptoolcircletest testqgsmaptoolcircle.cpp) ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp) ADD_QGIS_TEST(vertextool testqgsvertextool.cpp) ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp) diff --git a/tests/src/app/testqgsmaptoolcircle.cpp b/tests/src/app/testqgsmaptoolcircle.cpp new file mode 100644 index 000000000000..c0472226bcf7 --- /dev/null +++ b/tests/src/app/testqgsmaptoolcircle.cpp @@ -0,0 +1,158 @@ +/*************************************************************************** + testqgsmaptoolcircle.cpp + ------------------------ + Date : January 2018 + Copyright : (C) 2018 by Paul Blottiere + Email : paul.blottiere@oslandia.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" + +#include "qgisapp.h" +#include "qgsgeometry.h" +#include "qgsmapcanvas.h" +#include "qgssettings.h" +#include "qgsvectorlayer.h" +#include "qgsmaptooladdfeature.h" + +#include "testqgsmaptoolutils.h" +#include "qgsmaptoolcircle2points.h" +#include "qgsmaptoolcircle3points.h" +#include "qgsmaptoolcirclecenterpoint.h" + + +class TestQgsMapToolCircle : public QObject +{ + Q_OBJECT + + public: + TestQgsMapToolCircle(); + + private slots: + void initTestCase(); + void cleanupTestCase(); + + void testCircleFrom2Points(); + void testCircleFrom3Points(); + void testCircleFromCenterPoint(); + + private: + QgisApp *mQgisApp = nullptr; + QgsMapToolCapture *mParentTool = nullptr; + QgsMapCanvas *mCanvas = nullptr; + QgsVectorLayer *mLayer = nullptr; +}; + +TestQgsMapToolCircle::TestQgsMapToolCircle() = default; + + +//runs before all tests +void TestQgsMapToolCircle::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + + mQgisApp = new QgisApp(); + + mCanvas = new QgsMapCanvas(); + mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:27700" ) ) ); + + // make testing layers + mLayer = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayer->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayer ); + + // set layers in canvas + mCanvas->setLayers( QList() << mLayer ); + mCanvas->setCurrentLayer( mLayer ); + + mParentTool = new QgsMapToolAddFeature( mCanvas, QgsMapToolCapture::CaptureLine ); +} + +void TestQgsMapToolCircle::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsMapToolCircle::testCircleFrom2Points() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); + mLayer->startEditing(); + + QgsMapToolCircle2Points mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 0, 2 ); + utils.mouseClick( 0, 2, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "CompoundCurveZ (CircularStringZ (0 2 333, 1 1 333, 0 0 333, -1 1 333, 0 2 333))"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolCircle::testCircleFrom3Points() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 111 ); + mLayer->startEditing(); + + QgsMapToolCircle3Points mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseClick( 0, 2, Qt::LeftButton ); + utils.mouseMove( 1, 1 ); + utils.mouseClick( 1, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "CompoundCurveZ (CircularStringZ (0 2 111, 1 1 111, 0 0 111, -1 1 111, 0 2 111))"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolCircle::testCircleFromCenterPoint() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 222 ); + mLayer->startEditing(); + + QgsMapToolCircleCenterPoint mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 0, 2 ); + utils.mouseClick( 0, 2, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "CompoundCurveZ (CircularStringZ (0 2 222, 2 0 222, 0 -2 222, -2 0 222, 0 2 222))"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +QGSTEST_MAIN( TestQgsMapToolCircle ) +#include "testqgsmaptoolcircle.moc" From 868c869e88713ac807b474be041c2f02dbf95c65 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 10:16:03 +0000 Subject: [PATCH 13/23] Add some tests for ellipse map tools --- src/app/qgsmaptooladdellipse.h | 3 +- src/app/qgsmaptoolellipsecenter2points.h | 3 +- src/app/qgsmaptoolellipsecenterpoint.h | 3 +- src/app/qgsmaptoolellipseextent.h | 3 +- src/app/qgsmaptoolellipsefoci.h | 3 +- tests/src/app/CMakeLists.txt | 1 + tests/src/app/testqgsmaptoolellipse.cpp | 206 +++++++++++++++++++++++ 7 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 tests/src/app/testqgsmaptoolellipse.cpp diff --git a/src/app/qgsmaptooladdellipse.h b/src/app/qgsmaptooladdellipse.h index e0cd7818934b..74874f7f8944 100644 --- a/src/app/qgsmaptooladdellipse.h +++ b/src/app/qgsmaptooladdellipse.h @@ -19,10 +19,11 @@ #include "qgsmaptoolcapture.h" #include "qgsellipse.h" #include "qgssettings.h" +#include "qgis_app.h" class QgsGeometryRubberBand; -class QgsMapToolAddEllipse: public QgsMapToolCapture +class APP_EXPORT QgsMapToolAddEllipse: public QgsMapToolCapture { Q_OBJECT public: diff --git a/src/app/qgsmaptoolellipsecenter2points.h b/src/app/qgsmaptoolellipsecenter2points.h index 957010a7ca35..ec9168424b79 100644 --- a/src/app/qgsmaptoolellipsecenter2points.h +++ b/src/app/qgsmaptoolellipsecenter2points.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLELLIPSECENTER2POINTS_H #include "qgsmaptooladdellipse.h" +#include "qgis_app.h" -class QgsMapToolEllipseCenter2Points: public QgsMapToolAddEllipse +class APP_EXPORT QgsMapToolEllipseCenter2Points: public QgsMapToolAddEllipse { Q_OBJECT diff --git a/src/app/qgsmaptoolellipsecenterpoint.h b/src/app/qgsmaptoolellipsecenterpoint.h index cbde0d5ec13d..17ccc17afd22 100644 --- a/src/app/qgsmaptoolellipsecenterpoint.h +++ b/src/app/qgsmaptoolellipsecenterpoint.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLELLIPSECENTERPOINT_H #include "qgsmaptooladdellipse.h" +#include "qgis_app.h" -class QgsMapToolEllipseCenterPoint: public QgsMapToolAddEllipse +class APP_EXPORT QgsMapToolEllipseCenterPoint: public QgsMapToolAddEllipse { Q_OBJECT diff --git a/src/app/qgsmaptoolellipseextent.h b/src/app/qgsmaptoolellipseextent.h index 9114dec1f551..df0a40779a3a 100644 --- a/src/app/qgsmaptoolellipseextent.h +++ b/src/app/qgsmaptoolellipseextent.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLELLIPSEEXTENT_H #include "qgsmaptooladdellipse.h" +#include "qgis_app.h" -class QgsMapToolEllipseExtent: public QgsMapToolAddEllipse +class APP_EXPORT QgsMapToolEllipseExtent: public QgsMapToolAddEllipse { Q_OBJECT diff --git a/src/app/qgsmaptoolellipsefoci.h b/src/app/qgsmaptoolellipsefoci.h index f80cc59898f0..501081ec1af1 100644 --- a/src/app/qgsmaptoolellipsefoci.h +++ b/src/app/qgsmaptoolellipsefoci.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLELLIPSEFOCI_H #include "qgsmaptooladdellipse.h" +#include "qgis_app.h" -class QgsMapToolEllipseFoci: public QgsMapToolAddEllipse +class APP_EXPORT QgsMapToolEllipseFoci: public QgsMapToolAddEllipse { Q_OBJECT diff --git a/tests/src/app/CMakeLists.txt b/tests/src/app/CMakeLists.txt index e954e72b4299..c82f4b30b9fd 100644 --- a/tests/src/app/CMakeLists.txt +++ b/tests/src/app/CMakeLists.txt @@ -101,6 +101,7 @@ ADD_QGIS_TEST(maptoolselect testqgsmaptoolselect.cpp) ADD_QGIS_TEST(maptoolreshape testqgsmaptoolreshape.cpp) ADD_QGIS_TEST(maptoolcircularstringtest testqgsmaptoolcircularstring.cpp) ADD_QGIS_TEST(maptoolcircletest testqgsmaptoolcircle.cpp) +ADD_QGIS_TEST(maptoolellipsetest testqgsmaptoolellipse.cpp) ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp) ADD_QGIS_TEST(vertextool testqgsvertextool.cpp) ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp) diff --git a/tests/src/app/testqgsmaptoolellipse.cpp b/tests/src/app/testqgsmaptoolellipse.cpp new file mode 100644 index 000000000000..0d6dcacf41ec --- /dev/null +++ b/tests/src/app/testqgsmaptoolellipse.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** + testqgsmaptoolellipse.cpp + ------------------------ + Date : January 2018 + Copyright : (C) 2018 by Paul Blottiere + Email : paul.blottiere@oslandia.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" + +#include "qgisapp.h" +#include "qgsgeometry.h" +#include "qgsmapcanvas.h" +#include "qgssettings.h" +#include "qgsvectorlayer.h" +#include "qgsmaptooladdfeature.h" +#include "qgsgeometryutils.h" + +#include "testqgsmaptoolutils.h" +#include "qgsmaptoolellipsecenterpoint.h" +#include "qgsmaptoolellipsecenter2points.h" +#include "qgsmaptoolellipseextent.h" +#include "qgsmaptoolellipsefoci.h" + + +class TestQgsMapToolEllipse : public QObject +{ + Q_OBJECT + + public: + TestQgsMapToolEllipse(); + + private slots: + void initTestCase(); + void cleanupTestCase(); + + void testEllipseFromCenterAndPoint(); + void testEllipseFromCenterAnd2Points(); + void testEllipseFromExtent(); + void testEllipseFromFoci(); + + private: + QgisApp *mQgisApp = nullptr; + QgsMapToolCapture *mParentTool = nullptr; + QgsMapCanvas *mCanvas = nullptr; + QgsVectorLayer *mLayer = nullptr; +}; + +TestQgsMapToolEllipse::TestQgsMapToolEllipse() = default; + + +//runs before all tests +void TestQgsMapToolEllipse::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + + mQgisApp = new QgisApp(); + + mCanvas = new QgsMapCanvas(); + mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:27700" ) ) ); + + // make testing layers + mLayer = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayer->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayer ); + + // set layers in canvas + mCanvas->setLayers( QList() << mLayer ); + mCanvas->setCurrentLayer( mLayer ); + + mParentTool = new QgsMapToolAddFeature( mCanvas, QgsMapToolCapture::CaptureLine ); +} + +void TestQgsMapToolEllipse::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsMapToolEllipse::testEllipseFromCenterAndPoint() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); + mLayer->startEditing(); + + QgsMapToolEllipseCenterPoint mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 1, -1 ); + utils.mouseClick( 1, -1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = f.geometry().asWkt().replace( "LineStringZ (", "" ).replace( ")", "" ); + QgsPointSequence pts = QgsGeometryUtils::pointsFromWKT( wkt, true, false ); + + for ( const QgsPoint &pt : pts ) + { + QCOMPARE( pt.z(), ( double )333 ); + } + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolEllipse::testEllipseFromCenterAnd2Points() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 111 ); + mLayer->startEditing(); + + QgsMapToolEllipseCenter2Points mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseClick( 0, 1, Qt::LeftButton ); + utils.mouseMove( 0, -1 ); + utils.mouseClick( 0, -1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = f.geometry().asWkt().replace( "LineStringZ (", "" ).replace( ")", "" ); + QgsPointSequence pts = QgsGeometryUtils::pointsFromWKT( wkt, true, false ); + + for ( const QgsPoint &pt : pts ) + { + QCOMPARE( pt.z(), ( double )111 ); + } + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolEllipse::testEllipseFromExtent() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 222 ); + mLayer->startEditing(); + + QgsMapToolEllipseExtent mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 2 ); + utils.mouseClick( 2, 2, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = f.geometry().asWkt().replace( "LineStringZ (", "" ).replace( ")", "" ); + QgsPointSequence pts = QgsGeometryUtils::pointsFromWKT( wkt, true, false ); + + for ( const QgsPoint &pt : pts ) + { + QCOMPARE( pt.z(), ( double )222 ); + } + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolEllipse::testEllipseFromFoci() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 444 ); + mLayer->startEditing(); + + QgsMapToolEllipseFoci mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseClick( 0, 2, Qt::LeftButton ); + utils.mouseMove( 0, -1 ); + utils.mouseClick( 0, -1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = f.geometry().asWkt().replace( "LineStringZ (", "" ).replace( ")", "" ); + QgsPointSequence pts = QgsGeometryUtils::pointsFromWKT( wkt, true, false ); + + for ( const QgsPoint &pt : pts ) + { + QCOMPARE( pt.z(), ( double )444 ); + } + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +QGSTEST_MAIN( TestQgsMapToolEllipse ) +#include "testqgsmaptoolellipse.moc" From d7860e25b0e725d1a80f744b97458799f01c09a8 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 10:35:41 +0000 Subject: [PATCH 14/23] Add some tests for ellipse map tools --- src/app/qgsmaptooladdrectangle.h | 3 +- src/app/qgsmaptoolrectangle3points.h | 3 +- src/app/qgsmaptoolrectanglecenter.h | 3 +- src/app/qgsmaptoolrectangleextent.h | 3 +- tests/src/app/CMakeLists.txt | 1 + tests/src/app/testqgsmaptoolrectangle.cpp | 160 ++++++++++++++++++++++ 6 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 tests/src/app/testqgsmaptoolrectangle.cpp diff --git a/src/app/qgsmaptooladdrectangle.h b/src/app/qgsmaptooladdrectangle.h index 47b7cdc9f760..1834b2c1bc5f 100644 --- a/src/app/qgsmaptooladdrectangle.h +++ b/src/app/qgsmaptooladdrectangle.h @@ -19,10 +19,11 @@ #include "qgspolygon.h" #include "qgsmaptoolcapture.h" #include "qgsbox3d.h" +#include "qgis_app.h" class QgsPolygon; -class QgsMapToolAddRectangle: public QgsMapToolCapture +class APP_EXPORT QgsMapToolAddRectangle: public QgsMapToolCapture { Q_OBJECT diff --git a/src/app/qgsmaptoolrectangle3points.h b/src/app/qgsmaptoolrectangle3points.h index 9f65ac740ea1..b993d62dfab9 100644 --- a/src/app/qgsmaptoolrectangle3points.h +++ b/src/app/qgsmaptoolrectangle3points.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLRECTANGLE3POINTS_H #include "qgsmaptooladdrectangle.h" +#include "qgis_app.h" -class QgsMapToolRectangle3Points: public QgsMapToolAddRectangle +class APP_EXPORT QgsMapToolRectangle3Points: public QgsMapToolAddRectangle { Q_OBJECT diff --git a/src/app/qgsmaptoolrectanglecenter.h b/src/app/qgsmaptoolrectanglecenter.h index 7081cac5b630..61ba72c679d4 100644 --- a/src/app/qgsmaptoolrectanglecenter.h +++ b/src/app/qgsmaptoolrectanglecenter.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLRECTANGLECENTER_H #include "qgsmaptooladdrectangle.h" +#include "qgis_app.h" -class QgsMapToolRectangleCenter: public QgsMapToolAddRectangle +class APP_EXPORT QgsMapToolRectangleCenter: public QgsMapToolAddRectangle { Q_OBJECT diff --git a/src/app/qgsmaptoolrectangleextent.h b/src/app/qgsmaptoolrectangleextent.h index db9889919a88..cd6e559c5446 100644 --- a/src/app/qgsmaptoolrectangleextent.h +++ b/src/app/qgsmaptoolrectangleextent.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLRECTANGLEEXTENT_H #include "qgsmaptooladdrectangle.h" +#include "qgis_app.h" -class QgsMapToolRectangleExtent: public QgsMapToolAddRectangle +class APP_EXPORT QgsMapToolRectangleExtent: public QgsMapToolAddRectangle { Q_OBJECT diff --git a/tests/src/app/CMakeLists.txt b/tests/src/app/CMakeLists.txt index c82f4b30b9fd..3b07baf6e197 100644 --- a/tests/src/app/CMakeLists.txt +++ b/tests/src/app/CMakeLists.txt @@ -102,6 +102,7 @@ ADD_QGIS_TEST(maptoolreshape testqgsmaptoolreshape.cpp) ADD_QGIS_TEST(maptoolcircularstringtest testqgsmaptoolcircularstring.cpp) ADD_QGIS_TEST(maptoolcircletest testqgsmaptoolcircle.cpp) ADD_QGIS_TEST(maptoolellipsetest testqgsmaptoolellipse.cpp) +ADD_QGIS_TEST(maptoolrectangletest testqgsmaptoolrectangle.cpp) ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp) ADD_QGIS_TEST(vertextool testqgsvertextool.cpp) ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp) diff --git a/tests/src/app/testqgsmaptoolrectangle.cpp b/tests/src/app/testqgsmaptoolrectangle.cpp new file mode 100644 index 000000000000..6ec71730a989 --- /dev/null +++ b/tests/src/app/testqgsmaptoolrectangle.cpp @@ -0,0 +1,160 @@ +/*************************************************************************** + testqgsmaptoolrectangle.cpp + --------------------------- + Date : January 2018 + Copyright : (C) 2018 by Paul Blottiere + Email : paul.blottiere@oslandia.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" + +#include "qgisapp.h" +#include "qgsgeometry.h" +#include "qgsmapcanvas.h" +#include "qgssettings.h" +#include "qgsvectorlayer.h" +#include "qgsmaptooladdfeature.h" +#include "qgsgeometryutils.h" + +#include "testqgsmaptoolutils.h" +#include "qgsmaptoolrectanglecenter.h" +#include "qgsmaptoolrectangleextent.h" +#include "qgsmaptoolrectangle3points.h" + + +class TestQgsMapToolRectangle : public QObject +{ + Q_OBJECT + + public: + TestQgsMapToolRectangle(); + + private slots: + void initTestCase(); + void cleanupTestCase(); + + void testRectangleFromCenter(); + void testRectangleFromExtent(); + void testRectangleFrom3Points(); + + private: + QgisApp *mQgisApp = nullptr; + QgsMapToolCapture *mParentTool = nullptr; + QgsMapCanvas *mCanvas = nullptr; + QgsVectorLayer *mLayer = nullptr; +}; + +TestQgsMapToolRectangle::TestQgsMapToolRectangle() = default; + + +//runs before all tests +void TestQgsMapToolRectangle::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + + mQgisApp = new QgisApp(); + + mCanvas = new QgsMapCanvas(); + mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:27700" ) ) ); + + // make testing layers + mLayer = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayer->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayer ); + + // set layers in canvas + mCanvas->setLayers( QList() << mLayer ); + mCanvas->setCurrentLayer( mLayer ); + + mParentTool = new QgsMapToolAddFeature( mCanvas, QgsMapToolCapture::CaptureLine ); +} + +void TestQgsMapToolRectangle::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsMapToolRectangle::testRectangleFromCenter() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); + mLayer->startEditing(); + + QgsMapToolRectangleCenter mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 1 ); + utils.mouseClick( 2, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "LineStringZ (-2 -1 333, -2 1 333, 2 1 333, 2 -1 333, -2 -1 333)"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolRectangle::testRectangleFromExtent() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 222 ); + mLayer->startEditing(); + + QgsMapToolRectangleExtent mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 1 ); + utils.mouseClick( 2, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "LineStringZ (0 0 222, 0 1 222, 2 1 222, 2 0 222, 0 0 222)"; + QCOMPARE( f.geometry().asWkt(), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolRectangle::testRectangleFrom3Points() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 111 ); + mLayer->startEditing(); + + QgsMapToolRectangle3Points mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 0 ); + utils.mouseClick( 2, 0, Qt::LeftButton ); + utils.mouseMove( 2, 1 ); + utils.mouseClick( 2, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "LineStringZ (0 0 111, 2 0 111, 2 1 111, 0 1 111, 0 0 111)"; + QCOMPARE( f.geometry().asWkt( 0 ), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +QGSTEST_MAIN( TestQgsMapToolRectangle ) +#include "testqgsmaptoolrectangle.moc" From ce9e012be8307b76e09c982b937d6c9ab8e2e2ef Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 10:47:10 +0000 Subject: [PATCH 15/23] Add some tests for regular polygon map tools --- src/app/qgsmaptooladdregularpolygon.h | 3 +- src/app/qgsmaptoolregularpolygon2points.h | 3 +- .../qgsmaptoolregularpolygoncentercorner.h | 3 +- src/app/qgsmaptoolregularpolygoncenterpoint.h | 3 +- tests/src/app/CMakeLists.txt | 1 + .../src/app/testqgsmaptoolregularpolygon.cpp | 158 ++++++++++++++++++ 6 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 tests/src/app/testqgsmaptoolregularpolygon.cpp diff --git a/src/app/qgsmaptooladdregularpolygon.h b/src/app/qgsmaptooladdregularpolygon.h index c7543249dd41..6b2a25ab2ac2 100644 --- a/src/app/qgsmaptooladdregularpolygon.h +++ b/src/app/qgsmaptooladdregularpolygon.h @@ -19,10 +19,11 @@ #include "qgsregularpolygon.h" #include "qgsmaptoolcapture.h" #include "qgsspinbox.h" +#include "qgis_app.h" class QSpinBox; -class QgsMapToolAddRegularPolygon: public QgsMapToolCapture +class APP_EXPORT QgsMapToolAddRegularPolygon: public QgsMapToolCapture { Q_OBJECT diff --git a/src/app/qgsmaptoolregularpolygon2points.h b/src/app/qgsmaptoolregularpolygon2points.h index d38c05953ce1..eed15d807fba 100644 --- a/src/app/qgsmaptoolregularpolygon2points.h +++ b/src/app/qgsmaptoolregularpolygon2points.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLREGULARPOLYGON2POINTS_H #include "qgsmaptooladdregularpolygon.h" +#include "qgis_app.h" -class QgsMapToolRegularPolygon2Points: public QgsMapToolAddRegularPolygon +class APP_EXPORT QgsMapToolRegularPolygon2Points: public QgsMapToolAddRegularPolygon { Q_OBJECT diff --git a/src/app/qgsmaptoolregularpolygoncentercorner.h b/src/app/qgsmaptoolregularpolygoncentercorner.h index add900a3b73f..a7bff18b3f00 100644 --- a/src/app/qgsmaptoolregularpolygoncentercorner.h +++ b/src/app/qgsmaptoolregularpolygoncentercorner.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLREGULARPOLYGONCENTERCORNER_H #include "qgsmaptooladdregularpolygon.h" +#include "qgis_app.h" -class QgsMapToolRegularPolygonCenterCorner: public QgsMapToolAddRegularPolygon +class APP_EXPORT QgsMapToolRegularPolygonCenterCorner: public QgsMapToolAddRegularPolygon { Q_OBJECT diff --git a/src/app/qgsmaptoolregularpolygoncenterpoint.h b/src/app/qgsmaptoolregularpolygoncenterpoint.h index 45e07917f421..6af3a1bbb945 100644 --- a/src/app/qgsmaptoolregularpolygoncenterpoint.h +++ b/src/app/qgsmaptoolregularpolygoncenterpoint.h @@ -18,8 +18,9 @@ #define QGSMAPTOOLREGULARPOLYGONCENTERPOINT_H #include "qgsmaptooladdregularpolygon.h" +#include "qgis_app.h" -class QgsMapToolRegularPolygonCenterPoint: public QgsMapToolAddRegularPolygon +class APP_EXPORT QgsMapToolRegularPolygonCenterPoint: public QgsMapToolAddRegularPolygon { Q_OBJECT diff --git a/tests/src/app/CMakeLists.txt b/tests/src/app/CMakeLists.txt index 3b07baf6e197..0ccb505467e0 100644 --- a/tests/src/app/CMakeLists.txt +++ b/tests/src/app/CMakeLists.txt @@ -103,6 +103,7 @@ ADD_QGIS_TEST(maptoolcircularstringtest testqgsmaptoolcircularstring.cpp) ADD_QGIS_TEST(maptoolcircletest testqgsmaptoolcircle.cpp) ADD_QGIS_TEST(maptoolellipsetest testqgsmaptoolellipse.cpp) ADD_QGIS_TEST(maptoolrectangletest testqgsmaptoolrectangle.cpp) +ADD_QGIS_TEST(maptoolregularpolygontest testqgsmaptoolregularpolygon.cpp) ADD_QGIS_TEST(measuretool testqgsmeasuretool.cpp) ADD_QGIS_TEST(vertextool testqgsvertextool.cpp) ADD_QGIS_TEST(vectorlayersaveasdialogtest testqgsvectorlayersaveasdialog.cpp) diff --git a/tests/src/app/testqgsmaptoolregularpolygon.cpp b/tests/src/app/testqgsmaptoolregularpolygon.cpp new file mode 100644 index 000000000000..2176518e3359 --- /dev/null +++ b/tests/src/app/testqgsmaptoolregularpolygon.cpp @@ -0,0 +1,158 @@ +/*************************************************************************** + testqgsmaptoolregularpolygon.cpp + --------------------------- + Date : January 2018 + Copyright : (C) 2018 by Paul Blottiere + Email : paul.blottiere@oslandia.com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" + +#include "qgisapp.h" +#include "qgsgeometry.h" +#include "qgsmapcanvas.h" +#include "qgssettings.h" +#include "qgsvectorlayer.h" +#include "qgsmaptooladdfeature.h" +#include "qgsgeometryutils.h" + +#include "testqgsmaptoolutils.h" +#include "qgsmaptoolregularpolygon2points.h" +#include "qgsmaptoolregularpolygoncenterpoint.h" +#include "qgsmaptoolregularpolygoncentercorner.h" + + +class TestQgsMapToolRegularPolygon : public QObject +{ + Q_OBJECT + + public: + TestQgsMapToolRegularPolygon(); + + private slots: + void initTestCase(); + void cleanupTestCase(); + + void testRegularPolygonFrom2Points(); + void testRegularPolygonFromCenterAndPoint(); + void testRegularPolygonFromCenterAndCroner(); + + private: + QgisApp *mQgisApp = nullptr; + QgsMapToolCapture *mParentTool = nullptr; + QgsMapCanvas *mCanvas = nullptr; + QgsVectorLayer *mLayer = nullptr; +}; + +TestQgsMapToolRegularPolygon::TestQgsMapToolRegularPolygon() = default; + + +//runs before all tests +void TestQgsMapToolRegularPolygon::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + + mQgisApp = new QgisApp(); + + mCanvas = new QgsMapCanvas(); + mCanvas->setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:27700" ) ) ); + + // make testing layers + mLayer = new QgsVectorLayer( QStringLiteral( "LineStringZ?crs=EPSG:27700" ), QStringLiteral( "layer line Z" ), QStringLiteral( "memory" ) ); + QVERIFY( mLayer->isValid() ); + QgsProject::instance()->addMapLayers( QList() << mLayer ); + + // set layers in canvas + mCanvas->setLayers( QList() << mLayer ); + mCanvas->setCurrentLayer( mLayer ); + + mParentTool = new QgsMapToolAddFeature( mCanvas, QgsMapToolCapture::CaptureLine ); +} + +void TestQgsMapToolRegularPolygon::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsMapToolRegularPolygon::testRegularPolygonFrom2Points() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); + mLayer->startEditing(); + + QgsMapToolRegularPolygon2Points mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 1 ); + utils.mouseClick( 2, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "LineStringZ (0 0 333, 2 1 333, 4 -0 333, 4 -2 333, 2 -3 333, -0 -2 333, 0 0 333)"; + QCOMPARE( f.geometry().asWkt( 0 ), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolRegularPolygon::testRegularPolygonFromCenterAndPoint() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 222 ); + mLayer->startEditing(); + + QgsMapToolRegularPolygonCenterPoint mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 1 ); + utils.mouseClick( 2, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "LineStringZ (1 2 222, 3 -0 222, 1 -2 222, -1 -2 222, -3 0 222, -1 2 222, 1 2 222)"; + QCOMPARE( f.geometry().asWkt( 0 ), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +void TestQgsMapToolRegularPolygon::testRegularPolygonFromCenterAndCroner() +{ + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 111 ); + mLayer->startEditing(); + + QgsMapToolRegularPolygonCenterCorner mapTool( mParentTool, mCanvas ); + mCanvas->setMapTool( &mapTool ); + + TestQgsMapToolAdvancedDigitizingUtils utils( &mapTool ); + utils.mouseClick( 0, 0, Qt::LeftButton ); + utils.mouseMove( 2, 1 ); + utils.mouseClick( 2, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId(); + + QCOMPARE( mLayer->featureCount(), ( long )1 ); + QgsFeature f = mLayer->getFeature( newFid ); + + QString wkt = "LineStringZ (2 1 111, 2 -1 111, -0 -2 111, -2 -1 111, -2 1 111, 0 2 111, 2 1 111)"; + QCOMPARE( f.geometry().asWkt( 0 ), wkt ); + + mLayer->rollBack(); + QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 0 ); +} + +QGSTEST_MAIN( TestQgsMapToolRegularPolygon ) +#include "testqgsmaptoolregularpolygon.moc" From 76a57b834588507dfb05162331b7a27ebb3a4dfa Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 14:04:46 +0000 Subject: [PATCH 16/23] The first point in 3D is used to propagate Z dimension --- python/core/geometry/qgsgeometryutils.sip.in | 11 ++++ src/core/geometry/qgscircle.cpp | 35 +++++------- src/core/geometry/qgsellipse.cpp | 14 ++++- src/core/geometry/qgsgeometryutils.cpp | 57 ++++++++------------ src/core/geometry/qgsgeometryutils.h | 10 ++++ src/core/geometry/qgstriangle.cpp | 23 ++------ 6 files changed, 71 insertions(+), 79 deletions(-) diff --git a/python/core/geometry/qgsgeometryutils.sip.in b/python/core/geometry/qgsgeometryutils.sip.in index 76aed6403281..f1b292caf31f 100644 --- a/python/core/geometry/qgsgeometryutils.sip.in +++ b/python/core/geometry/qgsgeometryutils.sip.in @@ -388,6 +388,17 @@ Return the coefficients (a, b, c for equation "ax + by + c = 0") of a line defin :return: A line (segment) from p to perpendicular point on segment [s1, s2] %End + static bool setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point ); +%Docstring +A Z dimension is added to ``point`` if one of the point in the list +``points`` is in 3D. Moreover, the Z value of ``point`` is updated with. + +:param points: List of points in which a 3D point is searched. +:param point: The point to update with Z dimension and value. + +:return: true if the point is updated, false otherwise +%End + }; diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index 046d50be48e8..96373bb112e2 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -40,6 +40,8 @@ QgsCircle QgsCircle::from2Points( const QgsPoint &pt1, const QgsPoint &pt2 ) double azimuth = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ) * 180.0 / M_PI; double radius = pt1.distance( pt2 ) / 2.0; + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center ); + return QgsCircle( center, radius, azimuth ); } @@ -138,26 +140,8 @@ QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, cons double aSlope = yDelta_a / xDelta_a; double bSlope = yDelta_b / xDelta_b; - // set z cooridnate for center - double z = std::numeric_limits::quiet_NaN(); - if ( p1.is3D() ) - { - z = p1.z(); - } - else if ( p2.is3D() ) - { - z = p2.z(); - } - else if ( p3.is3D() ) - { - z = p3.z(); - } - - if ( ! std::isnan( z ) ) - { - center.convertTo( QgsWkbTypes::addZ( center.wkbType() ) ); - center.setZ( z ); - } + // set z coordinate for center + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2 << p3, center ); if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) ) { @@ -197,7 +181,11 @@ QgsCircle QgsCircle::fromCenterDiameter( const QgsPoint ¢er, double diameter QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt1 ) { double azimuth = QgsGeometryUtils::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI; - return QgsCircle( center, center.distance( pt1 ), azimuth ); + + QgsPoint centerPt( center ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1, centerPt ); + + return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth ); } QgsCircle QgsCircle::from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon ) @@ -242,7 +230,10 @@ QgsCircle QgsCircle::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ) return QgsCircle(); } - return QgsCircle( QgsGeometryUtils::midpoint( pt1, pt2 ), delta_x / 2.0, 0 ); + QgsPoint center = QgsGeometryUtils::midpoint( pt1, pt2 ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center ); + + return QgsCircle( center, delta_x / 2.0, 0 ); } double QgsCircle::area() const diff --git a/src/core/geometry/qgsellipse.cpp b/src/core/geometry/qgsellipse.cpp index ab9cf4df2060..6e01f32029f5 100644 --- a/src/core/geometry/qgsellipse.cpp +++ b/src/core/geometry/qgsellipse.cpp @@ -57,6 +57,8 @@ QgsEllipse QgsEllipse::fromFoci( const QgsPoint &pt1, const QgsPoint &pt2, const double axis_a = dist / 2.0; double axis_b = std::sqrt( std::pow( axis_a, 2.0 ) - std::pow( dist_p1p2 / 2.0, 2.0 ) ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2 << pt3, center ); + return QgsEllipse( center, axis_a, axis_b, azimuth ); } @@ -67,6 +69,8 @@ QgsEllipse QgsEllipse::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ) double axis_b = std::fabs( pt2.y() - pt1.y() ) / 2.0; double azimuth = 90.0; + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center ); + return QgsEllipse( center, axis_a, axis_b, azimuth ); } @@ -76,7 +80,10 @@ QgsEllipse QgsEllipse::fromCenterPoint( const QgsPoint ¢er, const QgsPoint & double axis_b = std::fabs( pt1.y() - center.y() ); double azimuth = 90.0; - return QgsEllipse( center, axis_a, axis_b, azimuth ); + QgsPoint centerPt( center ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1, centerPt ); + + return QgsEllipse( centerPt, axis_a, axis_b, azimuth ); } QgsEllipse QgsEllipse::fromCenter2Points( const QgsPoint ¢er, const QgsPoint &pt1, const QgsPoint &pt2 ) @@ -88,7 +95,10 @@ QgsEllipse QgsEllipse::fromCenter2Points( const QgsPoint ¢er, const QgsPoint QgsPoint pp = center.project( length, 90 + azimuth ); double axis_b = center.distance( pp ); - return QgsEllipse( center, axis_a, axis_b, azimuth ); + QgsPoint centerPt( center ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, centerPt ); + + return QgsEllipse( centerPt, axis_a, axis_b, azimuth ); } bool QgsEllipse::operator ==( const QgsEllipse &elp ) const diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index e932f379b26c..96fb7287713b 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -248,22 +248,8 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v1, const intersection = QgsPoint( p1.x() + v1.x() * k, p1.y() + v1.y() * k ); - // z support for inter point - double z = std::numeric_limits::quiet_NaN(); - if ( p1.is3D() ) - { - z = p1.z(); - } - else if ( p2.is3D() ) - { - z = p2.z(); - } - - if ( ! std::isnan( z ) ) - { - intersection.convertTo( QgsWkbTypes::addZ( intersection.wkbType() ) ); - intersection.setZ( z ); - } + // z support for intersection point + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2, intersection ); return true; } @@ -623,26 +609,7 @@ bool QgsGeometryUtils::segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2, result = possibleMidPoints.at( minDistIndex ); // add z support if necessary - double z = std::numeric_limits::quiet_NaN(); - - if ( p1.is3D() && p2.is3D() ) - { - z = ( p1.z() + p2.z() ) / 2.; - } - else if ( p1.is3D() && !p2.is3D() ) - { - z = p1.z(); - } - else if ( !p1.is3D() && p2.is3D() ) - { - z = p2.z(); - } - - if ( ! std::isnan( z ) ) - { - result.convertTo( QgsWkbTypes::addZ( result.wkbType() ) ); - result.setZ( z ); - } + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2, result ); return true; } @@ -1205,3 +1172,21 @@ double QgsGeometryUtils::averageAngle( double a1, double a2 ) } return normalizedAngle( resultAngle ); } + +bool QgsGeometryUtils::setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point ) +{ + bool rc = false; + + for ( const QgsPoint &pt : points ) + { + if ( pt.is3D() ) + { + point.convertTo( QgsWkbTypes::addZ( point.wkbType() ) ); + point.setZ( pt.z() ); + rc = true; + break; + } + } + + return rc; +} diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index a50fbe7e9cd9..666207464bd9 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -410,6 +410,16 @@ class CORE_EXPORT QgsGeometryUtils */ static QgsLineString perpendicularSegment( const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2 ); + /** + * A Z dimension is added to \a point if one of the point in the list + * \a points is in 3D. Moreover, the Z value of \a point is updated with. + * + * \param points List of points in which a 3D point is searched. + * \param point The point to update with Z dimension and value. + * \returns true if the point is updated, false otherwise + */ + static bool setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point ); + //! \note not available in Python bindings enum ComponentType SIP_SKIP { diff --git a/src/core/geometry/qgstriangle.cpp b/src/core/geometry/qgstriangle.cpp index cdd8e69d239f..75a205d48643 100644 --- a/src/core/geometry/qgstriangle.cpp +++ b/src/core/geometry/qgstriangle.cpp @@ -574,26 +574,11 @@ QgsPoint QgsTriangle::inscribedCenter() const l.at( 1 ) * vertexAt( 0 ).y() + l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter(); - double z = std::numeric_limits::quiet_NaN(); - if ( vertexAt( 0 ).is3D() ) - { - z = vertexAt( 0 ).z(); - } - else if ( vertexAt( 1 ).is3D() ) - { - z = vertexAt( 1 ).z(); - } - else if ( vertexAt( 2 ).is3D() ) - { - z = vertexAt( 2 ).z(); - } - QgsPoint center( x, y ); - if ( !std::isnan( z ) ) - { - center.convertTo( QgsWkbTypes::PointZ ); - center.setZ( z ); - } + + QgsPointSequence points; + points << vertexAt( 0 ) << vertexAt( 1 ) << vertexAt( 2 ); + QgsGeometryUtils::setZValueFromPoints( points, center ); return center; } From 12392f75b31817477554237a26d34c2eb3ea8558 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 5 Jan 2018 14:29:23 +0000 Subject: [PATCH 17/23] Some clean --- tests/src/app/testqgsmaptooladdfeature.cpp | 158 +++++++-------------- tests/src/app/testqgsmaptoolutils.h | 6 +- 2 files changed, 58 insertions(+), 106 deletions(-) diff --git a/tests/src/app/testqgsmaptooladdfeature.cpp b/tests/src/app/testqgsmaptooladdfeature.cpp index e490fbda3d45..547d6337658e 100644 --- a/tests/src/app/testqgsmaptooladdfeature.cpp +++ b/tests/src/app/testqgsmaptooladdfeature.cpp @@ -25,6 +25,7 @@ #include "qgsproject.h" #include "qgssettings.h" #include "qgsvectorlayer.h" +#include "testqgsmaptoolutils.h" bool operator==( const QgsGeometry &g1, const QgsGeometry &g2 ) @@ -45,25 +46,6 @@ namespace QTest } } -static QSet _existingFeatureIds( QgsVectorLayer *layer ) -{ - QSet fids; - QgsFeature f; - QgsFeatureIterator it = layer->getFeatures(); - while ( it.nextFeature( f ) ) - fids << f.id(); - return fids; -} - -static QgsFeatureId _newFeatureId( QgsVectorLayer *layer, QSet oldFids ) -{ - QSet newFids = _existingFeatureIds( layer ); - QSet diffFids = newFids.subtract( oldFids ); - Q_ASSERT( diffFids.count() == 1 ); - return *diffFids.constBegin(); -} - - /** * \ingroup UnitTests @@ -84,46 +66,6 @@ class TestQgsMapToolAddFeature : public QObject void testTracingWithOffset(); void testZ(); - private: - QPoint mapToScreen( double mapX, double mapY ) - { - QgsPointXY pt = mCanvas->mapSettings().mapToPixel().transform( mapX, mapY ); - return QPoint( std::round( pt.x() ), std::round( pt.y() ) ); - } - - void mouseMove( double mapX, double mapY ) - { - QgsMapMouseEvent e( mCanvas, QEvent::MouseMove, mapToScreen( mapX, mapY ) ); - mCaptureTool->cadCanvasMoveEvent( &e ); - } - - void mousePress( double mapX, double mapY, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers() ) - { - QgsMapMouseEvent e1( mCanvas, QEvent::MouseButtonPress, mapToScreen( mapX, mapY ), button, button, stateKey ); - mCaptureTool->cadCanvasPressEvent( &e1 ); - } - - void mouseRelease( double mapX, double mapY, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers() ) - { - QgsMapMouseEvent e2( mCanvas, QEvent::MouseButtonRelease, mapToScreen( mapX, mapY ), button, Qt::MouseButton(), stateKey ); - mCaptureTool->cadCanvasReleaseEvent( &e2 ); - } - - void mouseClick( double mapX, double mapY, Qt::MouseButton button, Qt::KeyboardModifiers stateKey = Qt::KeyboardModifiers() ) - { - mousePress( mapX, mapY, button, stateKey ); - mouseRelease( mapX, mapY, button, stateKey ); - } - - void keyClick( int key ) - { - QKeyEvent e1( QEvent::KeyPress, key, Qt::KeyboardModifiers() ); - mCaptureTool->keyPressEvent( &e1 ); - - QKeyEvent e2( QEvent::KeyRelease, key, Qt::KeyboardModifiers() ); - mCaptureTool->keyReleaseEvent( &e2 ); - } - private: QgisApp *mQgisApp = nullptr; QgsMapCanvas *mCanvas = nullptr; @@ -227,15 +169,17 @@ void TestQgsMapToolAddFeature::cleanupTestCase() void TestQgsMapToolAddFeature::testNoTracing() { + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + // tracing not enabled - will be straight line - QSet oldFids = _existingFeatureIds( mLayerLine ); + QSet oldFids = utils.existingFeatureIds(); - mouseClick( 1, 1, Qt::LeftButton ); - mouseClick( 3, 2, Qt::LeftButton ); - mouseClick( 3, 2, Qt::RightButton ); + utils.mouseClick( 1, 1, Qt::LeftButton ); + utils.mouseClick( 3, 2, Qt::LeftButton ); + utils.mouseClick( 3, 2, Qt::RightButton ); - QgsFeatureId newFid = _newFeatureId( mLayerLine, oldFids ); + QgsFeatureId newFid = utils.newFeatureId( oldFids ); QCOMPARE( mLayerLine->undoStack()->index(), 2 ); QCOMPARE( mLayerLine->getFeature( newFid ).geometry(), QgsGeometry::fromWkt( "LINESTRING(1 1, 3 2)" ) ); @@ -246,17 +190,19 @@ void TestQgsMapToolAddFeature::testNoTracing() void TestQgsMapToolAddFeature::testTracing() { + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + // tracing enabled - same clicks - now following line mEnableTracingAction->setChecked( true ); - QSet oldFids = _existingFeatureIds( mLayerLine ); + QSet oldFids = utils.existingFeatureIds(); - mouseClick( 1, 1, Qt::LeftButton ); - mouseClick( 3, 2, Qt::LeftButton ); - mouseClick( 3, 2, Qt::RightButton ); + utils.mouseClick( 1, 1, Qt::LeftButton ); + utils.mouseClick( 3, 2, Qt::LeftButton ); + utils.mouseClick( 3, 2, Qt::RightButton ); - QgsFeatureId newFid = _newFeatureId( mLayerLine, oldFids ); + QgsFeatureId newFid = utils.newFeatureId( oldFids ); QCOMPARE( mLayerLine->undoStack()->index(), 2 ); QCOMPARE( mLayerLine->getFeature( newFid ).geometry(), QgsGeometry::fromWkt( "LINESTRING(1 1, 2 1, 3 2)" ) ); @@ -268,13 +214,13 @@ void TestQgsMapToolAddFeature::testTracing() // tracing enabled - combined with first and last segments that are not traced - mouseClick( 0, 2, Qt::LeftButton ); - mouseClick( 1, 1, Qt::LeftButton ); - mouseClick( 3, 2, Qt::LeftButton ); - mouseClick( 4, 1, Qt::LeftButton ); - mouseClick( 4, 1, Qt::RightButton ); + utils.mouseClick( 0, 2, Qt::LeftButton ); + utils.mouseClick( 1, 1, Qt::LeftButton ); + utils.mouseClick( 3, 2, Qt::LeftButton ); + utils.mouseClick( 4, 1, Qt::LeftButton ); + utils.mouseClick( 4, 1, Qt::RightButton ); - QgsFeatureId newFid2 = _newFeatureId( mLayerLine, oldFids ); + QgsFeatureId newFid2 = utils.newFeatureId( oldFids ); QCOMPARE( mLayerLine->undoStack()->index(), 2 ); QCOMPARE( mLayerLine->getFeature( newFid2 ).geometry(), QgsGeometry::fromWkt( "LINESTRING(0 2, 1 1, 2 1, 3 2, 4 1)" ) ); @@ -289,18 +235,20 @@ void TestQgsMapToolAddFeature::testTracing() void TestQgsMapToolAddFeature::testTracingWithOffset() { + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + // tracing enabled + offset enabled mEnableTracingAction->setChecked( true ); mTracer->setOffset( 0.1 ); - QSet oldFids = _existingFeatureIds( mLayerLine ); + QSet oldFids = utils.existingFeatureIds(); - mouseClick( 2, 1, Qt::LeftButton ); - mouseClick( 1, 2, Qt::LeftButton ); - mouseClick( 1, 2, Qt::RightButton ); + utils.mouseClick( 2, 1, Qt::LeftButton ); + utils.mouseClick( 1, 2, Qt::LeftButton ); + utils.mouseClick( 1, 2, Qt::RightButton ); - QgsFeatureId newFid = _newFeatureId( mLayerLine, oldFids ); + QgsFeatureId newFid = utils.newFeatureId( oldFids ); QCOMPARE( mLayerLine->undoStack()->index(), 2 ); @@ -319,11 +267,11 @@ void TestQgsMapToolAddFeature::testTracingWithOffset() // use negative offset mTracer->setOffset( -0.1 ); - mouseClick( 2, 1, Qt::LeftButton ); - mouseClick( 1, 2, Qt::LeftButton ); - mouseClick( 1, 2, Qt::RightButton ); + utils.mouseClick( 2, 1, Qt::LeftButton ); + utils.mouseClick( 1, 2, Qt::LeftButton ); + utils.mouseClick( 1, 2, Qt::RightButton ); - QgsFeatureId newFid2 = _newFeatureId( mLayerLine, oldFids ); + QgsFeatureId newFid2 = utils.newFeatureId( oldFids ); QgsGeometry g2 = mLayerLine->getFeature( newFid2 ).geometry(); QgsPolylineXY poly2 = g2.asPolyline(); @@ -336,13 +284,13 @@ void TestQgsMapToolAddFeature::testTracingWithOffset() // tracing enabled + offset enabled - combined with first and last segments that are not traced - mouseClick( 3, 0, Qt::LeftButton ); - mouseClick( 2, 1, Qt::LeftButton ); - mouseClick( 1, 2, Qt::LeftButton ); - mouseClick( 0, 1, Qt::LeftButton ); - mouseClick( 0, 1, Qt::RightButton ); + utils.mouseClick( 3, 0, Qt::LeftButton ); + utils.mouseClick( 2, 1, Qt::LeftButton ); + utils.mouseClick( 1, 2, Qt::LeftButton ); + utils.mouseClick( 0, 1, Qt::LeftButton ); + utils.mouseClick( 0, 1, Qt::RightButton ); - QgsFeatureId newFid3 = _newFeatureId( mLayerLine, oldFids ); + QgsFeatureId newFid3 = utils.newFeatureId( oldFids ); QCOMPARE( mLayerLine->undoStack()->index(), 2 ); QgsGeometry g3 = mLayerLine->getFeature( newFid3 ).geometry(); @@ -365,18 +313,20 @@ void TestQgsMapToolAddFeature::testTracingWithOffset() void TestQgsMapToolAddFeature::testZ() { + TestQgsMapToolAdvancedDigitizingUtils utils( mCaptureTool ); + mCanvas->setCurrentLayer( mLayerLineZ ); // test with default Z value = 333 QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 333 ); - QSet oldFids = _existingFeatureIds( mLayerLineZ ); - mouseClick( 4, 0, Qt::LeftButton ); - mouseClick( 5, 0, Qt::LeftButton ); - mouseClick( 5, 1, Qt::LeftButton ); - mouseClick( 4, 1, Qt::LeftButton ); - mouseClick( 4, 1, Qt::RightButton ); - QgsFeatureId newFid = _newFeatureId( mLayerLineZ, oldFids ); + QSet oldFids = utils.existingFeatureIds(); + utils.mouseClick( 4, 0, Qt::LeftButton ); + utils.mouseClick( 5, 0, Qt::LeftButton ); + utils.mouseClick( 5, 1, Qt::LeftButton ); + utils.mouseClick( 4, 1, Qt::LeftButton ); + utils.mouseClick( 4, 1, Qt::RightButton ); + QgsFeatureId newFid = utils.newFeatureId( oldFids ); QString wkt = "LineStringZ (4 0 333, 5 0 333, 5 1 333, 4 1 333)"; QCOMPARE( mLayerLineZ->getFeature( newFid ).geometry(), QgsGeometry::fromWkt( wkt ) ); @@ -386,13 +336,13 @@ void TestQgsMapToolAddFeature::testZ() // test with default Z value = 222 QgsSettings().setValue( QStringLiteral( "/qgis/digitizing/default_z_value" ), 222 ); - oldFids = _existingFeatureIds( mLayerLineZ ); - mouseClick( 4, 0, Qt::LeftButton ); - mouseClick( 5, 0, Qt::LeftButton ); - mouseClick( 5, 1, Qt::LeftButton ); - mouseClick( 4, 1, Qt::LeftButton ); - mouseClick( 4, 1, Qt::RightButton ); - newFid = _newFeatureId( mLayerLineZ, oldFids ); + oldFids = utils.existingFeatureIds(); + utils.mouseClick( 4, 0, Qt::LeftButton ); + utils.mouseClick( 5, 0, Qt::LeftButton ); + utils.mouseClick( 5, 1, Qt::LeftButton ); + utils.mouseClick( 4, 1, Qt::LeftButton ); + utils.mouseClick( 4, 1, Qt::RightButton ); + newFid = utils.newFeatureId( oldFids ); wkt = "LineStringZ (4 0 222, 5 0 222, 5 1 222, 4 1 222)"; QCOMPARE( mLayerLineZ->getFeature( newFid ).geometry(), QgsGeometry::fromWkt( wkt ) ); diff --git a/tests/src/app/testqgsmaptoolutils.h b/tests/src/app/testqgsmaptoolutils.h index a4ca407eb3cc..45f3a025b37f 100644 --- a/tests/src/app/testqgsmaptoolutils.h +++ b/tests/src/app/testqgsmaptoolutils.h @@ -2,8 +2,10 @@ testqgsmaptoolutils.h --------------------- Date : January 2018 - Copyright : (C) 2018 by Paul Blottiere - Email : paul.blottiere@oslandia.com + Copyright : (C) 2017 by Martin Dobias + (C) 2018 by Paul Blottiere + Email : wonder dot sk at gmail dot com + paul.blottiere@oslandia.com *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * From d91bd457497065ef04cda3656c62995992796158 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Mon, 15 Jan 2018 08:30:53 +0000 Subject: [PATCH 18/23] Take into account z dimension from center points --- src/core/geometry/qgscircle.cpp | 2 +- src/core/geometry/qgsellipse.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index 96373bb112e2..77864754ea99 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -183,7 +183,7 @@ QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt double azimuth = QgsGeometryUtils::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI; QgsPoint centerPt( center ); - QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1, centerPt ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << center << pt1, centerPt ); return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth ); } diff --git a/src/core/geometry/qgsellipse.cpp b/src/core/geometry/qgsellipse.cpp index 6e01f32029f5..6561c57cd255 100644 --- a/src/core/geometry/qgsellipse.cpp +++ b/src/core/geometry/qgsellipse.cpp @@ -81,7 +81,7 @@ QgsEllipse QgsEllipse::fromCenterPoint( const QgsPoint ¢er, const QgsPoint & double azimuth = 90.0; QgsPoint centerPt( center ); - QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1, centerPt ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << center << pt1, centerPt ); return QgsEllipse( centerPt, axis_a, axis_b, azimuth ); } @@ -96,7 +96,7 @@ QgsEllipse QgsEllipse::fromCenter2Points( const QgsPoint ¢er, const QgsPoint double axis_b = center.distance( pp ); QgsPoint centerPt( center ); - QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, centerPt ); + QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << center << pt1 << pt2, centerPt ); return QgsEllipse( centerPt, axis_a, axis_b, azimuth ); } From 35d0f578078a37a0471142af151a0dc1aad67e5f Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Mon, 15 Jan 2018 08:31:12 +0000 Subject: [PATCH 19/23] Update documentation --- python/core/geometry/qgscircle.sip.in | 12 +++++++++--- python/core/geometry/qgsellipse.sip.in | 16 ++++++++++++---- python/core/geometry/qgsgeometryutils.sip.in | 10 ++++++++-- python/core/geometry/qgstriangle.sip.in | 3 ++- src/core/geometry/qgscircle.h | 12 +++++++++--- src/core/geometry/qgsellipse.h | 16 ++++++++++++---- src/core/geometry/qgsgeometryutils.h | 12 ++++++++++-- src/core/geometry/qgstriangle.h | 3 ++- 8 files changed, 64 insertions(+), 20 deletions(-) diff --git a/python/core/geometry/qgscircle.sip.in b/python/core/geometry/qgscircle.sip.in index 8c2ae188a4e6..9e35b30e18d4 100644 --- a/python/core/geometry/qgscircle.sip.in +++ b/python/core/geometry/qgscircle.sip.in @@ -42,7 +42,9 @@ Constructs a circle by defining all the members. static QgsCircle from2Points( const QgsPoint &pt1, const QgsPoint &pt2 ); %Docstring Constructs a circle by 2 points on the circle. -The center point can have z and m values which are the result from the midpoint operation between ``pt1`` and ``pt2``. +The center point can have m value which is the result from the midpoint +operation between ``pt1`` and ``pt2``. Z dimension is also supported and +is retrieved from the first 3D point amongst ``pt1`` and ``pt2``. The radius is calculated from the 2D distance between ``pt1`` and ``pt2``. The azimuth is the angle between ``pt1`` and ``pt2``. @@ -53,7 +55,9 @@ The azimuth is the angle between ``pt1`` and ``pt2``. static QgsCircle from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon = 1E-8 ); %Docstring Constructs a circle by 3 points on the circle. -Z and m values are dropped for the center point. +M value is dropped for the center point. +Z dimension is supported and is retrieved from the first 3D point +amongst ``pt1``, ``pt2`` and ``pt3``. The azimuth always takes the default value. If the points are colinear an empty circle is returned. @@ -106,7 +110,9 @@ The azimuth always takes the default value. static QgsCircle fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ); %Docstring Constructs a circle by an extent (aka bounding box / :py:class:`QgsRectangle`). -The center point can have z and m values which are the result from the midpoint operation between ``pt1`` and ``pt2``. +The center point can have m value which is the result from the midpoint +operation between ``pt1`` and ``pt2``. Z dimension is also supported and +is retrieved from the first 3D point amongst ``pt1`` and ``pt2``. Axes are calculated from the 2D distance between ``pt1`` and ``pt2``. The azimuth always takes the default value. diff --git a/python/core/geometry/qgsellipse.sip.in b/python/core/geometry/qgsellipse.sip.in index eda62d84a6b4..73dc4b6b4643 100644 --- a/python/core/geometry/qgsellipse.sip.in +++ b/python/core/geometry/qgsellipse.sip.in @@ -47,7 +47,9 @@ Constructs an ellipse by defining all the members. static QgsEllipse fromFoci( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3 ); %Docstring Constructs an ellipse by foci (``pt1`` and ``pt2``) and a point ``pt3``. -The center point can have z and m values which are the result from the midpoint operation between ``pt1`` and ``pt2``. +The center point can have m value which is the result from the midpoint +operation between ``pt1`` and ``pt2``. Z dimension is also supported and +is retrieved from the first 3D point amongst ``pt1`` and ``pt2``. Axes are calculated from the 2D distance with the third point ``pt3``. The azimuth is the angle between ``pt1`` and ``pt2``. @@ -59,7 +61,9 @@ The azimuth is the angle between ``pt1`` and ``pt2``. static QgsEllipse fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ); %Docstring Constructs an ellipse by an extent (aka bounding box / :py:class:`QgsRectangle`). -The center point can have z and m values which are the result from the midpoint operation between ``pt1`` and ``pt2``. +The center point can have m value which is the result from the midpoint +operation between ``pt1`` and ``pt2``. Z dimension is also supported and +is retrieved from the first 3D point amongst ``pt1`` and ``pt2``. Axes are calculated from the 2D distance between ``pt1`` and ``pt2``. The azimuth always takes the default value. @@ -70,7 +74,9 @@ The azimuth always takes the default value. static QgsEllipse fromCenterPoint( const QgsPoint &ptc, const QgsPoint &pt1 ); %Docstring Constructs an ellipse by a center point and a another point. -The center point keeps z and m values from ``ptc``. +The center point keeps m value from ``ptc``. Z dimension is also +supported and is retrieved from the first 3D point amongst ``ptc`` and +``pt1``. Axes are calculated from the 2D distance between ``ptc`` and ``pt1``. The azimuth always takes the default value. @@ -81,7 +87,9 @@ The azimuth always takes the default value. static QgsEllipse fromCenter2Points( const QgsPoint &ptc, const QgsPoint &pt1, const QgsPoint &pt2 ); %Docstring Constructs an ellipse by a central point and two other points. -The center point keeps z and m values from ``ptc``. +The center point keeps m value from ``ptc``. Z dimension is also +supported and is retrieved from the first 3D point amongst ``ptc``, +``pt1`` and ``pt2``. Axes are calculated from the 2D distance between ``ptc`` and ``pt1`` and ``pt2``. The azimuth is the angle between ``ptc`` and ``pt1``. diff --git a/python/core/geometry/qgsgeometryutils.sip.in b/python/core/geometry/qgsgeometryutils.sip.in index f1b292caf31f..4357112e18eb 100644 --- a/python/core/geometry/qgsgeometryutils.sip.in +++ b/python/core/geometry/qgsgeometryutils.sip.in @@ -89,7 +89,9 @@ Returns the squared distance between a point and a line. static bool lineIntersection( const QgsPoint &p1, QgsVector v1, const QgsPoint &p2, QgsVector v2, QgsPoint &intersection /Out/ ); %Docstring - Compute the intersection between two lines +Computes the intersection between two lines. Z dimension is +supported and is retrieved from the first 3D point amongst ``p1`` and +``p2``. :param p1: Point on the first line :param v1: Direction vector of the first line @@ -219,7 +221,9 @@ Calculates angle of a circular string part defined by pt1, pt2, pt3 static bool segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2, QgsPoint &result /Out/, double radius, const QgsPoint &mousePos ); %Docstring -Calculates midpoint on circle passing through p1 and p2, closest to given coordinate +Calculates midpoint on circle passing through p1 and p2, closest to +given coordinate. Z dimension is supported and is retrieved from the +first 3D point amongst ``p1`` and ``p2``. %End static double circleTangentDirection( const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3 ); @@ -397,6 +401,8 @@ A Z dimension is added to ``point`` if one of the point in the list :param point: The point to update with Z dimension and value. :return: true if the point is updated, false otherwise + +.. versionadded:: 3.0 %End diff --git a/python/core/geometry/qgstriangle.sip.in b/python/core/geometry/qgstriangle.sip.in index 557b3e9d5ac4..962581d58f7b 100644 --- a/python/core/geometry/qgstriangle.sip.in +++ b/python/core/geometry/qgstriangle.sip.in @@ -378,7 +378,8 @@ Example: QgsPoint inscribedCenter() const; %Docstring -Center of the inscribed circle of the triangle. +Center of the inscribed circle of the triangle. Z dimension is +supported and is retrieved from the first 3D point amongst vertexes. :return: The center of the inscribed circle of the triangle. An empty point is returned for empty triangle. diff --git a/src/core/geometry/qgscircle.h b/src/core/geometry/qgscircle.h index 5179126b63c4..33979f26f128 100644 --- a/src/core/geometry/qgscircle.h +++ b/src/core/geometry/qgscircle.h @@ -54,7 +54,9 @@ class CORE_EXPORT QgsCircle : public QgsEllipse /** * Constructs a circle by 2 points on the circle. - * The center point can have z and m values which are the result from the midpoint operation between \a pt1 and \a pt2. + * The center point can have m value which is the result from the midpoint + * operation between \a pt1 and \a pt2. Z dimension is also supported and + * is retrieved from the first 3D point amongst \a pt1 and \a pt2. * The radius is calculated from the 2D distance between \a pt1 and \a pt2. * The azimuth is the angle between \a pt1 and \a pt2. * \param pt1 First point. @@ -64,7 +66,9 @@ class CORE_EXPORT QgsCircle : public QgsEllipse /** * Constructs a circle by 3 points on the circle. - * Z and m values are dropped for the center point. + * M value is dropped for the center point. + * Z dimension is supported and is retrieved from the first 3D point + * amongst \a pt1, \a pt2 and \a pt3. * The azimuth always takes the default value. * If the points are colinear an empty circle is returned. * \param pt1 First point. @@ -113,7 +117,9 @@ class CORE_EXPORT QgsCircle : public QgsEllipse /** * Constructs a circle by an extent (aka bounding box / QgsRectangle). - * The center point can have z and m values which are the result from the midpoint operation between \a pt1 and \a pt2. + * The center point can have m value which is the result from the midpoint + * operation between \a pt1 and \a pt2. Z dimension is also supported and + * is retrieved from the first 3D point amongst \a pt1 and \a pt2. * Axes are calculated from the 2D distance between \a pt1 and \a pt2. * The azimuth always takes the default value. * \param pt1 First corner. diff --git a/src/core/geometry/qgsellipse.h b/src/core/geometry/qgsellipse.h index 4cff13de343e..8f4731ef29d9 100644 --- a/src/core/geometry/qgsellipse.h +++ b/src/core/geometry/qgsellipse.h @@ -59,7 +59,9 @@ class CORE_EXPORT QgsEllipse /** * Constructs an ellipse by foci (\a pt1 and \a pt2) and a point \a pt3. - * The center point can have z and m values which are the result from the midpoint operation between \a pt1 and \a pt2. + * The center point can have m value which is the result from the midpoint + * operation between \a pt1 and \a pt2. Z dimension is also supported and + * is retrieved from the first 3D point amongst \a pt1 and \a pt2. * Axes are calculated from the 2D distance with the third point \a pt3. * The azimuth is the angle between \a pt1 and \a pt2. * \param pt1 First focus. @@ -70,7 +72,9 @@ class CORE_EXPORT QgsEllipse /** * Constructs an ellipse by an extent (aka bounding box / QgsRectangle). - * The center point can have z and m values which are the result from the midpoint operation between \a pt1 and \a pt2. + * The center point can have m value which is the result from the midpoint + * operation between \a pt1 and \a pt2. Z dimension is also supported and + * is retrieved from the first 3D point amongst \a pt1 and \a pt2. * Axes are calculated from the 2D distance between \a pt1 and \a pt2. * The azimuth always takes the default value. * \param pt1 First corner. @@ -80,7 +84,9 @@ class CORE_EXPORT QgsEllipse /** * Constructs an ellipse by a center point and a another point. - * The center point keeps z and m values from \a ptc. + * The center point keeps m value from \a ptc. Z dimension is also + * supported and is retrieved from the first 3D point amongst \a ptc and + * \a pt1. * Axes are calculated from the 2D distance between \a ptc and \a pt1. * The azimuth always takes the default value. * \param ptc Center point. @@ -90,7 +96,9 @@ class CORE_EXPORT QgsEllipse /** * Constructs an ellipse by a central point and two other points. - * The center point keeps z and m values from \a ptc. + * The center point keeps m value from \a ptc. Z dimension is also + * supported and is retrieved from the first 3D point amongst \a ptc, + * \a pt1 and \a pt2. * Axes are calculated from the 2D distance between \a ptc and \a pt1 and \a pt2. * The azimuth is the angle between \a ptc and \a pt1. * \param ptc Center point. diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index 666207464bd9..3f503024a100 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -90,7 +90,9 @@ class CORE_EXPORT QgsGeometryUtils static double sqrDistToLine( double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX SIP_OUT, double &minDistY SIP_OUT, double epsilon ); /** - * \brief Compute the intersection between two lines + * Computes the intersection between two lines. Z dimension is + * supported and is retrieved from the first 3D point amongst \a p1 and + * \a p2. * \param p1 Point on the first line * \param v1 Direction vector of the first line * \param p2 Point on the second line @@ -225,7 +227,11 @@ class CORE_EXPORT QgsGeometryUtils //! Calculates angle of a circular string part defined by pt1, pt2, pt3 static double sweepAngle( double centerX, double centerY, double x1, double y1, double x2, double y2, double x3, double y3 ); - //! Calculates midpoint on circle passing through p1 and p2, closest to given coordinate + /** + * Calculates midpoint on circle passing through p1 and p2, closest to + * given coordinate. Z dimension is supported and is retrieved from the + * first 3D point amongst \a p1 and \a p2. + */ static bool segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2, QgsPoint &result SIP_OUT, double radius, const QgsPoint &mousePos ); //! Calculates the direction angle of a circle tangent (clockwise from north in radians) @@ -417,6 +423,8 @@ class CORE_EXPORT QgsGeometryUtils * \param points List of points in which a 3D point is searched. * \param point The point to update with Z dimension and value. * \returns true if the point is updated, false otherwise + * + * \since QGIS 3.0 */ static bool setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point ); diff --git a/src/core/geometry/qgstriangle.h b/src/core/geometry/qgstriangle.h index 2b571195429f..0e0b51309c2f 100644 --- a/src/core/geometry/qgstriangle.h +++ b/src/core/geometry/qgstriangle.h @@ -351,7 +351,8 @@ class CORE_EXPORT QgsTriangle : public QgsPolygon QgsCircle circumscribedCircle() const; /** - * Center of the inscribed circle of the triangle. + * Center of the inscribed circle of the triangle. Z dimension is + * supported and is retrieved from the first 3D point amongst vertexes. * \returns The center of the inscribed circle of the triangle. * An empty point is returned for empty triangle. * * Example: From cd4d9d0b0d2f8c01c78aef18f071d07de7adb907 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Mon, 15 Jan 2018 10:28:52 +0000 Subject: [PATCH 20/23] Drop z dimension in case of circle from tangential points --- src/app/qgsmaptoolcircle2tangentspoint.cpp | 12 ++++++------ src/core/geometry/qgscircle.cpp | 15 +++++++++++++++ tests/src/core/testqgsgeometry.cpp | 5 +++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index 6f8b564ee040..417a2d8d6229 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -43,7 +43,7 @@ QgsMapToolCircle2TangentsPoint::~QgsMapToolCircle2TangentsPoint() void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint mapPoint( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -56,8 +56,8 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e if ( match.isValid() ) { match.edgePoints( p1, p2 ); - mPoints.append( fromPointXY( p1 ) ); - mPoints.append( fromPointXY( p2 ) ); + mPoints.append( QgsPoint( p1 ) ); + mPoints.append( QgsPoint( p2 ) ); } } if ( mPoints.size() == 4 ) @@ -100,7 +100,7 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint mapPoint( e->mapPoint() ); EdgesOnlyFilter filter; QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); @@ -123,8 +123,8 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) match.edgePoints( p1, p2 ); std::unique_ptr line( new QgsLineString() ); - line->addVertex( fromPointXY( p1 ) ); - line->addVertex( fromPointXY( p2 ) ); + line->addVertex( QgsPoint( p1 ) ); + line->addVertex( QgsPoint( p2 ) ); mTempRubberBand->setGeometry( line.release() ); mTempRubberBand->show(); diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index 77864754ea99..dd7d4aed5c71 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -202,6 +202,21 @@ QgsCircle QgsCircle::from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2 if ( !isIntersect ) return QgsCircle(); + if ( p1.is3D() ) + { + p1.convertTo( QgsWkbTypes::dropZ( p1.wkbType() ) ); + } + + if ( p2.is3D() ) + { + p2.convertTo( QgsWkbTypes::dropZ( p2.wkbType() ) ); + } + + if ( p3.is3D() ) + { + p3.convertTo( QgsWkbTypes::dropZ( p3.wkbType() ) ); + } + return QgsTriangle( p1, p2, p3 ).inscribedCircle(); } diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp index f7f6359652c2..81587b6c39ae 100644 --- a/tests/src/core/testqgsgeometry.cpp +++ b/tests/src/core/testqgsgeometry.cpp @@ -7031,6 +7031,11 @@ void TestQgsGeometry::circle() QVERIFY( circ_tgt.isEmpty() ); circ_tgt = QgsCircle().from3Tangents( QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) ); QVERIFY( circ_tgt.isEmpty() ); + + // check that Z dimension is ignored in case of using tangents + QgsCircle circ_tgt_z = QgsCircle().from3Tangents( QgsPoint( 0, 0, 333 ), QgsPoint( 0, 1, 1 ), QgsPoint( 2, 0, 2 ), QgsPoint( 3, 0, 3 ), QgsPoint( 5, 0, 4 ), QgsPoint( 0, 5, 5 ) ); + QCOMPARE( circ_tgt_z.center().is3D(), false ); + // minimalCircleFrom3points QgsCircle minCircle3Points = QgsCircle().minimalCircleFrom3Points( QgsPoint( 0, 5 ), QgsPoint( 0, -5 ), QgsPoint( 1, 2 ) ); QGSCOMPARENEARPOINT( minCircle3Points.center(), QgsPoint( 0, 0 ), 0.0001 ); From a6a3e0b1d46bb8fd8b18e38943c1265b1cea4f04 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Mon, 15 Jan 2018 13:41:35 +0000 Subject: [PATCH 21/23] Fix spelling check and sip binding --- python/core/geometry/qgstriangle.sip.in | 2 +- python/gui/qgsmaptoolcapture.sip.in | 10 +++++----- src/core/geometry/qgstriangle.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/core/geometry/qgstriangle.sip.in b/python/core/geometry/qgstriangle.sip.in index 962581d58f7b..2c747ade9dec 100644 --- a/python/core/geometry/qgstriangle.sip.in +++ b/python/core/geometry/qgstriangle.sip.in @@ -379,7 +379,7 @@ Example: QgsPoint inscribedCenter() const; %Docstring Center of the inscribed circle of the triangle. Z dimension is -supported and is retrieved from the first 3D point amongst vertexes. +supported and is retrieved from the first 3D point amongst vertices. :return: The center of the inscribed circle of the triangle. An empty point is returned for empty triangle. diff --git a/python/gui/qgsmaptoolcapture.sip.in b/python/gui/qgsmaptoolcapture.sip.in index 5e808b82345c..0fff83e0c2c6 100644 --- a/python/gui/qgsmaptoolcapture.sip.in +++ b/python/gui/qgsmaptoolcapture.sip.in @@ -104,15 +104,15 @@ convenient method to clean members QgsPoint fromPointXY( const QgsPointXY &point ) const; %Docstring - Creates a QgsPoint with ZM support if necessary (according to the - WkbType of the current layer) from a QgsPointXY. +Creates a QgsPoint with ZM support if necessary (according to the +WkbType of the current layer) from a :py:class:`QgsPointXY`. - \param point A QgsPointXY to convert +:param point: A QgsPointXY to convert + +:return: a point if ZM support if necessary - :return: a point if ZM support if necessary .. versionadded:: 3.0 - :rtype: QgsPoint %End int addVertex( const QgsPointXY &point ); diff --git a/src/core/geometry/qgstriangle.h b/src/core/geometry/qgstriangle.h index 0e0b51309c2f..6e6dc99b9a97 100644 --- a/src/core/geometry/qgstriangle.h +++ b/src/core/geometry/qgstriangle.h @@ -352,7 +352,7 @@ class CORE_EXPORT QgsTriangle : public QgsPolygon /** * Center of the inscribed circle of the triangle. Z dimension is - * supported and is retrieved from the first 3D point amongst vertexes. + * supported and is retrieved from the first 3D point amongst vertices. * \returns The center of the inscribed circle of the triangle. * An empty point is returned for empty triangle. * * Example: From b4be0ce7912197cfd53138ce40398b477ac7f524 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Mon, 29 Jan 2018 09:03:55 +0000 Subject: [PATCH 22/23] Fixes build --- src/app/qgisapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 6c9233293c1e..3a2f691e4d1d 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -1311,7 +1311,7 @@ QgisApp::QgisApp() mMapCanvas->freeze(); mLayerTreeView = new QgsLayerTreeView( this ); mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas ); - mUserInputDockWidget = new QgsUserInputDockWidget( this ); + mUserInputDockWidget = new QgsUserInputWidget( this ); mInfoBar = new QgsMessageBar( centralWidget() ); mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this ); mPanelMenu = new QMenu( this ); From 53aafb48030d27036eee0093de0e8541e9e5eb23 Mon Sep 17 00:00:00 2001 From: Blottiere Paul Date: Fri, 16 Feb 2018 10:03:07 +0000 Subject: [PATCH 23/23] Z value from snapped point is kept --- python/gui/qgsmaptoolcapture.sip.in | 22 +++++++++--- src/app/qgsmaptooladdcircle.cpp | 16 ++++++++- src/app/qgsmaptooladdellipse.cpp | 16 ++++++++- src/app/qgsmaptooladdrectangle.cpp | 27 +++++++++++--- src/app/qgsmaptooladdregularpolygon.cpp | 16 ++++++++- src/app/qgsmaptoolcircle2points.cpp | 10 +++--- src/app/qgsmaptoolcircle3points.cpp | 10 +++--- src/app/qgsmaptoolcircle3tangents.cpp | 20 +++++------ src/app/qgsmaptoolcirclecenterpoint.cpp | 10 +++--- .../qgsmaptoolcircularstringcurvepoint.cpp | 8 ++--- src/app/qgsmaptoolcircularstringradius.cpp | 10 +++--- src/app/qgsmaptoolellipsecenter2points.cpp | 10 +++--- src/app/qgsmaptoolellipsecenterpoint.cpp | 8 ++--- src/app/qgsmaptoolellipseextent.cpp | 12 +++---- src/app/qgsmaptoolellipsefoci.cpp | 10 +++--- src/app/qgsmaptoolrectangle3points.cpp | 17 +++++---- src/app/qgsmaptoolrectanglecenter.cpp | 16 +++++---- src/app/qgsmaptoolrectangleextent.cpp | 14 ++++---- src/app/qgsmaptoolregularpolygon2points.cpp | 10 +++--- .../qgsmaptoolregularpolygoncentercorner.cpp | 10 +++--- .../qgsmaptoolregularpolygoncenterpoint.cpp | 10 +++--- src/gui/qgsmaptoolcapture.cpp | 36 +++++++++++++------ src/gui/qgsmaptoolcapture.h | 21 ++++++++--- 23 files changed, 227 insertions(+), 112 deletions(-) diff --git a/python/gui/qgsmaptoolcapture.sip.in b/python/gui/qgsmaptoolcapture.sip.in index 0fff83e0c2c6..66370d74b6e5 100644 --- a/python/gui/qgsmaptoolcapture.sip.in +++ b/python/gui/qgsmaptoolcapture.sip.in @@ -102,14 +102,28 @@ convenient method to clean members int fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ); - QgsPoint fromPointXY( const QgsPointXY &point ) const; + QgsPoint mapPoint( const QgsMapMouseEvent &e ) const; %Docstring Creates a QgsPoint with ZM support if necessary (according to the -WkbType of the current layer) from a :py:class:`QgsPointXY`. +WkbType of the current layer). If the point is snapped, then the Z +value is took from the snapped point. -:param point: A QgsPointXY to convert +:param e: A mouse event -:return: a point if ZM support if necessary +:return: a point with ZM support if necessary + + +.. versionadded:: 3.0 +%End + + QgsPoint mapPoint( const QgsPointXY &point ) const; +%Docstring +Creates a QgsPoint with ZM support if necessary (according to the +WkbType of the current layer). + +:param point: A point in 2D + +:return: a point with ZM support if necessary .. versionadded:: 3.0 diff --git a/src/app/qgsmaptooladdcircle.cpp b/src/app/qgsmaptooladdcircle.cpp index de563cf6943f..21a4514c8ec0 100644 --- a/src/app/qgsmaptooladdcircle.cpp +++ b/src/app/qgsmaptooladdcircle.cpp @@ -68,7 +68,21 @@ void QgsMapToolAddCircle::deactivate() } mParentTool->clearCurve(); - mParentTool->addCurve( mCircle.toCircularString() ); + + // keep z value from the first snapped point + std::unique_ptr lineString( mCircle.toCircularString() ); + for ( const QgsPoint point : qgis::as_const( mPoints ) ) + { + if ( QgsWkbTypes::hasZ( point.wkbType() ) && + point.z() != defaultZValue() ) + { + lineString->dropZValue(); + lineString->addZValue( point.z() ); + break; + } + } + + mParentTool->addCurve( lineString.release() ); clean(); QgsMapToolCapture::deactivate(); diff --git a/src/app/qgsmaptooladdellipse.cpp b/src/app/qgsmaptooladdellipse.cpp index 84e5700a87c0..a48c5ffdf06d 100644 --- a/src/app/qgsmaptooladdellipse.cpp +++ b/src/app/qgsmaptooladdellipse.cpp @@ -68,7 +68,21 @@ void QgsMapToolAddEllipse::deactivate() } mParentTool->clearCurve(); - mParentTool->addCurve( mEllipse.toLineString( segments() ) ); + + // keep z value from the first snapped point + std::unique_ptr ls( mEllipse.toLineString( segments() ) ); + for ( const QgsPoint point : qgis::as_const( mPoints ) ) + { + if ( QgsWkbTypes::hasZ( point.wkbType() ) && + point.z() != defaultZValue() ) + { + ls->dropZValue(); + ls->addZValue( point.z() ); + break; + } + } + + mParentTool->addCurve( ls.release() ); clean(); QgsMapToolCapture::deactivate(); diff --git a/src/app/qgsmaptooladdrectangle.cpp b/src/app/qgsmaptooladdrectangle.cpp index 78a2ad7654bd..7ea8db2cbc91 100644 --- a/src/app/qgsmaptooladdrectangle.cpp +++ b/src/app/qgsmaptooladdrectangle.cpp @@ -89,7 +89,7 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien return ext.release(); } - QgsPoint x0( mRectangle.xMinimum(), mRectangle.yMinimum(), mRectangle.zMinimum() ); + QgsPoint x0( mRectangle.xMinimum(), mRectangle.yMinimum() ); QgsPoint x1, x2, x3; if ( isOriented ) @@ -101,9 +101,9 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien } else { - x1 = QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum(), mRectangle.zMinimum() ); - x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum(), mRectangle.zMinimum() ); - x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum(), mRectangle.zMinimum() ); + x1 = QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum() ); + x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() ); + x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() ); } ext->addVertex( x0 ); @@ -112,6 +112,25 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien ext->addVertex( x3 ); ext->addVertex( x0 ); + // keep z value from the first snapped point + for ( const QgsPoint point : qgis::as_const( mPoints ) ) + { + if ( QgsWkbTypes::hasZ( point.wkbType() ) ) + { + if ( point.z() != defaultZValue() ) + { + ext->dropZValue(); + ext->addZValue( point.z() ); + break; + } + else + { + ext->dropZValue(); + ext->addZValue( defaultZValue() ); + } + } + } + return ext.release(); } diff --git a/src/app/qgsmaptooladdregularpolygon.cpp b/src/app/qgsmaptooladdregularpolygon.cpp index 8e289b22734d..b985509fd1f2 100644 --- a/src/app/qgsmaptooladdregularpolygon.cpp +++ b/src/app/qgsmaptooladdregularpolygon.cpp @@ -87,7 +87,21 @@ void QgsMapToolAddRegularPolygon::deactivate() return; } mParentTool->clearCurve( ); - mParentTool->addCurve( mRegularPolygon.toLineString() ); + + // keep z value from the first snapped point + std::unique_ptr ls( mRegularPolygon.toLineString() ); + for ( const QgsPoint point : qgis::as_const( mPoints ) ) + { + if ( QgsWkbTypes::hasZ( point.wkbType() ) && + point.z() != defaultZValue() ) + { + ls->dropZValue(); + ls->addZValue( point.z() ); + break; + } + } + + mParentTool->addCurve( ls.release() ); clean(); QgsMapToolCapture::deactivate(); diff --git a/src/app/qgsmaptoolcircle2points.cpp b/src/app/qgsmaptoolcircle2points.cpp index 62619e481c3e..f05486ae2d43 100644 --- a/src/app/qgsmaptoolcircle2points.cpp +++ b/src/app/qgsmaptoolcircle2points.cpp @@ -28,11 +28,11 @@ QgsMapToolCircle2Points::QgsMapToolCircle2Points( QgsMapToolCapture *parentTool, void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -42,6 +42,8 @@ void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -52,10 +54,10 @@ void QgsMapToolCircle2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { - mCircle = QgsCircle().from2Points( mPoints.at( 0 ), mapPoint ); + mCircle = QgsCircle().from2Points( mPoints.at( 0 ), point ); mTempRubberBand->setGeometry( mCircle.toCircularString( true ) ); } } diff --git a/src/app/qgsmaptoolcircle3points.cpp b/src/app/qgsmaptoolcircle3points.cpp index 5d284e5f92a0..3801964d4bce 100644 --- a/src/app/qgsmaptoolcircle3points.cpp +++ b/src/app/qgsmaptoolcircle3points.cpp @@ -29,12 +29,12 @@ QgsMapToolCircle3Points::QgsMapToolCircle3Points( QgsMapToolCapture *parentTool, void QgsMapToolCircle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { if ( mPoints.size() < 2 ) - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { mTempRubberBand = createGeometryRubberBand( ( mode() == CapturePolygon ) ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true ); @@ -53,7 +53,7 @@ void QgsMapToolCircle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -63,13 +63,13 @@ void QgsMapToolCircle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { std::unique_ptr line( new QgsLineString() ); line->addVertex( mPoints.at( 0 ) ); - line->addVertex( mapPoint ); + line->addVertex( point ); mTempRubberBand->setGeometry( line.release() ); } break; case 2: { - mCircle = QgsCircle().from3Points( mPoints.at( 0 ), mPoints.at( 1 ), mapPoint ); + mCircle = QgsCircle().from3Points( mPoints.at( 0 ), mPoints.at( 1 ), point ); mTempRubberBand->setGeometry( mCircle.toCircularString( true ) ); } break; diff --git a/src/app/qgsmaptoolcircle3tangents.cpp b/src/app/qgsmaptoolcircle3tangents.cpp index 78d6bc351da5..927e764c7490 100644 --- a/src/app/qgsmaptoolcircle3tangents.cpp +++ b/src/app/qgsmaptoolcircle3tangents.cpp @@ -32,9 +32,9 @@ QgsMapToolCircle3Tangents::QgsMapToolCircle3Tangents( QgsMapToolCapture *parentT void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); EdgesOnlyFilter filter; - QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); + QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( point, &filter ); QgsPointXY p1, p2; @@ -43,8 +43,8 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) if ( match.isValid() && ( mPoints.size() <= 2 * 2 ) ) { match.edgePoints( p1, p2 ); - mPoints.append( fromPointXY( p1 ) ); - mPoints.append( fromPointXY( p2 ) ); + mPoints.append( mapPoint( p1 ) ); + mPoints.append( mapPoint( p2 ) ); } } else if ( e->button() == Qt::RightButton ) @@ -52,8 +52,8 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) if ( match.isValid() && ( mPoints.size() == 4 ) ) { match.edgePoints( p1, p2 ); - mPoints.append( fromPointXY( p1 ) ); - mPoints.append( fromPointXY( p2 ) ); + mPoints.append( mapPoint( p1 ) ); + mPoints.append( mapPoint( p2 ) ); mCircle = QgsCircle().from3Tangents( mPoints.at( 0 ), mPoints.at( 1 ), mPoints.at( 2 ), mPoints.at( 3 ), mPoints.at( 4 ), mPoints.at( 5 ) ); if ( mCircle.isEmpty() ) { @@ -73,9 +73,9 @@ void QgsMapToolCircle3Tangents::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircle3Tangents::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); EdgesOnlyFilter filter; - QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( mapPoint, &filter ); + QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToMap( point, &filter ); if ( !mTempRubberBand ) { @@ -94,8 +94,8 @@ void QgsMapToolCircle3Tangents::cadCanvasMoveEvent( QgsMapMouseEvent *e ) match.edgePoints( p1, p2 ); std::unique_ptr line( new QgsLineString() ); - line->addVertex( fromPointXY( p1 ) ); - line->addVertex( fromPointXY( p2 ) ); + line->addVertex( mapPoint( p1 ) ); + line->addVertex( mapPoint( p2 ) ); mTempRubberBand->setGeometry( line.release() ); mTempRubberBand->show(); diff --git a/src/app/qgsmaptoolcirclecenterpoint.cpp b/src/app/qgsmaptoolcirclecenterpoint.cpp index 912f322bc3b9..d0509f322fbf 100644 --- a/src/app/qgsmaptoolcirclecenterpoint.cpp +++ b/src/app/qgsmaptoolcirclecenterpoint.cpp @@ -29,11 +29,11 @@ QgsMapToolCircleCenterPoint::QgsMapToolCircleCenterPoint( QgsMapToolCapture *par void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -44,6 +44,8 @@ void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -54,10 +56,10 @@ void QgsMapToolCircleCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolCircleCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { - mCircle = QgsCircle().fromCenterPoint( mPoints.at( 0 ), mapPoint ); + mCircle = QgsCircle().fromCenterPoint( mPoints.at( 0 ), point ); mTempRubberBand->setGeometry( mCircle.toCircularString( true ) ); } } diff --git a/src/app/qgsmaptoolcircularstringcurvepoint.cpp b/src/app/qgsmaptoolcircularstringcurvepoint.cpp index 6df902877b82..f127c26da701 100644 --- a/src/app/qgsmaptoolcircularstringcurvepoint.cpp +++ b/src/app/qgsmaptoolcircularstringcurvepoint.cpp @@ -29,11 +29,11 @@ QgsMapToolCircularStringCurvePoint::QgsMapToolCircularStringCurvePoint( QgsMapTo void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mCenterPointRubberBand && mShowCenterPointRubberBand ) { createCenterPointRubberBand(); @@ -49,7 +49,7 @@ void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent QgsCircularString *c = new QgsCircularString(); QgsPointSequence rubberBandPoints = mPoints.mid( mPoints.size() - 1 - ( mPoints.size() + 1 ) % 2 ); - rubberBandPoints.append( mapPoint ); + rubberBandPoints.append( point ); c->setPoints( rubberBandPoints ); mTempRubberBand->setGeometry( c ); } @@ -63,7 +63,7 @@ void QgsMapToolCircularStringCurvePoint::cadCanvasReleaseEvent( QgsMapMouseEvent QgsCircularString *c = new QgsCircularString(); QgsPointSequence rubberBandPoints = mPoints; - rubberBandPoints.append( mapPoint ); + rubberBandPoints.append( point ); c->setPoints( rubberBandPoints ); mRubberBand->setGeometry( c ); removeCenterPointRubberBand(); diff --git a/src/app/qgsmaptoolcircularstringradius.cpp b/src/app/qgsmaptoolcircularstringradius.cpp index 42186c3cd533..2edb5423a0a3 100644 --- a/src/app/qgsmaptoolcircularstringradius.cpp +++ b/src/app/qgsmaptoolcircularstringradius.cpp @@ -43,26 +43,26 @@ void QgsMapToolCircularStringRadius::deactivate() void QgsMapToolCircularStringRadius::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { if ( mPoints.isEmpty() ) { - mPoints.append( mapPoint ); + mPoints.append( point ); } else { if ( mPoints.size() % 2 ) { - mTemporaryEndPoint = fromPointXY( mapPoint ); + mTemporaryEndPoint = point; //initial radius is distance( tempPoint - mPoints.last ) / 2.0 double minRadius = std::sqrt( QgsGeometryUtils::sqrDistance2D( mPoints.last(), mTemporaryEndPoint ) ) / 2.0; mRadius = minRadius + minRadius / 10.0; QgsPoint result; - if ( QgsGeometryUtils::segmentMidPoint( mPoints.last(), mTemporaryEndPoint, result, mRadius, QgsPoint( mapPoint.x(), mapPoint.y() ) ) ) + if ( QgsGeometryUtils::segmentMidPoint( mPoints.last(), mTemporaryEndPoint, result, mRadius, QgsPoint( point.x(), point.y() ) ) ) { mPoints.append( result ); createRadiusSpinBox(); @@ -136,7 +136,7 @@ void QgsMapToolCircularStringRadius::recalculateTempRubberBand( const QgsPointXY else { rubberBandPoints.append( mPoints.last() ); - rubberBandPoints.append( fromPointXY( mousePosition ) ); + rubberBandPoints.append( mapPoint( mousePosition ) ); } QgsCircularString *cString = new QgsCircularString(); cString->setPoints( rubberBandPoints ); diff --git a/src/app/qgsmaptoolellipsecenter2points.cpp b/src/app/qgsmaptoolellipsecenter2points.cpp index d477cfb59e9c..63b88b56764f 100644 --- a/src/app/qgsmaptoolellipsecenter2points.cpp +++ b/src/app/qgsmaptoolellipsecenter2points.cpp @@ -30,13 +30,13 @@ QgsMapToolEllipseCenter2Points::QgsMapToolEllipseCenter2Points( QgsMapToolCaptur void QgsMapToolEllipseCenter2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { if ( mPoints.size() < 2 ) - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -56,7 +56,7 @@ void QgsMapToolEllipseCenter2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolEllipseCenter2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -66,13 +66,13 @@ void QgsMapToolEllipseCenter2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { std::unique_ptr line( new QgsLineString() ); line->addVertex( mPoints.at( 0 ) ); - line->addVertex( mapPoint ); + line->addVertex( point ); mTempRubberBand->setGeometry( line.release() ); } break; case 2: { - mEllipse = QgsEllipse().fromCenter2Points( mPoints.at( 0 ), mPoints.at( 1 ), mapPoint ); + mEllipse = QgsEllipse().fromCenter2Points( mPoints.at( 0 ), mPoints.at( 1 ), point ); mTempRubberBand->setGeometry( mEllipse.toPolygon( segments() ) ); } break; diff --git a/src/app/qgsmaptoolellipsecenterpoint.cpp b/src/app/qgsmaptoolellipsecenterpoint.cpp index 8f265becdd0c..5f1049b96240 100644 --- a/src/app/qgsmaptoolellipsecenterpoint.cpp +++ b/src/app/qgsmaptoolellipsecenterpoint.cpp @@ -28,11 +28,11 @@ QgsMapToolEllipseCenterPoint::QgsMapToolEllipseCenterPoint( QgsMapToolCapture *p void QgsMapToolEllipseCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -52,10 +52,10 @@ void QgsMapToolEllipseCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolEllipseCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { - mEllipse = QgsEllipse().fromCenterPoint( mPoints.at( 0 ), mapPoint ); + mEllipse = QgsEllipse().fromCenterPoint( mPoints.at( 0 ), point ); mTempRubberBand->setGeometry( mEllipse.toPolygon( segments() ) ); } } diff --git a/src/app/qgsmaptoolellipseextent.cpp b/src/app/qgsmaptoolellipseextent.cpp index 3177b33ead55..f66ec1b7454b 100644 --- a/src/app/qgsmaptoolellipseextent.cpp +++ b/src/app/qgsmaptoolellipseextent.cpp @@ -30,11 +30,11 @@ QgsMapToolEllipseExtent::QgsMapToolEllipseExtent( QgsMapToolCapture *parentTool, void QgsMapToolEllipseExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -54,7 +54,7 @@ void QgsMapToolEllipseExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolEllipseExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -64,13 +64,13 @@ void QgsMapToolEllipseExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { if ( qgsDoubleNear( mCanvas->rotation(), 0.0 ) ) { - mEllipse = QgsEllipse().fromExtent( mPoints.at( 0 ), mapPoint ); + mEllipse = QgsEllipse().fromExtent( mPoints.at( 0 ), point ); mTempRubberBand->setGeometry( mEllipse.toPolygon( segments() ) ); } else { - double dist = mPoints.at( 0 ).distance( mapPoint ); - double angle = mPoints.at( 0 ).azimuth( mapPoint ); + double dist = mPoints.at( 0 ).distance( point ); + double angle = mPoints.at( 0 ).azimuth( point ); mEllipse = QgsEllipse().fromExtent( mPoints.at( 0 ), mPoints.at( 0 ).project( dist, angle ) ); mTempRubberBand->setGeometry( mEllipse.toPolygon( segments() ) ); diff --git a/src/app/qgsmaptoolellipsefoci.cpp b/src/app/qgsmaptoolellipsefoci.cpp index 0319a786b812..54bff0f0dd86 100644 --- a/src/app/qgsmaptoolellipsefoci.cpp +++ b/src/app/qgsmaptoolellipsefoci.cpp @@ -30,11 +30,11 @@ QgsMapToolEllipseFoci::QgsMapToolEllipseFoci( QgsMapToolCapture *parentTool, void QgsMapToolEllipseFoci::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -54,7 +54,7 @@ void QgsMapToolEllipseFoci::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolEllipseFoci::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -64,13 +64,13 @@ void QgsMapToolEllipseFoci::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { std::unique_ptr line( new QgsLineString() ); line->addVertex( mPoints.at( 0 ) ); - line->addVertex( mapPoint ); + line->addVertex( point ); mTempRubberBand->setGeometry( line.release() ); } break; case 2: { - mEllipse = QgsEllipse().fromFoci( mPoints.at( 0 ), mPoints.at( 1 ), mapPoint ); + mEllipse = QgsEllipse().fromFoci( mPoints.at( 0 ), mPoints.at( 1 ), point ); mTempRubberBand->setGeometry( mEllipse.toPolygon() ); } break; diff --git a/src/app/qgsmaptoolrectangle3points.cpp b/src/app/qgsmaptoolrectangle3points.cpp index 256d2f94df0b..ce8cc9f36892 100644 --- a/src/app/qgsmaptoolrectangle3points.cpp +++ b/src/app/qgsmaptoolrectangle3points.cpp @@ -31,12 +31,12 @@ QgsMapToolRectangle3Points::QgsMapToolRectangle3Points( QgsMapToolCapture *paren void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { if ( mPoints.size() < 2 ) - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -56,7 +56,7 @@ void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -66,17 +66,16 @@ void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { std::unique_ptr line( new QgsLineString() ); line->addVertex( mPoints.at( 0 ) ); - line->addVertex( mapPoint ); + line->addVertex( point ); mTempRubberBand->setGeometry( line.release() ); - setAzimuth( mPoints.at( 0 ).azimuth( mapPoint ) ); - setDistance1( mPoints.at( 0 ).distance( mapPoint ) ); + setAzimuth( mPoints.at( 0 ).azimuth( point ) ); + setDistance1( mPoints.at( 0 ).distance( point ) ); } break; case 2: { - - setDistance2( mPoints.at( 1 ).distance( mapPoint ) ); - int side = QgsGeometryUtils::leftOfLine( mapPoint.x(), mapPoint.y(), + setDistance2( mPoints.at( 1 ).distance( point ) ); + int side = QgsGeometryUtils::leftOfLine( point.x(), point.y(), mPoints.at( 0 ).x(), mPoints.at( 0 ).y(), mPoints.at( 1 ).x(), mPoints.at( 1 ).y() ); diff --git a/src/app/qgsmaptoolrectanglecenter.cpp b/src/app/qgsmaptoolrectanglecenter.cpp index 897f855ae9a3..11aedfa09c1b 100644 --- a/src/app/qgsmaptoolrectanglecenter.cpp +++ b/src/app/qgsmaptoolrectanglecenter.cpp @@ -31,11 +31,11 @@ QgsMapToolRectangleCenter::QgsMapToolRectangleCenter( QgsMapToolCapture *parentT void QgsMapToolRectangleCenter::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -45,6 +45,8 @@ void QgsMapToolRectangleCenter::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -55,7 +57,7 @@ void QgsMapToolRectangleCenter::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolRectangleCenter::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -65,8 +67,8 @@ void QgsMapToolRectangleCenter::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { if ( qgsDoubleNear( mCanvas->rotation(), 0.0 ) ) { - double xOffset = fabs( mapPoint.x() - mPoints.at( 0 ).x() ); - double yOffset = fabs( mapPoint.y() - mPoints.at( 0 ).y() ); + double xOffset = fabs( point.x() - mPoints.at( 0 ).x() ); + double yOffset = fabs( point.y() - mPoints.at( 0 ).y() ); mRectangle = QgsBox3d( QgsPoint( mPoints.at( 0 ).x() - xOffset, mPoints.at( 0 ).y() - yOffset, mPoints.at( 0 ).z() ), QgsPoint( mPoints.at( 0 ).x() + xOffset, mPoints.at( 0 ).y() + yOffset, mPoints.at( 0 ).z() ) ); @@ -74,8 +76,8 @@ void QgsMapToolRectangleCenter::cadCanvasMoveEvent( QgsMapMouseEvent *e ) } else { - double dist = mPoints.at( 0 ).distance( mapPoint ); - double angle = mPoints.at( 0 ).azimuth( mapPoint ); + double dist = mPoints.at( 0 ).distance( point ); + double angle = mPoints.at( 0 ).azimuth( point ); mRectangle = QgsBox3d( mPoints.at( 0 ).project( -dist, angle ), mPoints.at( 0 ).project( dist, angle ) ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon() ); diff --git a/src/app/qgsmaptoolrectangleextent.cpp b/src/app/qgsmaptoolrectangleextent.cpp index 5ddc11dfcb38..096604b8bf72 100644 --- a/src/app/qgsmaptoolrectangleextent.cpp +++ b/src/app/qgsmaptoolrectangleextent.cpp @@ -31,11 +31,11 @@ QgsMapToolRectangleExtent::QgsMapToolRectangleExtent( QgsMapToolCapture *parentT void QgsMapToolRectangleExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() && !mTempRubberBand ) { @@ -45,6 +45,8 @@ void QgsMapToolRectangleExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -55,7 +57,7 @@ void QgsMapToolRectangleExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) void QgsMapToolRectangleExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { @@ -65,13 +67,13 @@ void QgsMapToolRectangleExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { if ( qgsDoubleNear( mCanvas->rotation(), 0.0 ) ) { - mRectangle = QgsBox3d( mPoints.at( 0 ), mapPoint ); + mRectangle = QgsBox3d( mPoints.at( 0 ), point ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon( ) ); } else { - double dist = mPoints.at( 0 ).distance( mapPoint ); - double angle = mPoints.at( 0 ).azimuth( mapPoint ); + double dist = mPoints.at( 0 ).distance( point ); + double angle = mPoints.at( 0 ).azimuth( point ); mRectangle = QgsBox3d( mPoints.at( 0 ), mPoints.at( 0 ).project( dist, angle ) ); mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon() ); diff --git a/src/app/qgsmaptoolregularpolygon2points.cpp b/src/app/qgsmaptoolregularpolygon2points.cpp index bac93850ece1..13ea610e8eb3 100644 --- a/src/app/qgsmaptoolregularpolygon2points.cpp +++ b/src/app/qgsmaptoolregularpolygon2points.cpp @@ -36,11 +36,11 @@ QgsMapToolRegularPolygon2Points::~QgsMapToolRegularPolygon2Points() void QgsMapToolRegularPolygon2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() ) { @@ -55,6 +55,8 @@ void QgsMapToolRegularPolygon2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -65,10 +67,10 @@ void QgsMapToolRegularPolygon2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e void QgsMapToolRegularPolygon2Points::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { - mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), mapPoint, mNumberSidesSpinBox->value() ); + mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), point, mNumberSidesSpinBox->value() ); mTempRubberBand->setGeometry( mRegularPolygon.toPolygon() ); } } diff --git a/src/app/qgsmaptoolregularpolygoncentercorner.cpp b/src/app/qgsmaptoolregularpolygoncentercorner.cpp index 41b631be4dab..be9e8315ff0e 100644 --- a/src/app/qgsmaptoolregularpolygoncentercorner.cpp +++ b/src/app/qgsmaptoolregularpolygoncentercorner.cpp @@ -33,11 +33,11 @@ QgsMapToolRegularPolygonCenterCorner::~QgsMapToolRegularPolygonCenterCorner() void QgsMapToolRegularPolygonCenterCorner::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() ) { @@ -52,6 +52,8 @@ void QgsMapToolRegularPolygonCenterCorner::cadCanvasReleaseEvent( QgsMapMouseEve } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -62,11 +64,11 @@ void QgsMapToolRegularPolygonCenterCorner::cadCanvasReleaseEvent( QgsMapMouseEve void QgsMapToolRegularPolygonCenterCorner::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { QgsRegularPolygon::ConstructionOption option = QgsRegularPolygon::InscribedCircle; - mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), mapPoint, mNumberSidesSpinBox->value(), option ); + mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), point, mNumberSidesSpinBox->value(), option ); mTempRubberBand->setGeometry( mRegularPolygon.toPolygon() ); } } diff --git a/src/app/qgsmaptoolregularpolygoncenterpoint.cpp b/src/app/qgsmaptoolregularpolygoncenterpoint.cpp index de293b161116..5aa90dc4e98b 100644 --- a/src/app/qgsmaptoolregularpolygoncenterpoint.cpp +++ b/src/app/qgsmaptoolregularpolygoncenterpoint.cpp @@ -33,11 +33,11 @@ QgsMapToolRegularPolygonCenterPoint::~QgsMapToolRegularPolygonCenterPoint() void QgsMapToolRegularPolygonCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( e->button() == Qt::LeftButton ) { - mPoints.append( mapPoint ); + mPoints.append( point ); if ( !mPoints.isEmpty() ) { @@ -52,6 +52,8 @@ void QgsMapToolRegularPolygonCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEven } else if ( e->button() == Qt::RightButton ) { + mPoints.append( point ); + deactivate(); if ( mParentTool ) { @@ -62,11 +64,11 @@ void QgsMapToolRegularPolygonCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEven void QgsMapToolRegularPolygonCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) { - QgsPoint mapPoint = fromPointXY( e->mapPoint() ); + QgsPoint point = mapPoint( *e ); if ( mTempRubberBand ) { QgsRegularPolygon::ConstructionOption option = QgsRegularPolygon::CircumscribedCircle; - mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), mapPoint, mNumberSidesSpinBox->value(), option ); + mRegularPolygon = QgsRegularPolygon( mPoints.at( 0 ), point, mNumberSidesSpinBox->value(), option ); mTempRubberBand->setGeometry( mRegularPolygon.toPolygon() ); } } diff --git a/src/gui/qgsmaptoolcapture.cpp b/src/gui/qgsmaptoolcapture.cpp index cea448008eeb..9d5020ebe80b 100644 --- a/src/gui/qgsmaptoolcapture.cpp +++ b/src/gui/qgsmaptoolcapture.cpp @@ -768,7 +768,7 @@ void QgsMapToolCapture::setPoints( const QVector &pointList ) mSnappingMatches.append( QgsPointLocator::Match() ); } -QgsPoint QgsMapToolCapture::fromPointXY( const QgsPointXY &point ) const +QgsPoint QgsMapToolCapture::mapPoint( const QgsPointXY &point ) const { QgsPoint newPoint( QgsWkbTypes::Point, point.x(), point.y() ); @@ -780,7 +780,7 @@ QgsPoint QgsMapToolCapture::fromPointXY( const QgsPointXY &point ) const } // convert to the corresponding type for a full ZM support - QgsWkbTypes::Type type = vlayer->wkbType(); + const QgsWkbTypes::Type type = vlayer->wkbType(); if ( QgsWkbTypes::hasZ( type ) && !QgsWkbTypes::hasM( type ) ) { newPoint.convertTo( QgsWkbTypes::PointZ ); @@ -794,22 +794,36 @@ QgsPoint QgsMapToolCapture::fromPointXY( const QgsPointXY &point ) const newPoint.convertTo( QgsWkbTypes::PointZM ); } - // set default value for Z if necessary + // set z value if necessary if ( QgsWkbTypes::hasZ( newPoint.wkbType() ) ) + { newPoint.setZ( defaultZValue() ); + } return newPoint; } -#ifdef Q_OS_WIN -bool QgsMapToolCapture::eventFilter( QObject *obj, QEvent *event ) +QgsPoint QgsMapToolCapture::mapPoint( const QgsMapMouseEvent &e ) const { - if ( event->type() != QEvent::ContextMenu ) - return false; + QgsPoint newPoint = mapPoint( e.mapPoint() ); + + // set z value from snapped point if necessary + if ( QgsWkbTypes::hasZ( newPoint.wkbType() ) ) + { + // if snapped, z dimension is taken from the corresponding snapped + // point. + if ( e.isSnapped() ) + { + const QgsPointLocator::Match match = e.mapPointMatch(); + const QgsWkbTypes::Type snappedType = match.layer()->wkbType(); - if ( --mSkipNextContextMenuEvent == 0 ) - obj->removeEventFilter( this ); + if ( QgsWkbTypes::hasZ( snappedType ) ) + { + const QgsFeature ft = match.layer()->getFeature( match.featureId() ); + newPoint.setZ( ft.geometry().vertexAt( match.vertexIndex() ).z() ); + } + } + } - return mSkipNextContextMenuEvent >= 0; + return newPoint; } -#endif diff --git a/src/gui/qgsmaptoolcapture.h b/src/gui/qgsmaptoolcapture.h index b764610c31b3..ad58c15cb887 100644 --- a/src/gui/qgsmaptoolcapture.h +++ b/src/gui/qgsmaptoolcapture.h @@ -149,15 +149,28 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing /** * Creates a QgsPoint with ZM support if necessary (according to the - * WkbType of the current layer) from a QgsPointXY. + * WkbType of the current layer). If the point is snapped, then the Z + * value is took from the snapped point. * - * \param point A QgsPointXY to convert + * \param e A mouse event * - * \returns a point if ZM support if necessary + * \returns a point with ZM support if necessary * * \since QGIS 3.0 */ - QgsPoint fromPointXY( const QgsPointXY &point ) const; + QgsPoint mapPoint( const QgsMapMouseEvent &e ) const; + + /** + * Creates a QgsPoint with ZM support if necessary (according to the + * WkbType of the current layer). + * + * \param point A point in 2D + * + * \returns a point with ZM support if necessary + * + * \since QGIS 3.0 + */ + QgsPoint mapPoint( const QgsPointXY &point ) const; /** * Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)