Skip to content

Commit 2964c33

Browse files
committed
Reshape tool: use default Z value for 3D geometries
1 parent f5b38fe commit 2964c33

File tree

9 files changed

+125
-7
lines changed

9 files changed

+125
-7
lines changed

doc/api_break.dox

+1
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,7 @@ empty geometry collection)
12331233
- smoothLine and smoothPolygon are no longer public API (use smooth() instead)
12341234
- avoidIntersections() got an extra argument: list of layers to include in the operation (previously read from active QgsProject)
12351235
- isGeosEmpty() was removed. Use isEmpty() instead.
1236+
- reshapeGeometry() expects QgsLineString as a parameter instead of a list of 2D points (so that it can support 3D geometries)
12361237

12371238

12381239
QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer}

python/core/geometry/qgsgeometry.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ not disjoint with existing polygons of the feature
488488
:rtype: int
489489
%End
490490

491-
int reshapeGeometry( const QList<QgsPointXY> &reshapeWithLine );
491+
int reshapeGeometry( const QgsLineString &reshapeLineString );
492492
%Docstring
493493
Replaces a part of this geometry with another line
494494
:return: 0 in case of success

python/core/geometry/qgslinestring.sip

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ class QgsLineString: QgsCurve
2626
public:
2727
QgsLineString();
2828

29+
QgsLineString( const QVector<QgsPoint> &points );
30+
%Docstring
31+
Construct a linestring from a vector of points.
32+
.. versionadded:: 3.0
33+
%End
34+
2935
QgsLineString( const QVector<double> &x, const QVector<double> &y,
3036
const QVector<double> &z = QVector<double>(),
3137
const QVector<double> &m = QVector<double>() );

src/app/qgsmaptoolreshape.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "qgsmaptoolreshape.h"
1717
#include "qgsfeatureiterator.h"
1818
#include "qgsgeometry.h"
19+
#include "qgslinestring.h"
1920
#include "qgsmapcanvas.h"
2021
#include "qgsproject.h"
2122
#include "qgsvectorlayer.h"
@@ -84,6 +85,10 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
8485
bbox.combineExtentWith( points().at( i ).x(), points().at( i ).y() );
8586
}
8687

