Skip to content

Commit

Permalink
Merge pull request #5823 from pblottiere/bugfix_curvedstrings_z
Browse files Browse the repository at this point in the history
[bugfix] Fixes #17576 and #17574 Add Z support and fixes crashes
  • Loading branch information
pblottiere committed Feb 18, 2018
2 parents 6c64c5a + 53aafb4 commit 323e75c
Show file tree
Hide file tree
Showing 69 changed files with 1,534 additions and 254 deletions.
12 changes: 9 additions & 3 deletions python/core/geometry/qgscircle.sip.in
Expand Up @@ -42,7 +42,9 @@ Constructs a circle by defining all the members.
static QgsCircle from2Points( const QgsPoint &pt1, const QgsPoint &pt2 ); static QgsCircle from2Points( const QgsPoint &pt1, const QgsPoint &pt2 );
%Docstring %Docstring
Constructs a circle by 2 points on the circle. 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 radius is calculated from the 2D distance between ``pt1`` and ``pt2``.
The azimuth is the angle between ``pt1`` and ``pt2``. The azimuth is the angle between ``pt1`` and ``pt2``.


Expand All @@ -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 ); static QgsCircle from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon = 1E-8 );
%Docstring %Docstring
Constructs a circle by 3 points on the circle. 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. The azimuth always takes the default value.
If the points are colinear an empty circle is returned. If the points are colinear an empty circle is returned.


Expand Down Expand Up @@ -106,7 +110,9 @@ The azimuth always takes the default value.
static QgsCircle fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ); static QgsCircle fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 );
%Docstring %Docstring
Constructs a circle by an extent (aka bounding box / :py:class:`QgsRectangle`). 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``. Axes are calculated from the 2D distance between ``pt1`` and ``pt2``.
The azimuth always takes the default value. The azimuth always takes the default value.


Expand Down
16 changes: 12 additions & 4 deletions python/core/geometry/qgsellipse.sip.in
Expand Up @@ -47,7 +47,9 @@ Constructs an ellipse by defining all the members.
static QgsEllipse fromFoci( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3 ); static QgsEllipse fromFoci( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3 );
%Docstring %Docstring
Constructs an ellipse by foci (``pt1`` and ``pt2``) and a point ``pt3``. 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``. Axes are calculated from the 2D distance with the third point ``pt3``.
The azimuth is the angle between ``pt1`` and ``pt2``. The azimuth is the angle between ``pt1`` and ``pt2``.


Expand All @@ -59,7 +61,9 @@ The azimuth is the angle between ``pt1`` and ``pt2``.
static QgsEllipse fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ); static QgsEllipse fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 );
%Docstring %Docstring
Constructs an ellipse by an extent (aka bounding box / :py:class:`QgsRectangle`). 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``. Axes are calculated from the 2D distance between ``pt1`` and ``pt2``.
The azimuth always takes the default value. The azimuth always takes the default value.


Expand All @@ -70,7 +74,9 @@ The azimuth always takes the default value.
static QgsEllipse fromCenterPoint( const QgsPoint &ptc, const QgsPoint &pt1 ); static QgsEllipse fromCenterPoint( const QgsPoint &ptc, const QgsPoint &pt1 );
%Docstring %Docstring
Constructs an ellipse by a center point and a another point. 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``. Axes are calculated from the 2D distance between ``ptc`` and ``pt1``.
The azimuth always takes the default value. The azimuth always takes the default value.


Expand All @@ -81,7 +87,9 @@ The azimuth always takes the default value.
static QgsEllipse fromCenter2Points( const QgsPoint &ptc, const QgsPoint &pt1, const QgsPoint &pt2 ); static QgsEllipse fromCenter2Points( const QgsPoint &ptc, const QgsPoint &pt1, const QgsPoint &pt2 );
%Docstring %Docstring
Constructs an ellipse by a central point and two other points. 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``. Axes are calculated from the 2D distance between ``ptc`` and ``pt1`` and ``pt2``.
The azimuth is the angle between ``ptc`` and ``pt1``. The azimuth is the angle between ``ptc`` and ``pt1``.


Expand Down
21 changes: 19 additions & 2 deletions python/core/geometry/qgsgeometryutils.sip.in
Expand Up @@ -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/ ); static bool lineIntersection( const QgsPoint &p1, QgsVector v1, const QgsPoint &p2, QgsVector v2, QgsPoint &intersection /Out/ );
%Docstring %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 p1: Point on the first line
:param v1: Direction vector of the first line :param v1: Direction vector of the first line
Expand Down Expand Up @@ -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 ); static bool segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2, QgsPoint &result /Out/, double radius, const QgsPoint &mousePos );
%Docstring %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 %End


