Skip to content
Permalink
Browse files

Merge pull request #5823 from pblottiere/bugfix_curvedstrings_z

[bugfix] Fixes #17576 and #17574 Add Z support and fixes crashes
  • Loading branch information
pblottiere committed Feb 18, 2018
2 parents 6c64c5a + 53aafb4 commit 323e75c029bb0be44a11cbd5608763d0b7ca6e34
Showing with 1,534 additions and 254 deletions.
  1. +9 −3 python/core/geometry/qgscircle.sip.in
  2. +12 −4 python/core/geometry/qgsellipse.sip.in
  3. +19 −2 python/core/geometry/qgsgeometryutils.sip.in
  4. +2 −1 python/core/geometry/qgstriangle.sip.in
  5. +27 −0 python/gui/qgsmaptoolcapture.sip.in
  6. +1 −0 src/app/qgisapp.cpp
  7. +15 −1 src/app/qgsmaptooladdcircle.cpp
  8. +2 −1 src/app/qgsmaptooladdcircle.h
  9. +2 −1 src/app/qgsmaptooladdcircularstring.h
  10. +15 −1 src/app/qgsmaptooladdellipse.cpp
  11. +2 −1 src/app/qgsmaptooladdellipse.h
  12. +24 −4 src/app/qgsmaptooladdrectangle.cpp
  13. +4 −3 src/app/qgsmaptooladdrectangle.h
  14. +15 −1 src/app/qgsmaptooladdregularpolygon.cpp
  15. +2 −1 src/app/qgsmaptooladdregularpolygon.h
  16. +6 −4 src/app/qgsmaptoolcircle2points.cpp
  17. +2 −1 src/app/qgsmaptoolcircle2points.h
  18. +5 −5 src/app/qgsmaptoolcircle2tangentspoint.cpp
  19. +1 −1 src/app/qgsmaptoolcircle2tangentspoint.h
  20. +5 −5 src/app/qgsmaptoolcircle3points.cpp
  21. +2 −1 src/app/qgsmaptoolcircle3points.h
  22. +10 −10 src/app/qgsmaptoolcircle3tangents.cpp
  23. +6 −4 src/app/qgsmaptoolcirclecenterpoint.cpp
  24. +2 −1 src/app/qgsmaptoolcirclecenterpoint.h
  25. +4 −4 src/app/qgsmaptoolcircularstringcurvepoint.cpp
  26. +2 −1 src/app/qgsmaptoolcircularstringcurvepoint.h
  27. +5 −5 src/app/qgsmaptoolcircularstringradius.cpp
  28. +2 −1 src/app/qgsmaptoolcircularstringradius.h
  29. +5 −5 src/app/qgsmaptoolellipsecenter2points.cpp
  30. +2 −1 src/app/qgsmaptoolellipsecenter2points.h
  31. +4 −4 src/app/qgsmaptoolellipsecenterpoint.cpp
  32. +2 −1 src/app/qgsmaptoolellipsecenterpoint.h
  33. +6 −6 src/app/qgsmaptoolellipseextent.cpp
  34. +2 −1 src/app/qgsmaptoolellipseextent.h
  35. +5 −5 src/app/qgsmaptoolellipsefoci.cpp
  36. +2 −1 src/app/qgsmaptoolellipsefoci.h
  37. +15 −15 src/app/qgsmaptoolrectangle3points.cpp
  38. +2 −1 src/app/qgsmaptoolrectangle3points.h
  39. +11 −9 src/app/qgsmaptoolrectanglecenter.cpp
  40. +2 −1 src/app/qgsmaptoolrectanglecenter.h
  41. +9 −7 src/app/qgsmaptoolrectangleextent.cpp
  42. +2 −1 src/app/qgsmaptoolrectangleextent.h
  43. +6 −4 src/app/qgsmaptoolregularpolygon2points.cpp
  44. +2 −1 src/app/qgsmaptoolregularpolygon2points.h
  45. +6 −4 src/app/qgsmaptoolregularpolygoncentercorner.cpp
  46. +2 −1 src/app/qgsmaptoolregularpolygoncentercorner.h
  47. +6 −4 src/app/qgsmaptoolregularpolygoncenterpoint.cpp
  48. +2 −1 src/app/qgsmaptoolregularpolygoncenterpoint.h
  49. +9 −1 src/app/vertextool/qgsvertextool.cpp
  50. +2 −0 src/app/vertextool/qgsvertextool.h
  51. +33 −6 src/core/geometry/qgscircle.cpp
  52. +9 −3 src/core/geometry/qgscircle.h
  53. +12 −2 src/core/geometry/qgsellipse.cpp
  54. +12 −4 src/core/geometry/qgsellipse.h
  55. +25 −0 src/core/geometry/qgsgeometryutils.cpp
  56. +20 −2 src/core/geometry/qgsgeometryutils.h
  57. +7 −4 src/core/geometry/qgstriangle.cpp
  58. +2 −1 src/core/geometry/qgstriangle.h
  59. +59 −0 src/gui/qgsmaptoolcapture.cpp
  60. +25 −0 src/gui/qgsmaptoolcapture.h
  61. +5 −0 tests/src/app/CMakeLists.txt
  62. +97 −91 tests/src/app/testqgsmaptooladdfeature.cpp
  63. +158 −0 tests/src/app/testqgsmaptoolcircle.cpp
  64. +133 −0 tests/src/app/testqgsmaptoolcircularstring.cpp
  65. +206 −0 tests/src/app/testqgsmaptoolellipse.cpp
  66. +160 −0 tests/src/app/testqgsmaptoolrectangle.cpp
  67. +158 −0 tests/src/app/testqgsmaptoolregularpolygon.cpp
  68. +101 −0 tests/src/app/testqgsmaptoolutils.h
  69. +5 −0 tests/src/core/testqgsgeometry.cpp