88+
QgsLineString reshapeLineString( points() );
89+
if ( QgsWkbTypes::hasZ( vlayer->wkbType() ) )
90+
reshapeLineString.addZValue( defaultZValue() );
91+
8792
//query all the features that intersect bounding box of capture line
8893
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bbox ).setSubsetOfAttributes( QgsAttributeList() ) );
8994
QgsFeature f;
@@ -99,7 +104,7 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
99104
QgsGeometry geom = f.geometry();
100105
if ( !geom.isNull() )
101106
{
102-
reshapeReturn = geom.reshapeGeometry( points() );
107+
reshapeReturn = geom.reshapeGeometry( reshapeLineString );
103108
if ( reshapeReturn == 0 )
104109
{
105110
//avoid intersections on polygon layers

src/core/geometry/qgsgeometry.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -816,15 +816,13 @@ int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeo
816816
return result;
817817
}
818818

819-
int QgsGeometry::reshapeGeometry( const QList<QgsPointXY> &reshapeWithLine )
819+
int QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
820820
{
821821
if ( !d->geometry )
822822
{
823823
return 0;
824824
}
825825

826-
QgsLineString reshapeLineString( reshapeWithLine );
827-
828826
QgsGeos geos( d->geometry );
829827
int errorCode = 0;
830828
QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );

src/core/geometry/qgsgeometry.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ class CORE_EXPORT QgsGeometry
491491
* \returns 0 in case of success
492492
* \since QGIS 1.3
493493
*/
494-
int reshapeGeometry( const QList<QgsPointXY> &reshapeWithLine );
494+
int reshapeGeometry( const QgsLineString &reshapeLineString );
495495

496496
/** Changes this geometry such that it does not intersect the other geometry
497497
* \param other geometry that should not be intersect

src/core/geometry/qgslinestring.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@ QgsLineString::QgsLineString(): QgsCurve()
4040
mWkbType = QgsWkbTypes::LineString;
4141
}
4242

43+
QgsLineString::QgsLineString( const QVector<QgsPoint> &points )
44+
{
45+
if ( points.isEmpty() )
46+
{
47+
mWkbType = QgsWkbTypes::LineString;
48+
return;
49+
}
50+
QgsWkbTypes::Type ptType = points.at( 0 ).wkbType();
51+
mWkbType = QgsWkbTypes::zmType( QgsWkbTypes::LineString, QgsWkbTypes::hasZ( ptType ), QgsWkbTypes::hasM( ptType ) );
52+
mX.resize( points.count() );
53+
mY.resize( points.count() );
54+
double *x = mX.data();
55+
double *y = mY.data();
56+
double *z = nullptr;
57+
double *m = nullptr;
58+
if ( QgsWkbTypes::hasZ( mWkbType ) )
59+
{
60+
mZ.resize( points.count() );
61+
z = mZ.data();
62+
}
63+
if ( QgsWkbTypes::hasM( mWkbType ) )
64+
{
65+
mM.resize( points.count() );
66+
m = mM.data();
67+
}
68+
69+
Q_FOREACH ( const QgsPoint &pt, points )
70+
{
71+
*x++ = pt.x();
72+
*y++ = pt.y();
73+
if ( z )
74+
*z++ = pt.z();
75+
if ( m )
76+
*m++ = pt.m();
77+
}
78+
}
79+
4380
QgsLineString::QgsLineString( const QVector<double> &x, const QVector<double> &y, const QVector<double> &z, const QVector<double> &m )
4481
{
4582
mWkbType = QgsWkbTypes::LineString;

src/core/geometry/qgslinestring.h

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class CORE_EXPORT QgsLineString: public QgsCurve
4242
public:
4343
QgsLineString();
4444

45+
/**
46+
* Construct a linestring from a vector of points.
47+
* \since QGIS 3.0
48+
*/
49+
QgsLineString( const QVector<QgsPoint> &points );
50+
4551
/**
4652
* Construct a linestring from arrays of coordinates. If the z or m
4753
* arrays are non-empty then the resultant linestring will have

tests/src/core/testqgsgeometry.cpp

+66-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ class TestQgsGeometry : public QObject
126126

127127
void isSimple();
128128

129+
void reshapeGeometryLineMerge();
130+
129131
private:
130132
//! A helper method to do a render check to see if the geometry op is as expected
131133
bool renderCheck( const QString &testName, const QString &comment = QLatin1String( QLatin1String( "" ) ), int mismatchCount = 0 );
@@ -1078,7 +1080,27 @@ void TestQgsGeometry::lineString()
10781080
QCOMPARE( fromPts.xAt( 2 ), 21.0 );
10791081
QCOMPARE( fromPts.yAt( 2 ), 22.0 );
10801082

1081-
1083+
// from QVector<QgsPoint>
1084+
QVector<QgsPoint> ptsVector;
1085+
ptsVector << QgsPoint( 10, 20 ) << QgsPoint( 30, 40 );
1086+
QgsLineString fromVector( ptsVector );
1087+
QCOMPARE( fromVector.wkbType(), QgsWkbTypes::LineString );
1088+
QCOMPARE( fromVector.numPoints(), 2 );
1089+
QCOMPARE( fromVector.xAt( 0 ), 10.0 );
1090+
QCOMPARE( fromVector.yAt( 0 ), 20.0 );
1091+
QCOMPARE( fromVector.xAt( 1 ), 30.0 );
1092+
QCOMPARE( fromVector.yAt( 1 ), 40.0 );
1093+
QVector<QgsPoint> ptsVector3D;
1094+
ptsVector3D << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 40, 200 );
1095+
QgsLineString fromVector3D( ptsVector3D );
1096+
QCOMPARE( fromVector3D.wkbType(), QgsWkbTypes::LineStringZ );
1097+
QCOMPARE( fromVector3D.numPoints(), 2 );
1098+
QCOMPARE( fromVector3D.xAt( 0 ), 10.0 );
1099+
QCOMPARE( fromVector3D.yAt( 0 ), 20.0 );
1100+
QCOMPARE( fromVector3D.zAt( 0 ), 100.0 );
1101+
QCOMPARE( fromVector3D.xAt( 1 ), 30.0 );
1102+
QCOMPARE( fromVector3D.yAt( 1 ), 40.0 );
1103+
QCOMPARE( fromVector3D.zAt( 1 ), 200.0 );
10821104

10831105
//addVertex
10841106
QgsLineString l2;
@@ -5452,5 +5474,48 @@ void TestQgsGeometry::isSimple()
54525474
}
54535475
}
54545476

5477+
void TestQgsGeometry::reshapeGeometryLineMerge()
5478+
{
5479+
int res;
5480+
QgsGeometry g2D = QgsGeometry::fromWkt( "LINESTRING(10 10, 20 20)" );
5481+
QgsGeometry g3D = QgsGeometry::fromWkt( "LINESTRINGZ(10 10 1, 20 20 2)" );
5482+
5483+
// prepare 2D reshaping line
5484+
QVector<QgsPoint> v2D_1, v2D_2;
5485+
v2D_1 << QgsPoint( 20, 20 ) << QgsPoint( 30, 30 );
5486+
v2D_2 << QgsPoint( 10, 10 ) << QgsPoint( -10, -10 );
5487+
QgsLineString line2D_1( v2D_1 ), line2D_2( v2D_2 );
5488+
5489+
// prepare 3D reshaping line
5490+
QVector<QgsPoint> v3D_1, v3D_2;
5491+
v3D_1 << QgsPoint( QgsWkbTypes::PointZ, 20, 20, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 30, 3 );
5492+
v3D_2 << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZ, -10, -10, -1 );
5493+
QgsLineString line3D_1( v3D_1 ), line3D_2( v3D_2 );
5494+
5495+
// append with 2D line
5496+
QgsGeometry g2D_1 = g2D;
5497+
res = g2D_1.reshapeGeometry( line2D_1 );
5498+
QCOMPARE( res, 0 );
5499+
QCOMPARE( g2D_1.exportToWkt(), QString( "LineString (10 10, 20 20, 30 30)" ) );
5500+
5501+
// prepend with 2D line
5502+
QgsGeometry g2D_2 = g2D;
5503+
res = g2D_2.reshapeGeometry( line2D_2 );
5504+
QCOMPARE( res, 0 );
5505+
QCOMPARE( g2D_2.exportToWkt(), QString( "LineString (-10 -10, 10 10, 20 20)" ) );
5506+
5507+
// append with 3D line
5508+
QgsGeometry g3D_1 = g3D;
5509+
res = g3D_1.reshapeGeometry( line3D_1 );
5510+
QCOMPARE( res, 0 );
5511+
QCOMPARE( g3D_1.exportToWkt(), QString( "LineStringZ (10 10 1, 20 20 2, 30 30 3)" ) );
5512+
5513+
// prepend with 3D line
5514+
QgsGeometry g3D_2 = g3D;
5515+
res = g3D_2.reshapeGeometry( line3D_2 );
5516+
QCOMPARE( res, 0 );
5517+
QCOMPARE( g3D_2.exportToWkt(), QString( "LineStringZ (-10 -10 -1, 10 10 1, 20 20 2)" ) );
5518+
}
5519+
54555520
QGSTEST_MAIN( TestQgsGeometry )
54565521
#include "testqgsgeometry.moc"

0 commit comments

Comments
 (0)