static double circleTangentDirection( const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3 ); static double circleTangentDirection( const QgsPoint &tangentPoint, const QgsPoint &cp1, const QgsPoint &cp2, const QgsPoint &cp3 );
Expand Down Expand Up @@ -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] :return: A line (segment) from p to perpendicular point on segment [s1, s2]
%End %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



}; };


Expand Down
3 changes: 2 additions & 1 deletion python/core/geometry/qgstriangle.sip.in
Expand Up @@ -378,7 +378,8 @@ Example:


QgsPoint inscribedCenter() const; QgsPoint inscribedCenter() const;
%Docstring %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. :return: The center of the inscribed circle of the triangle.
An empty point is returned for empty triangle. An empty point is returned for empty triangle.
Expand Down
27 changes: 27 additions & 0 deletions python/gui/qgsmaptoolcapture.sip.in
Expand Up @@ -102,6 +102,33 @@ convenient method to clean members


int fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ); 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 &point );


int addVertex( const QgsPointXY &mapPoint, const QgsPointLocator::Match &match ); int addVertex( const QgsPointXY &mapPoint, const QgsPointLocator::Match &match );
Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -1311,6 +1311,7 @@ QgisApp::QgisApp()
mMapCanvas->freeze(); mMapCanvas->freeze();
mLayerTreeView = new QgsLayerTreeView( this ); mLayerTreeView = new QgsLayerTreeView( this );
mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas ); mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas );
mUserInputDockWidget = new QgsUserInputWidget( this );
mInfoBar = new QgsMessageBar( centralWidget() ); mInfoBar = new QgsMessageBar( centralWidget() );
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this ); mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this );
mPanelMenu = new QMenu( this ); mPanelMenu = new QMenu( this );
Expand Down
16 changes: 15 additions & 1 deletion src/app/qgsmaptooladdcircle.cpp
Expand Up @@ -68,7 +68,21 @@ void QgsMapToolAddCircle::deactivate()
} }


mParentTool->clearCurve(); 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(); clean();


QgsMapToolCapture::deactivate(); QgsMapToolCapture::deactivate();
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdcircle.h
Expand Up @@ -18,6 +18,7 @@


#include "qgsmaptoolcapture.h" #include "qgsmaptoolcapture.h"
#include "qgscircle.h" #include "qgscircle.h"
#include "qgis_app.h"


class QgsGeometryRubberBand; class QgsGeometryRubberBand;


Expand All @@ -26,7 +27,7 @@ struct EdgesOnlyFilter : public QgsPointLocator::MatchFilter
bool acceptMatch( const QgsPointLocator::Match &m ) override { return m.hasEdge(); } bool acceptMatch( const QgsPointLocator::Match &m ) override { return m.hasEdge(); }
}; };


class QgsMapToolAddCircle: public QgsMapToolCapture class APP_EXPORT QgsMapToolAddCircle: public QgsMapToolCapture
{ {
Q_OBJECT Q_OBJECT


Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdcircularstring.h
Expand Up @@ -17,10 +17,11 @@
#define QGSMAPTOOLADDCIRCULARSTRING_H #define QGSMAPTOOLADDCIRCULARSTRING_H


#include "qgsmaptoolcapture.h" #include "qgsmaptoolcapture.h"
#include "qgis_app.h"


class QgsGeometryRubberBand; class QgsGeometryRubberBand;


class QgsMapToolAddCircularString: public QgsMapToolCapture class APP_EXPORT QgsMapToolAddCircularString: public QgsMapToolCapture
{ {
Q_OBJECT Q_OBJECT
public: public:
Expand Down
16 changes: 15 additions & 1 deletion src/app/qgsmaptooladdellipse.cpp
Expand Up @@ -68,7 +68,21 @@ void QgsMapToolAddEllipse::deactivate()
} }


mParentTool->clearCurve(); 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(); clean();


QgsMapToolCapture::deactivate(); QgsMapToolCapture::deactivate();
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdellipse.h
Expand Up @@ -19,10 +19,11 @@
#include "qgsmaptoolcapture.h" #include "qgsmaptoolcapture.h"
#include "qgsellipse.h" #include "qgsellipse.h"
#include "qgssettings.h" #include "qgssettings.h"
#include "qgis_app.h"


class QgsGeometryRubberBand; class QgsGeometryRubberBand;


class QgsMapToolAddEllipse: public QgsMapToolCapture class APP_EXPORT QgsMapToolAddEllipse: public QgsMapToolCapture
{ {
Q_OBJECT Q_OBJECT
public: public:
Expand Down
28 changes: 24 additions & 4 deletions src/app/qgsmaptooladdrectangle.cpp
Expand Up @@ -84,7 +84,7 @@ void QgsMapToolAddRectangle::keyReleaseEvent( QKeyEvent *e )
QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOriented ) const QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOriented ) const
{ {
std::unique_ptr<QgsLineString> ext( new QgsLineString() ); std::unique_ptr<QgsLineString> ext( new QgsLineString() );
if ( mRectangle.isEmpty() ) if ( mRectangle.toRectangle().isEmpty() )
{ {
return ext.release(); return ext.release();
} }
Expand All @@ -105,19 +105,39 @@ QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOrien
x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() ); x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() );
x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() ); x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() );
} }

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


