Skip to content
Permalink
Browse files

Reshape tool: use default Z value for 3D geometries

  • Loading branch information
wonder-sk committed Jun 8, 2017
1 parent f5b38fe commit 2964c33d638b1a3e1fd535cd9df3ca7ecf98a2b7
@@ -1233,6 +1233,7 @@ empty geometry collection)
- smoothLine and smoothPolygon are no longer public API (use smooth() instead)
- avoidIntersections() got an extra argument: list of layers to include in the operation (previously read from active QgsProject)
- isGeosEmpty() was removed. Use isEmpty() instead.
- reshapeGeometry() expects QgsLineString as a parameter instead of a list of 2D points (so that it can support 3D geometries)


QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer}
@@ -488,7 +488,7 @@ not disjoint with existing polygons of the feature
:rtype: int
%End

int reshapeGeometry( const QList<QgsPointXY> &reshapeWithLine );
int reshapeGeometry( const QgsLineString &reshapeLineString );
%Docstring
Replaces a part of this geometry with another line
:return: 0 in case of success
@@ -26,6 +26,12 @@ class QgsLineString: QgsCurve
public:
QgsLineString();

QgsLineString( const QVector<QgsPoint> &points );
%Docstring
Construct a linestring from a vector of points.
.. versionadded:: 3.0
%End

QgsLineString( const QVector<double> &x, const QVector<double> &y,
const QVector<double> &z = QVector<double>(),
const QVector<double> &m = QVector<double>() );
@@ -16,6 +16,7 @@
#include "qgsmaptoolreshape.h"
#include "qgsfeatureiterator.h"
#include "qgsgeometry.h"
#include "qgslinestring.h"
#include "qgsmapcanvas.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
@@ -84,6 +85,10 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
bbox.combineExtentWith( points().at( i ).x(), points().at( i ).y() );
}

QgsLineString reshapeLineString( points() );
if ( QgsWkbTypes::hasZ( vlayer->wkbType() ) )
reshapeLineString.addZValue( defaultZValue() );

