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 );
%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``.

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 );
%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.

Expand Down Expand Up @@ -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.

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 );
%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``.

Expand All @@ -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.

Expand All @@ -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.

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 );
%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``.

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/ );
%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
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 );
%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 );
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]
%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;
%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.
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 );

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 );
Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -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 );
Expand Down
16 changes: 15 additions & 1 deletion src/app/qgsmaptooladdcircle.cpp
Expand Up @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdcircle.h
Expand Up @@ -18,6 +18,7 @@

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

class QgsGeometryRubberBand;

Expand All @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdcircularstring.h
Expand Up @@ -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:
Expand Down
16 changes: 15 additions & 1 deletion src/app/qgsmaptooladdellipse.cpp
Expand Up @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdellipse.h
Expand Up @@ -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:
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
{
std::unique_ptr<QgsLineString> ext( new QgsLineString() );
if ( mRectangle.isEmpty() )
if ( mRectangle.toRectangle().isEmpty() )
{
return ext.release();
}
Expand All @@ -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();
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -162,5 +182,5 @@ void QgsMapToolAddRectangle::clean()
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

#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

Expand Down Expand Up @@ -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;
Expand Down
16 changes: 15 additions & 1 deletion src/app/qgsmaptooladdregularpolygon.cpp
Expand Up @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsmaptooladdregularpolygon.h
Expand Up @@ -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

Expand Down

0 comments on commit 323e75c

Please sign in to comment.