@@ -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.

@@ -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``.

@@ -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 );
@@ -388,6 +392,19 @@ 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

.. versionadded:: 3.0
%End


};

@@ -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 vertices.

:return: The center of the inscribed circle of the triangle.
An empty point is returned for empty triangle.
@@ -102,6 +102,33 @@ convenient method to clean members

int fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint );

QgsPoint mapPoint( const QgsMapMouseEvent &e ) const;
%Docstring
Creates a QgsPoint with ZM support if necessary (according to the
WkbType of the current layer). If the point is snapped, then the Z
value is took from the snapped point.

:param e: A mouse event

: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
%End

int addVertex( const QgsPointXY &point );

int addVertex( const QgsPointXY &mapPoint, const QgsPointLocator::Match &match );
@@ -1311,6 +1311,7 @@ QgisApp::QgisApp()
mMapCanvas->freeze();
mLayerTreeView = new QgsLayerTreeView( this );
mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas );
mUserInputDockWidget = new QgsUserInputWidget( this );
mInfoBar = new QgsMessageBar( centralWidget() );
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this );
mPanelMenu = new QMenu( this );
@@ -68,7 +68,21 @@ void QgsMapToolAddCircle::deactivate()
}

mParentTool->clearCurve();
mParentTool->addCurve( mCircle.toCircularString() );

// keep z value from the first snapped point
std::unique_ptr<QgsCircularString> 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();
@@ -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

@@ -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:
@@ -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<QgsLineString> 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();
@@ -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:
@@ -84,7 +84,7 @@ void QgsMapToolAddRectangle::keyReleaseEvent( QKeyEvent *e )
QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOriented ) const
{
std::unique_ptr<QgsLineString> ext( new QgsLineString() );
if ( mRectangle.isEmpty() )
if ( mRectangle.toRectangle().isEmpty() )
{
return ext.release();
}
@@ -105,19 +105,39 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien
x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() );
x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() );
}

ext->addVertex( x0 );
ext->addVertex( x1 );
ext->addVertex( x2 );
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();
}

QgsPolygon *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) const
{
std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() );
if ( mRectangle.isEmpty() )
if ( mRectangle.toRectangle().isEmpty() )
{
return polygon.release();
}
@@ -129,7 +149,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 +182,5 @@ void QgsMapToolAddRectangle::clean()
mParentTool->deleteTempRubberBand();
}

mRectangle = QgsRectangle();
mRectangle = QgsBox3d();
}
@@ -17,12 +17,13 @@
#define QGSMAPTOOLADDRECTANGLE_H

#include "qgspolygon.h"
#include "qgsrectangle.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

@@ -51,7 +52,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;
@@ -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<QgsLineString> 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();
@@ -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

0 comments on commit 323e75c

Please sign in to comment.
You can’t perform that action at this time.