//query all the features that intersect bounding box of capture line
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bbox ).setSubsetOfAttributes( QgsAttributeList() ) );
QgsFeature f;
@@ -99,7 +104,7 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
QgsGeometry geom = f.geometry();
if ( !geom.isNull() )
{
reshapeReturn = geom.reshapeGeometry( points() );
reshapeReturn = geom.reshapeGeometry( reshapeLineString );
if ( reshapeReturn == 0 )
{
//avoid intersections on polygon layers
@@ -816,15 +816,13 @@ int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeo
return result;
}

int QgsGeometry::reshapeGeometry( const QList<QgsPointXY> &reshapeWithLine )
int QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
{
if ( !d->geometry )
{
return 0;
}

QgsLineString reshapeLineString( reshapeWithLine );

QgsGeos geos( d->geometry );
int errorCode = 0;
QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
@@ -491,7 +491,7 @@ class CORE_EXPORT QgsGeometry
* \returns 0 in case of success
* \since QGIS 1.3
*/
int reshapeGeometry( const QList<QgsPointXY> &reshapeWithLine );
int reshapeGeometry( const QgsLineString &reshapeLineString );

/** Changes this geometry such that it does not intersect the other geometry
* \param other geometry that should not be intersect
@@ -40,6 +40,43 @@ QgsLineString::QgsLineString(): QgsCurve()
mWkbType = QgsWkbTypes::LineString;
}

QgsLineString::QgsLineString( const QVector<QgsPoint> &points )
{
if ( points.isEmpty() )
{
mWkbType = QgsWkbTypes::LineString;
return;
}
QgsWkbTypes::Type ptType = points.at( 0 ).wkbType();
mWkbType = QgsWkbTypes::zmType( QgsWkbTypes::LineString, QgsWkbTypes::hasZ( ptType ), QgsWkbTypes::hasM( ptType ) );
mX.resize( points.count() );
mY.resize( points.count() );
double *x = mX.data();
double *y = mY.data();
double *z = nullptr;
double *m = nullptr;
if ( QgsWkbTypes::hasZ( mWkbType ) )
{
mZ.resize( points.count() );
z = mZ.data();
}
if ( QgsWkbTypes::hasM( mWkbType ) )
{
mM.resize( points.count() );
m = mM.data();
}

Q_FOREACH ( const QgsPoint &pt, points )
{
*x++ = pt.x();
*y++ = pt.y();
if ( z )
*z++ = pt.z();
if ( m )
*m++ = pt.m();
}
}

QgsLineString::QgsLineString( const QVector<double> &x, const QVector<double> &y, const QVector<double> &z, const QVector<double> &m )
{
mWkbType = QgsWkbTypes::LineString;
@@ -42,6 +42,12 @@ class CORE_EXPORT QgsLineString: public QgsCurve
public:
QgsLineString();

/**
* Construct a linestring from a vector of points.
* \since QGIS 3.0
*/
QgsLineString( const QVector<QgsPoint> &points );

/**
* Construct a linestring from arrays of coordinates. If the z or m
* arrays are non-empty then the resultant linestring will have
@@ -126,6 +126,8 @@ class TestQgsGeometry : public QObject

void isSimple();

void reshapeGeometryLineMerge();

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


// from QVector<QgsPoint>
QVector<QgsPoint> ptsVector;
ptsVector << QgsPoint( 10, 20 ) << QgsPoint( 30, 40 );
QgsLineString fromVector( ptsVector );
QCOMPARE( fromVector.wkbType(), QgsWkbTypes::LineString );
QCOMPARE( fromVector.numPoints(), 2 );
QCOMPARE( fromVector.xAt( 0 ), 10.0 );
QCOMPARE( fromVector.yAt( 0 ), 20.0 );
QCOMPARE( fromVector.xAt( 1 ), 30.0 );
QCOMPARE( fromVector.yAt( 1 ), 40.0 );
QVector<QgsPoint> ptsVector3D;
ptsVector3D << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 40, 200 );
QgsLineString fromVector3D( ptsVector3D );
QCOMPARE( fromVector3D.wkbType(), QgsWkbTypes::LineStringZ );
QCOMPARE( fromVector3D.numPoints(), 2 );
QCOMPARE( fromVector3D.xAt( 0 ), 10.0 );
QCOMPARE( fromVector3D.yAt( 0 ), 20.0 );
QCOMPARE( fromVector3D.zAt( 0 ), 100.0 );
QCOMPARE( fromVector3D.xAt( 1 ), 30.0 );
QCOMPARE( fromVector3D.yAt( 1 ), 40.0 );
QCOMPARE( fromVector3D.zAt( 1 ), 200.0 );

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

void TestQgsGeometry::reshapeGeometryLineMerge()
{
int res;
QgsGeometry g2D = QgsGeometry::fromWkt( "LINESTRING(10 10, 20 20)" );
QgsGeometry g3D = QgsGeometry::fromWkt( "LINESTRINGZ(10 10 1, 20 20 2)" );

// prepare 2D reshaping line
QVector<QgsPoint> v2D_1, v2D_2;
v2D_1 << QgsPoint( 20, 20 ) << QgsPoint( 30, 30 );
v2D_2 << QgsPoint( 10, 10 ) << QgsPoint( -10, -10 );
QgsLineString line2D_1( v2D_1 ), line2D_2( v2D_2 );

// prepare 3D reshaping line
QVector<QgsPoint> v3D_1, v3D_2;
v3D_1 << QgsPoint( QgsWkbTypes::PointZ, 20, 20, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 30, 3 );
v3D_2 << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZ, -10, -10, -1 );
QgsLineString line3D_1( v3D_1 ), line3D_2( v3D_2 );

// append with 2D line
QgsGeometry g2D_1 = g2D;
res = g2D_1.reshapeGeometry( line2D_1 );
QCOMPARE( res, 0 );
QCOMPARE( g2D_1.exportToWkt(), QString( "LineString (10 10, 20 20, 30 30)" ) );

// prepend with 2D line
QgsGeometry g2D_2 = g2D;
res = g2D_2.reshapeGeometry( line2D_2 );
QCOMPARE( res, 0 );
QCOMPARE( g2D_2.exportToWkt(), QString( "LineString (-10 -10, 10 10, 20 20)" ) );

// append with 3D line
QgsGeometry g3D_1 = g3D;
res = g3D_1.reshapeGeometry( line3D_1 );
QCOMPARE( res, 0 );
QCOMPARE( g3D_1.exportToWkt(), QString( "LineStringZ (10 10 1, 20 20 2, 30 30 3)" ) );

// prepend with 3D line
QgsGeometry g3D_2 = g3D;
res = g3D_2.reshapeGeometry( line3D_2 );
QCOMPARE( res, 0 );
QCOMPARE( g3D_2.exportToWkt(), QString( "LineStringZ (-10 -10 -1, 10 10 1, 20 20 2)" ) );
}

QGSTEST_MAIN( TestQgsGeometry )
#include "testqgsgeometry.moc"

0 comments on commit 2964c33

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