QgsPolygon *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) const QgsPolygon *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) const
{ {
std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() ); std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() );
if ( mRectangle.isEmpty() ) if ( mRectangle.toRectangle().isEmpty() )
{ {
return polygon.release(); return polygon.release();
} }
Expand All @@ -129,7 +149,7 @@ QgsPolygon *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented )


void QgsMapToolAddRectangle::deactivate( const bool isOriented ) void QgsMapToolAddRectangle::deactivate( const bool isOriented )
{ {
if ( !mParentTool || mRectangle.isEmpty() ) if ( !mParentTool || mRectangle.toRectangle().isEmpty() )
{ {
return; return;
} }
Expand Down Expand Up @@ -162,5 +182,5 @@ void QgsMapToolAddRectangle::clean()
mParentTool->deleteTempRubberBand(); mParentTool->deleteTempRubberBand();
} }


mRectangle = QgsRectangle(); mRectangle = QgsBox3d();
} }
7 changes: 4 additions & 3 deletions src/app/qgsmaptooladdrectangle.h
Expand Up @@ -17,12 +17,13 @@
#define QGSMAPTOOLADDRECTANGLE_H #define QGSMAPTOOLADDRECTANGLE_H


#include "qgspolygon.h" #include "qgspolygon.h"
#include "qgsrectangle.h"
#include "qgsmaptoolcapture.h" #include "qgsmaptoolcapture.h"
#include "qgsbox3d.h"
#include "qgis_app.h"


class QgsPolygon; class QgsPolygon;


class QgsMapToolAddRectangle: public QgsMapToolCapture class APP_EXPORT QgsMapToolAddRectangle: public QgsMapToolCapture
{ {
Q_OBJECT Q_OBJECT


Expand Down Expand Up @@ -51,7 +52,7 @@ class QgsMapToolAddRectangle: public QgsMapToolCapture
//! The rubberband to show the rectangle currently working on //! The rubberband to show the rectangle currently working on
QgsGeometryRubberBand *mTempRubberBand = nullptr; QgsGeometryRubberBand *mTempRubberBand = nullptr;
//! Rectangle //! Rectangle
QgsRectangle mRectangle; QgsBox3d mRectangle;


//! Convenient method to export a QgsRectangle to a LineString //! Convenient method to export a QgsRectangle to a LineString
QgsLineString *rectangleToLinestring( const bool isOriented = false ) const; QgsLineString *rectangleToLinestring( const bool isOriented = false ) const;
Expand Down
16 changes: 15 additions & 1 deletion src/app/qgsmaptooladdregularpolygon.cpp
Expand Up @@ -87,7 +87,21 @@ void QgsMapToolAddRegularPolygon::deactivate()
return; return;
} }
mParentTool->clearCurve( ); 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(); clean();


QgsMapToolCapture::deactivate(); QgsMapToolCapture::deactivate();
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdregularpolygon.h
Expand Up @@ -19,10 +19,11 @@
#include "qgsregularpolygon.h" #include "qgsregularpolygon.h"
#include "qgsmaptoolcapture.h" #include "qgsmaptoolcapture.h"
#include "qgsspinbox.h" #include "qgsspinbox.h"
#include "qgis_app.h"


class QSpinBox; class QSpinBox;


class QgsMapToolAddRegularPolygon: public QgsMapToolCapture class APP_EXPORT QgsMapToolAddRegularPolygon: public QgsMapToolCapture
{ {
Q_OBJECT Q_OBJECT


Expand Down

0 comments on commit 323e75c

Please sign in to comment.