Skip to content

Commit 86e8da7

Browse files
3nidsm-kuhn
authored andcommittedAug 13, 2017
Return enum instead of int from QgsGeometry operations
1 parent 8d61554 commit 86e8da7

13 files changed

+597
-475
lines changed
 

‎python/core/geometry/qgsgeometry.sip‎

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,23 @@ class QgsGeometry
4444
#include "qgsgeometry.h"
4545
%End
4646
public:
47+
48+
enum OperationResult
49+
{
50+
Success,
51+
NothingHappened,
52+
InvalidBaseGeometry,
53+
InvalidInput,
54+
GeometryEngineError,
55+
AddPartSelectedGeometryNotFound,
56+
AddPartNotMultiGeometry,
57+
AddRingNotClosed,
58+
AddRingNotValid,
59+
AddRingCrossesExistingRings,
60+
AddRingNotInExistingFeature,
61+
SplitCannotSplitPoint,
62+
};
63+
4764
QgsGeometry();
4865
%Docstring
4966
Constructor
@@ -380,63 +397,58 @@ Returns true if WKB of the geometry is of WKBMulti* type
380397
:rtype: float
381398
%End
382399

383-
int addRing( const QList<QgsPointXY> &ring );
400+
OperationResult addRing( const QList<QgsPointXY> &ring );
384401
%Docstring
385402
Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
386-
:return: 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
387-
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*
388-
:rtype: int
403+
\param ring The ring to be added
404+
:return: OperationResult a result code: success or reason of failure
405+
:rtype: OperationResult
389406
%End
390407

391-
int addRing( QgsCurve *ring /Transfer/ );
408+
OperationResult addRing( QgsCurve *ring /Transfer/ );
392409
%Docstring
393410
Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
394-
:return: 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
395-
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*
396-
:rtype: int
411+
\param ring The ring to be added
412+
:return: OperationResult a result code: success or reason of failure
413+
:rtype: OperationResult
397414
%End
398415

399-
int addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPoints/;
416+
OperationResult addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPoints/;
400417
%Docstring
401418
Adds a new part to a the geometry.
402419
\param points points describing part to add
403420
\param geomType default geometry type to create if no existing geometry
404-
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
405-
not disjoint with existing polygons of the feature
406-
:rtype: int
421+
:return: OperationResult a result code: success or reason of failure
422+
:rtype: OperationResult
407423
%End
408424

409-
int addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPointsV2/;
425+
OperationResult addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPointsV2/;
410426
%Docstring
411427
Adds a new part to a the geometry.
412428
\param points points describing part to add
413429
\param geomType default geometry type to create if no existing geometry
414-
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
415-
not disjoint with existing polygons of the feature
416-
:rtype: int
430+
:return: OperationResult a result code: success or reason of failure
431+
:rtype: OperationResult
417432
%End
418433

419-
int addPart( QgsAbstractGeometry *part /Transfer/, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
434+
OperationResult addPart( QgsAbstractGeometry *part /Transfer/, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
420435
%Docstring
421436
Adds a new part to this geometry.
422437
\param part part to add (ownership is transferred)
423438
\param geomType default geometry type to create if no existing geometry
424-
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
425-
not disjoint with existing polygons of the feature
426-
:rtype: int
439+
:return: OperationResult a result code: success or reason of failure
440+
:rtype: OperationResult
427441
%End
428442

429443

430-
int addPart( const QgsGeometry &newPart ) /PyName=addPartGeometry/;
444+
OperationResult addPart( const QgsGeometry &newPart ) /PyName=addPartGeometry/;
431445
%Docstring
432446
Adds a new island polygon to a multipolygon feature
433-
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
434-
not disjoint with existing polygons of the feature
447+
:return: OperationResult a result code: success or reason of failure
435448
.. note::
436449

437-
available in Python bindings as addPartGeometry
438-
.. versionadded:: 2.2
439-
:rtype: int
450+
available in python bindings as addPartGeometry
451+
:rtype: OperationResult
440452
%End
441453

442454
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
@@ -448,52 +460,52 @@ not disjoint with existing polygons of the feature
448460
:rtype: QgsGeometry
449461
%End
450462

451-
int translate( double dx, double dy );
463+
OperationResult translate( double dx, double dy );
452464
%Docstring
453465
Translate this geometry by dx, dy
454-
:return: 0 in case of success*
455-
:rtype: int
466+
:return: OperationResult a result code: success or reason of failure
467+
:rtype: OperationResult
456468
%End
457469

458-
int transform( const QgsCoordinateTransform &ct );
470+
OperationResult transform( const QgsCoordinateTransform &ct );
459471
%Docstring
460472
Transform this geometry as described by CoordinateTransform ct
461-
:return: 0 in case of success*
462-
:rtype: int
473+
:return: OperationResult a result code: success or reason of failure
474+
:rtype: OperationResult
463475
%End
464476

465-
int transform( const QTransform &ct );
477+
OperationResult transform( const QTransform &ct );
466478
%Docstring
467479
Transform this geometry as described by QTransform ct
468-
.. versionadded:: 2.8
469-
:return: 0 in case of success*
470-
:rtype: int
480+
:return: OperationResult a result code: success or reason of failure
481+
:rtype: OperationResult
471482
%End
472483

473-
int rotate( double rotation, const QgsPointXY &center );
484+
OperationResult rotate( double rotation, const QgsPointXY &center );
474485
%Docstring
475486
Rotate this geometry around the Z axis
476-
.. versionadded:: 2.8
477-
\param rotation clockwise rotation in degrees
478-
\param center rotation center
479-
:return: 0 in case of success*
480-
:rtype: int
487+
\param rotation clockwise rotation in degrees
488+
\param center rotation center
489+
:return: OperationResult a result code: success or reason of failure
490+
:rtype: OperationResult
481491
%End
482492

483-
int splitGeometry( const QList<QgsPointXY> &splitLine,
484-
QList<QgsGeometry> &newGeometries /Out/,
485-
bool topological,
486-
QList<QgsPointXY> &topologyTestPoints /Out/ );
493+
OperationResult splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints );
487494
%Docstring
488-
:rtype: int
495+
Splits this geometry according to a given line.
496+
\param splitLine the line that splits the geometry
497+
\param[out] newGeometries list of new geometries that have been created with the split
498+
\param topological true if topological editing is enabled
499+
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
500+
:return: OperationResult a result code: success or reason of failure
501+
:rtype: OperationResult
489502
%End
490503

491-
int reshapeGeometry( const QgsLineString &reshapeLineString );
504+
OperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
492505
%Docstring
493506
Replaces a part of this geometry with another line
494-
:return: 0 in case of success
495-
.. versionadded:: 1.3
496-
:rtype: int
507+
:return: OperationResult a result code: success or reason of failure
508+
:rtype: OperationResult
497509
%End
498510

499511

‎python/core/geometry/qgsgeometryengine.sip‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ class QgsGeometryEngine
2121
#include "qgsgeometryengine.h"
2222
%End
2323
public:
24+
25+
enum EngineOperationResult
26+
{
27+
Success,
28+
NothingHappened,
29+
MethodNotImplemented,
30+
EngineError,
31+
NodedGeometryError,
32+
InvalidBaseGeometry,
33+
InvalidInput,
34+
SplitCannotSplitPoint,
35+
};
36+
2437
virtual ~QgsGeometryEngine();
2538

2639
virtual void geometryChanged() = 0;
@@ -230,12 +243,12 @@ class QgsGeometryEngine
230243
:rtype: bool
231244
%End
232245

233-
virtual int splitGeometry( const QgsLineString &splitLine,
234-
QList<QgsAbstractGeometry *> &newGeometries,
235-
bool topological,
236-
QgsPointSequence &topologyTestPoints, QString *errorMsg = 0 ) const;
246+
virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
247+
QList<QgsAbstractGeometry *> &newGeometries,
248+
bool topological,
249+
QgsPointSequence &topologyTestPoints, QString *errorMsg = 0 ) const;
237250
%Docstring
238-
:rtype: int
251+
:rtype: QgsGeometryEngine.EngineOperationResult
239252
%End
240253

241254
virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = 0 ) const = 0 /Factory/;

‎python/core/qgsvectorlayereditutils.sip‎

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,51 @@ class QgsVectorLayerEditUtils
6363
:rtype: QgsVectorLayer.EditResult
6464
%End
6565

66-
int addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 );
66+
QgsGeometry::OperationResult addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 );
6767
%Docstring
68-
:rtype: int
68+
Adds a ring to polygon/multipolygon features
69+
@param ring ring to add
70+
@param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
71+
all intersecting features are tested and the ring is added to the first valid feature.
72+
@param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
73+
@return OperationResult result code: success or reason of failure
74+
:rtype: QgsGeometry.OperationResult
6975
%End
7076

71-
int addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 ) /PyName=addCurvedRing/;
77+
QgsGeometry::OperationResult addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 ) /PyName=addCurvedRing/;
7278
%Docstring
73-
:rtype: int
79+
Adds a ring to polygon/multipolygon features
80+
@param ring ring to add
81+
@param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
82+
all intersecting features are tested and the ring is added to the first valid feature.
83+
@param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
84+
@return OperationResult result code: success or reason of failure
85+
.. note::
86+
87+
available in python bindings as addCurvedRing
88+
:rtype: QgsGeometry.OperationResult
7489
%End
7590

76-
int addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
91+
QgsGeometry::OperationResult addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
7792
%Docstring
78-
:rtype: int
93+
Adds a new part polygon to a multipart feature
94+
@returns QgsGeometry.OperationResult a result code: success or reason of failure
95+
:rtype: QgsGeometry.OperationResult
7996
%End
8097

81-
int addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
98+
QgsGeometry::OperationResult addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
8299
%Docstring
83-
:rtype: int
100+
Adds a new part polygon to a multipart feature
101+
@returns QgsGeometry.OperationResult a result code: success or reason of failure
102+
.. note::
103+
104+
available in python bindings as addPartV2
105+
:rtype: QgsGeometry.OperationResult
84106
%End
85107

86-
int addPart( QgsCurve *ring, QgsFeatureId featureId ) /PyName=addCurvedPart/;
108+
QgsGeometry::OperationResult addPart( QgsCurve *ring, QgsFeatureId featureId ) /PyName=addCurvedPart/;
87109
%Docstring
88-
:rtype: int
110+
:rtype: QgsGeometry.OperationResult
89111
%End
90112

91113
int translateFeature( QgsFeatureId featureId, double dx, double dy );
@@ -98,14 +120,14 @@ class QgsVectorLayerEditUtils
98120
:rtype: int
99121
%End
100122

101-
int splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
123+
QgsGeometry::OperationResult splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
102124
%Docstring
103-
:rtype: int
125+
:rtype: QgsGeometry.OperationResult
104126
%End
105127

106-
int splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
128+
QgsGeometry::OperationResult splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
107129
%Docstring
108-
:rtype: int
130+
:rtype: QgsGeometry.OperationResult
109131
%End
110132

111133
int addTopologicalPoints( const QgsGeometry &geom );
@@ -130,15 +152,6 @@ class QgsVectorLayerEditUtils
130152
:rtype: int
131153
%End
132154

133-
protected:
134-
135-
int boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
136-
%Docstring
137-
Little helper function that gives bounding box from a list of points.
138-
:return: 0 in case of success *
139-
:rtype: int
140-
%End
141-
142155
};
143156

144157
/************************************************************************

‎src/core/geometry/qgsgeometry.cpp‎

Lines changed: 86 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -626,35 +626,35 @@ double QgsGeometry::closestSegmentWithContext(
626626
return sqrDist;
627627
}
628628

629-
int QgsGeometry::addRing( const QList<QgsPointXY> &ring )
629+
QgsGeometry::OperationResult QgsGeometry::addRing( const QList<QgsPointXY> &ring )
630630
{
631631
detach( true );
632632

633633
QgsLineString *ringLine = new QgsLineString( ring );
634634
return addRing( ringLine );
635635
}
636636

637-
int QgsGeometry::addRing( QgsCurve *ring )
637+
QgsGeometry::OperationResult QgsGeometry::addRing( QgsCurve *ring )
638638
{
639639
if ( !d->geometry )
640640
{
641641
delete ring;
642-
return 1;
642+
return InvalidInput;
643643
}
644644

645645
detach( true );
646646

647647
return QgsGeometryEditUtils::addRing( d->geometry, ring );
648648
}
649649

650-
int QgsGeometry::addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType )
650+
QgsGeometry::OperationResult QgsGeometry::addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType )
651651
{
652652
QgsPointSequence l;
653653
convertPointList( points, l );
654654
return addPart( l, geomType );
655655
}
656656

657-
int QgsGeometry::addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType )
657+
QgsGeometry::OperationResult QgsGeometry::addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType )
658658
{
659659
QgsAbstractGeometry *partGeom = nullptr;
660660
if ( points.size() == 1 )
@@ -670,7 +670,7 @@ int QgsGeometry::addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryT
670670
return addPart( partGeom, geomType );
671671
}
672672

673-
int QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType geomType )
673+
QgsGeometry::OperationResult QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType geomType )
674674
{
675675
if ( !d->geometry )
676676
{
@@ -687,7 +687,7 @@ int QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType g
687687
d->geometry = new QgsMultiPolygonV2();
688688
break;
689689
default:
690-
return 1;
690+
return QgsGeometry::AddPartNotMultiGeometry;
691691
}
692692
}
693693
else
@@ -699,11 +699,15 @@ int QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType g
699699
return QgsGeometryEditUtils::addPart( d->geometry, part );
700700
}
701701

702-
int QgsGeometry::addPart( const QgsGeometry &newPart )
702+
QgsGeometry::OperationResult QgsGeometry::addPart( const QgsGeometry &newPart )
703703
{
704-
if ( !d->geometry || !newPart.d || !newPart.d->geometry )
704+
if ( !d->geometry )
705705
{
706-
return 1;
706+
return QgsGeometry::InvalidBaseGeometry;
707+
}
708+
if ( !newPart.d || !newPart.d->geometry )
709+
{
710+
return QgsGeometry::AddPartNotMultiGeometry;
707711
}
708712

709713
return addPart( newPart.d->geometry->clone() );
@@ -744,11 +748,15 @@ QgsGeometry QgsGeometry::removeInteriorRings( double minimumRingArea ) const
744748
}
745749
}
746750

747-
int QgsGeometry::addPart( GEOSGeometry *newPart )
751+
QgsGeometry::OperationResult QgsGeometry::addPart( GEOSGeometry *newPart )
748752
{
749-
if ( !d->geometry || !newPart )
753+
if ( !d->geometry )
750754
{
751-
return 1;
755+
return QgsGeometry::InvalidBaseGeometry;
756+
}
757+
if ( !newPart )
758+
{
759+
return QgsGeometry::AddPartNotMultiGeometry;
752760
}
753761

754762
detach( true );
@@ -757,24 +765,24 @@ int QgsGeometry::addPart( GEOSGeometry *newPart )
757765
return QgsGeometryEditUtils::addPart( d->geometry, geom );
758766
}
759767

760-
int QgsGeometry::translate( double dx, double dy )
768+
QgsGeometry::OperationResult QgsGeometry::translate( double dx, double dy )
761769
{
762770
if ( !d->geometry )
763771
{
764-
return 1;
772+
return QgsGeometry::InvalidBaseGeometry;
765773
}
766774

767775
detach( true );
768776

769777
d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
770-
return 0;
778+
return QgsGeometry::Success;
771779
}
772780

773-
int QgsGeometry::rotate( double rotation, const QgsPointXY &center )
781+
QgsGeometry::OperationResult QgsGeometry::rotate( double rotation, const QgsPointXY &center )
774782
{
775783
if ( !d->geometry )
776784
{
777-
return 1;
785+
return QgsGeometry::InvalidBaseGeometry;
778786
}
779787

780788
detach( true );
@@ -783,24 +791,24 @@ int QgsGeometry::rotate( double rotation, const QgsPointXY &center )
783791
t.rotate( -rotation );
784792
t.translate( -center.x(), -center.y() );
785793
d->geometry->transform( t );
786-
return 0;
794+
return QgsGeometry::Success;
787795
}
788796

789-
int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints )
797+
QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints )
790798
{
791799
if ( !d->geometry )
792800
{
793-
return 0;
801+
return InvalidBaseGeometry;
794802
}
795803

796804
QList<QgsAbstractGeometry *> newGeoms;
797805
QgsLineString splitLineString( splitLine );
798806
QgsPointSequence tp;
799807

800808
QgsGeos geos( d->geometry );
801-
int result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
809+
QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
802810

803-
if ( result == 0 )
811+
if ( result == QgsGeometryEngine::Success )
804812
{
805813
detach( false );
806814
d->geometry = newGeoms.at( 0 );
@@ -813,27 +821,69 @@ int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeo
813821
}
814822

815823
convertPointList( tp, topologyTestPoints );
816-
return result;
824+
825+
switch ( result )
826+
{
827+
case QgsGeometryEngine::Success:
828+
return QgsGeometry::Success;
829+
case QgsGeometryEngine::MethodNotImplemented:
830+
case QgsGeometryEngine::EngineError:
831+
case QgsGeometryEngine::NodedGeometryError:
832+
return QgsGeometry::GeometryEngineError;
833+
case QgsGeometryEngine::InvalidBaseGeometry:
834+
return QgsGeometry::InvalidBaseGeometry;
835+
case QgsGeometryEngine::InvalidInput:
836+
return QgsGeometry::InvalidInput;
837+
case QgsGeometryEngine::SplitCannotSplitPoint:
838+
return QgsGeometry::SplitCannotSplitPoint;
839+
case QgsGeometryEngine::NothingHappened:
840+
return QgsGeometry::NothingHappened;
841+
//default: do not implement default to handle properly all cases
842+
}
843+
844+
// this should never be reached
845+
Q_ASSERT( false );
846+
return QgsGeometry::NothingHappened;
817847
}
818848

819-
int QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
849+
QgsGeometry::OperationResult QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
820850
{
821851
if ( !d->geometry )
822852
{
823-
return 0;
853+
return InvalidBaseGeometry;
824854
}
825855

826856
QgsGeos geos( d->geometry );
827-
int errorCode = 0;
857+
QgsGeometryEngine::EngineOperationResult errorCode = QgsGeometryEngine::Success;
828858
QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
829-
if ( errorCode == 0 && geom )
859+
if ( errorCode == QgsGeometryEngine::Success && geom )
830860
{
831861
detach( false );
832862
delete d->geometry;
833863
d->geometry = geom;
834-
return 0;
864+
return Success;
865+
}
866+
867+
switch ( errorCode )
868+
{
869+
case QgsGeometryEngine::Success:
870+
return Success;
871+
case QgsGeometryEngine::MethodNotImplemented:
872+
case QgsGeometryEngine::EngineError:
873+
case QgsGeometryEngine::NodedGeometryError:
874+
return GeometryEngineError;
875+
case QgsGeometryEngine::InvalidBaseGeometry:
876+
return InvalidBaseGeometry;
877+
case QgsGeometryEngine::InvalidInput:
878+
return InvalidInput;
879+
case QgsGeometryEngine::SplitCannotSplitPoint: // should not happen
880+
return GeometryEngineError;
881+
case QgsGeometryEngine::NothingHappened:
882+
return NothingHappened;
835883
}
836-
return errorCode;
884+
885+
// should not be reached
886+
return GeometryEngineError;
837887
}
838888

839889
int QgsGeometry::makeDifferenceInPlace( const QgsGeometry &other )
@@ -2091,28 +2141,28 @@ bool QgsGeometry::requiresConversionToStraightSegments() const
20912141
return d->geometry->hasCurvedSegments();
20922142
}
20932143

2094-
int QgsGeometry::transform( const QgsCoordinateTransform &ct )
2144+
QgsGeometry::OperationResult QgsGeometry::transform( const QgsCoordinateTransform &ct )
20952145
{
20962146
if ( !d->geometry )
20972147
{
2098-
return 1;
2148+
return QgsGeometry::InvalidBaseGeometry;
20992149
}
21002150

21012151
detach();
21022152
d->geometry->transform( ct );
2103-
return 0;
2153+
return QgsGeometry::Success;
21042154
}
21052155

2106-
int QgsGeometry::transform( const QTransform &ct )
2156+
QgsGeometry::OperationResult QgsGeometry::transform( const QTransform &ct )
21072157
{
21082158
if ( !d->geometry )
21092159
{
2110-
return 1;
2160+
return QgsGeometry::InvalidBaseGeometry;
21112161
}
21122162

21132163
detach();
21142164
d->geometry->transform( ct );
2115-
return 0;
2165+
return QgsGeometry::Success;
21162166
}
21172167

21182168
void QgsGeometry::mapToPixel( const QgsMapToPixel &mtp )

‎src/core/geometry/qgsgeometry.h‎

Lines changed: 104 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ struct QgsGeometryPrivate;
9696
class CORE_EXPORT QgsGeometry
9797
{
9898
public:
99+
100+
/**
101+
* Success or failure of a geometry operation.
102+
* This gived details about cause of failure.
103+
*/
104+
enum OperationResult
105+
{
106+
Success = 0, //!< Operation succeeded
107+
NothingHappened, //!< Nothing happened, without any error
108+
InvalidBaseGeometry, //!< The base geometry on which the operation is done is invalid or empty
109+
InvalidInput, //!< The input geometry (ring, part, split line, etc.) has not the correct geometry type
110+
GeometryEngineError, //!< Geometry engine misses a method implemented or an error occured in the geometry engine
111+
/* Add part issues */
112+
AddPartSelectedGeometryNotFound, //!< The selected geometry cannot be found
113+
AddPartNotMultiGeometry, //!< The source geometry is not multi
114+
/* Add ring issues*/
115+
AddRingNotClosed, //!< The imput ring is not closed
116+
AddRingNotValid, //!< The input ring is not valid
117+
AddRingCrossesExistingRings, //!< The input ring crosses existing rings (it is not disjoint)
118+
AddRingNotInExistingFeature, //!< The input ring doesn't have any existing ring to fit into
119+
/* Split features */
120+
SplitCannotSplitPoint, //!< Cannot split points
121+
};
122+
99123
//! Constructor
100124
QgsGeometry();
101125

@@ -390,62 +414,58 @@ class CORE_EXPORT QgsGeometry
390414
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &afterVertex SIP_OUT ) const;
391415
#endif
392416

393-
/** Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
394-
\returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
395-
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
396-
int addRing( const QList<QgsPointXY> &ring );
397-
// TODO QGIS 3.0 returns an enum instead of a magic constant
417+
/**
418+
* Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
419+
* \param ring The ring to be added
420+
* \returns OperationResult a result code: success or reason of failure
421+
*/
422+
OperationResult addRing( const QList<QgsPointXY> &ring );
398423

399-
/** Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
400-
\returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
401-
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
402-
int addRing( QgsCurve *ring SIP_TRANSFER );
403-
// TODO QGIS 3.0 returns an enum instead of a magic constant
424+
/**
425+
* Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
426+
* \param ring The ring to be added
427+
* \returns OperationResult a result code: success or reason of failure
428+
*/
429+
OperationResult addRing( QgsCurve *ring SIP_TRANSFER );
404430

405-
/** Adds a new part to a the geometry.
431+
/**
432+
* Adds a new part to a the geometry.
406433
* \param points points describing part to add
407434
* \param geomType default geometry type to create if no existing geometry
408-
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
409-
* not disjoint with existing polygons of the feature
435+
* \returns OperationResult a result code: success or reason of failure
410436
*/
411-
int addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPoints );
412-
// TODO QGIS 3.0 returns an enum instead of a magic constant
437+
OperationResult addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPoints );
413438

414-
/** Adds a new part to a the geometry.
439+
/**
440+
* Adds a new part to a the geometry.
415441
* \param points points describing part to add
416442
* \param geomType default geometry type to create if no existing geometry
417-
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
418-
* not disjoint with existing polygons of the feature
443+
* \returns OperationResult a result code: success or reason of failure
419444
*/
420-
int addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsV2 );
421-
// TODO QGIS 3.0 returns an enum instead of a magic constant
445+
OperationResult addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsV2 );
422446

423-
/** Adds a new part to this geometry.
447+
/**
448+
* Adds a new part to this geometry.
424449
* \param part part to add (ownership is transferred)
425450
* \param geomType default geometry type to create if no existing geometry
426-
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
427-
* not disjoint with existing polygons of the feature
451+
* \returns OperationResult a result code: success or reason of failure
428452
*/
429-
int addPart( QgsAbstractGeometry *part SIP_TRANSFER, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
430-
// TODO QGIS 3.0 returns an enum instead of a magic constant
453+
OperationResult addPart( QgsAbstractGeometry *part SIP_TRANSFER, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
431454

432-
/** Adds a new island polygon to a multipolygon feature
455+
/**
456+
* Adds a new island polygon to a multipolygon feature
433457
* \param newPart part to add. Ownership is NOT transferred.
434-
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
435-
* not disjoint with existing polygons of the feature
436-
* \note not available in Python bindings
458+
* \returns OperationResult a result code: success or reason of failure
459+
* \note not available in python bindings
437460
*/
438-
int addPart( GEOSGeometry *newPart ) SIP_SKIP;
439-
// TODO QGIS 3.0 returns an enum instead of a magic constant
461+
OperationResult addPart( GEOSGeometry *newPart ) SIP_SKIP;
440462

441-
/** Adds a new island polygon to a multipolygon feature
442-
\returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
443-
not disjoint with existing polygons of the feature
444-
\note available in Python bindings as addPartGeometry
445-
\since QGIS 2.2
463+
/**
464+
* Adds a new island polygon to a multipolygon feature
465+
* \returns OperationResult a result code: success or reason of failure
466+
* \note available in python bindings as addPartGeometry
446467
*/
447-
int addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
448-
// TODO QGIS 3.0 returns an enum instead of a magic constant
468+
OperationResult addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
449469

450470
/**
451471
* Removes the interior rings from a (multi)polygon geometry. If the minimumAllowedArea
@@ -455,52 +475,57 @@ class CORE_EXPORT QgsGeometry
455475
*/
456476
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
457477

458-
/** Translate this geometry by dx, dy
459-
\returns 0 in case of success*/
460-
int translate( double dx, double dy );
461-
462-
/** Transform this geometry as described by CoordinateTransform ct
463-
\returns 0 in case of success*/
464-
int transform( const QgsCoordinateTransform &ct );
465-
466-
/** Transform this geometry as described by QTransform ct
467-
\since QGIS 2.8
468-
\returns 0 in case of success*/
469-
int transform( const QTransform &ct );
470-
471-
/** Rotate this geometry around the Z axis
472-
\since QGIS 2.8
473-
\param rotation clockwise rotation in degrees
474-
\param center rotation center
475-
\returns 0 in case of success*/
476-
int rotate( double rotation, const QgsPointXY &center );
477-
478-
/** Splits this geometry according to a given line.
479-
\param splitLine the line that splits the geometry
480-
\param[out] newGeometries list of new geometries that have been created with the split
481-
\param topological true if topological editing is enabled
482-
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
483-
\returns 0 in case of success, 1 if geometry has not been split, error else*/
484-
// TODO QGIS 3.0 returns an enum instead of a magic constant
485-
int splitGeometry( const QList<QgsPointXY> &splitLine,
486-
QList<QgsGeometry> &newGeometries SIP_OUT,
487-
bool topological,
488-
QList<QgsPointXY> &topologyTestPoints SIP_OUT );
489-
490-
/** Replaces a part of this geometry with another line
491-
* \returns 0 in case of success
492-
* \since QGIS 1.3
493-
*/
494-
int reshapeGeometry( const QgsLineString &reshapeLineString );
495-
496-
/** Changes this geometry such that it does not intersect the other geometry
478+
/**
479+
* Translate this geometry by dx, dy
480+
* \returns OperationResult a result code: success or reason of failure
481+
*/
482+
OperationResult translate( double dx, double dy );
483+
484+
/**
485+
* Transform this geometry as described by CoordinateTransform ct
486+
* \returns OperationResult a result code: success or reason of failure
487+
*/
488+
OperationResult transform( const QgsCoordinateTransform &ct );
489+
490+
/**
491+
* Transform this geometry as described by QTransform ct
492+
* \returns OperationResult a result code: success or reason of failure
493+
*/
494+
OperationResult transform( const QTransform &ct );
495+
496+
/**
497+
* Rotate this geometry around the Z axis
498+
* \param rotation clockwise rotation in degrees
499+
* \param center rotation center
500+
* \returns OperationResult a result code: success or reason of failure
501+
*/
502+
OperationResult rotate( double rotation, const QgsPointXY &center );
503+
504+
/**
505+
* Splits this geometry according to a given line.
506+
* \param splitLine the line that splits the geometry
507+
* \param[out] newGeometries list of new geometries that have been created with the split
508+
* \param topological true if topological editing is enabled
509+
* \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
510+
* \returns OperationResult a result code: success or reason of failure
511+
*/
512+
OperationResult splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints );
513+
514+
/**
515+
* Replaces a part of this geometry with another line
516+
* \returns OperationResult a result code: success or reason of failure
517+
*/
518+
OperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
519+
520+
/**
521+
* Changes this geometry such that it does not intersect the other geometry
497522
* \param other geometry that should not be intersect
498-
* \returns 0 in case of success
499523
* \note Not available in Python
500524
*/
501525
int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
502526

503-
/** Returns the geometry formed by modifying this geometry such that it does not
527+
/**
528+
* Returns the geometry formed by modifying this geometry such that it does not
504529
* intersect the other geometry.
505530
* \param other geometry that should not be intersect
506531
* \returns difference geometry, or empty geometry if difference could not be calculated

‎src/core/geometry/qgsgeometryeditutils.cpp‎

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ email : marco.hugentobler at sourcepole dot com
2626
#include "qgsvectorlayer.h"
2727
#include <limits>
2828

29-
int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
29+
QgsGeometry::OperationResult QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *r )
3030
{
31+
std::unique_ptr<QgsCurve> ring( r );
3132
if ( !ring )
3233
{
33-
return 1;
34+
return QgsGeometry::InvalidInput;
3435
}
3536

3637
QList< QgsCurvePolygon * > polygonList;
@@ -50,23 +51,20 @@ int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
5051
}
5152
else
5253
{
53-
delete ring;
54-
return 1; //not polygon / multipolygon;
54+
return QgsGeometry::InvalidInput; //not polygon / multipolygon;
5555
}
5656

5757
//ring must be closed
5858
if ( !ring->isClosed() )
5959
{
60-
delete ring;
61-
return 2;
60+
return QgsGeometry::AddRingNotClosed;
6261
}
6362
else if ( !ring->isRing() )
6463
{
65-
delete ring;
66-
return 3;
64+
return QgsGeometry::AddRingNotValid;
6765
}
6866

69-
std::unique_ptr<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring ) );
67+
std::unique_ptr<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring.get() ) );
7068
ringGeom->prepareGeometry();
7169

7270
//for each polygon, test if inside outer ring and no intersection with other interior ring
@@ -81,8 +79,7 @@ int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
8179
{
8280
if ( !ringGeom->disjoint( ( *polyIter )->interiorRing( i ) ) )
8381
{
84-
delete ring;
85-
return 4;
82+
return QgsGeometry::AddRingCrossesExistingRings;
8683
}
8784
}
8885

@@ -92,59 +89,62 @@ int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
9289
if ( QgsWkbTypes::hasM( geom->wkbType() ) )
9390
ring->addMValue( 0 );
9491

95-
( *polyIter )->addInteriorRing( ring );
96-
return 0; //success
92+
( *polyIter )->addInteriorRing( ring.release() );
93+
return QgsGeometry::Success; //success
9794
}
9895
}
99-
delete ring;
100-
return 5; //not contained in any outer ring
96+
return QgsGeometry::AddRingNotInExistingFeature; //not contained in any outer ring
10197
}
10298

103-
int QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, QgsAbstractGeometry *part )
99+
QgsGeometry::OperationResult QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, QgsAbstractGeometry *p )
104100
{
101+
std::unique_ptr<QgsAbstractGeometry> part( p );
105102
if ( !geom )
106103
{
107-
return 1;
104+
return QgsGeometry::InvalidBaseGeometry;
108105
}
109106

110107
if ( !part )
111108
{
112-
return 2;
109+
return QgsGeometry::InvalidInput;
113110
}
114111

115112
//multitype?
116113
QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom );
117114
if ( !geomCollection )
118115
{
119-
return 1;
116+
return QgsGeometry::AddPartNotMultiGeometry;
120117
}
121118

122119
bool added = false;
123120
if ( QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiSurface
124121
|| QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiPolygon )
125122
{
126-
QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( part );
123+
std::unique_ptr<QgsCurve> curve( qgsgeometry_cast<QgsCurve *>( part.get() ) );
124+
if ( curve )
125+
part.release();
126+
127127
if ( curve && curve->isClosed() && curve->numPoints() >= 4 )
128128
{
129-
QgsCurvePolygon *poly = nullptr;
129+
std::unique_ptr<QgsCurvePolygon> poly;
130130
if ( QgsWkbTypes::flatType( curve->wkbType() ) == QgsWkbTypes::LineString )
131131
{
132-
poly = new QgsPolygonV2();
132+
poly.reset( new QgsPolygonV2() );
133133
}
134134
else
135135
{
136-
poly = new QgsCurvePolygon();
136+
poly.reset( new QgsCurvePolygon() );
137137
}
138-
poly->setExteriorRing( curve );
139-
added = geomCollection->addGeometry( poly );
138+
poly->setExteriorRing( curve.release() );
139+
added = geomCollection->addGeometry( poly.release() );
140140
}
141141
else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::Polygon )
142142
{
143-
added = geomCollection->addGeometry( part );
143+
added = geomCollection->addGeometry( part.release() );
144144
}
145145
else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::MultiPolygon )
146146
{
147-
QgsGeometryCollection *parts = static_cast<QgsGeometryCollection *>( part );
147+
std::unique_ptr<QgsGeometryCollection> parts( static_cast<QgsGeometryCollection *>( part.release() ) );
148148

149149
int i;
150150
int n = geomCollection->numGeometries();
@@ -156,23 +156,19 @@ int QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, QgsAbstractGeometr
156156
{
157157
while ( geomCollection->numGeometries() > n )
158158
geomCollection->removeGeometry( n );
159-
delete part;
160-
return 2;
159+
return QgsGeometry::InvalidInput;
161160
}
162-
163-
delete part;
164161
}
165162
else
166163
{
167-
delete part;
168-
return 2;
164+
return QgsGeometry::InvalidInput;
169165
}
170166
}
171167
else
172168
{
173-
added = geomCollection->addGeometry( part );
169+
added = geomCollection->addGeometry( part.release() );
174170
}
175-
return added ? 0 : 2;
171+
return added ? QgsGeometry::Success : QgsGeometry::InvalidInput;
176172
}
177173

178174
bool QgsGeometryEditUtils::deleteRing( QgsAbstractGeometry *geom, int ringNum, int partNum )

‎src/core/geometry/qgsgeometryeditutils.h‎

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class QgsVectorLayer;
2424
#define SIP_NO_FILE
2525

2626
#include "qgsfeature.h"
27+
#include "qgsgeometry.h"
2728
#include <QMap>
2829

2930
/** \ingroup core
@@ -36,19 +37,24 @@ class QgsGeometryEditUtils
3637
{
3738
public:
3839

39-
/** Adds interior ring (taking ownership).
40-
\returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
41-
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
42-
// TODO QGIS 3.0 returns an enum instead of a magic constant
43-
static int addRing( QgsAbstractGeometry *geom, QgsCurve *ring );
40+
/**
41+
* Add an interior \a ring to a \a geometry.
42+
* Ownership of the \a ring is transferred.
43+
* \returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
44+
* 3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring
45+
*/
46+
static QgsGeometry::OperationResult addRing( QgsAbstractGeometry *geometry, QgsCurve *ring SIP_TRANSFER );
4447

45-
/** Adds part to multi type geometry (taking ownership)
46-
\returns 0 in case of success, 1 if not a multigeometry, 2 if part is not a valid geometry, 3 if new polygon ring
47-
not disjoint with existing polygons of the feature*/
48-
// TODO QGIS 3.0 returns an enum instead of a magic constant
49-
static int addPart( QgsAbstractGeometry *geom, QgsAbstractGeometry *part );
48+
/**
49+
* Add a \a part to multi type \a geometry.
50+
* Ownership of the \a part is transferred.
51+
* \returns 0 in case of success, 1 if not a multigeometry, 2 if part is not a valid geometry, 3 if new polygon ring
52+
* not disjoint with existing polygons of the feature
53+
*/
54+
static QgsGeometry::OperationResult addPart( QgsAbstractGeometry *geometry, QgsAbstractGeometry *part SIP_TRANSFER );
5055

51-
/** Deletes a ring from a geometry.
56+
/**
57+
* Deletes a ring from a geometry.
5258
* \returns true if delete was successful
5359
*/
5460
static bool deleteRing( QgsAbstractGeometry *geom, int ringNum, int partNum = 0 );

‎src/core/geometry/qgsgeometryengine.h‎

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ email : marco.hugentobler at sourcepole dot com
1818

1919
#include "qgis_core.h"
2020
#include "qgslinestring.h"
21+
#include "qgsgeometry.h"
2122

2223
#include <QList>
2324

@@ -31,6 +32,24 @@ class QgsAbstractGeometry;
3132
class CORE_EXPORT QgsGeometryEngine
3233
{
3334
public:
35+
36+
/**
37+
* Success or failure of a geometry operation.
38+
* This gived details about cause of failure.
39+
*/
40+
enum EngineOperationResult
41+
{
42+
Success = 0, //!< Operation succeeded
43+
NothingHappened, //!< Nothing happened, without any error
44+
MethodNotImplemented, //!< Method not implemented in geometry engine
45+
EngineError, //!< Error occured in the geometry engine
46+
NodedGeometryError, //!< Error occured while creating a noded geometry
47+
InvalidBaseGeometry, //!< The geometry on which the operation occurs is not valid
48+
InvalidInput, //!< The input is not valid
49+
/* split */
50+
SplitCannotSplitPoint, //!< Points cannot be split
51+
};
52+
3453
virtual ~QgsGeometryEngine() = default;
3554

3655
virtual void geometryChanged() = 0;
@@ -190,17 +209,17 @@ class CORE_EXPORT QgsGeometryEngine
190209
*/
191210
virtual bool isSimple( QString *errorMsg = nullptr ) const = 0;
192211

193-
virtual int splitGeometry( const QgsLineString &splitLine,
194-
QList<QgsAbstractGeometry *> &newGeometries,
195-
bool topological,
196-
QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr ) const
212+
virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
213+
QList<QgsAbstractGeometry *> &newGeometries,
214+
bool topological,
215+
QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr ) const
197216
{
198217
Q_UNUSED( splitLine );
199218
Q_UNUSED( newGeometries );
200219
Q_UNUSED( topological );
201220
Q_UNUSED( topologyTestPoints );
202221
Q_UNUSED( errorMsg );
203-
return 2;
222+
return MethodNotImplemented;
204223
}
205224

206225
virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;

‎src/core/geometry/qgsgeos.cpp‎

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ email : marco.hugentobler at sourcepole dot com
2525
#include "qgsmultipolygon.h"
2626
#include "qgslogger.h"
2727
#include "qgspolygon.h"
28-
#include "qgsgeometry.h"
2928
#include <limits>
3029
#include <cstdio>
3130
#include <QtCore/qmath.h>
@@ -519,32 +518,32 @@ double QgsGeos::length( QString *errorMsg ) const
519518
return length;
520519
}
521520

522-
int QgsGeos::splitGeometry( const QgsLineString &splitLine,
523-
QList<QgsAbstractGeometry *> &newGeometries,
524-
bool topological,
525-
QgsPointSequence &topologyTestPoints,
526-
QString *errorMsg ) const
521+
QgsGeometryEngine::EngineOperationResult QgsGeos::splitGeometry( const QgsLineString &splitLine,
522+
QList<QgsAbstractGeometry *> &newGeometries,
523+
bool topological,
524+
QgsPointSequence &topologyTestPoints,
525+
QString *errorMsg ) const
527526
{
528527

529-
int returnCode = 0;
530-
if ( !mGeometry || !mGeos )
528+
EngineOperationResult returnCode = Success;
529+
if ( !mGeos || !mGeometry )
531530
{
532-
return 1;
531+
return InvalidBaseGeometry;
533532
}
534533

535534
//return if this type is point/multipoint
536535
if ( mGeometry->dimension() == 0 )
537536
{
538-
return 1; //cannot split points
537+
return SplitCannotSplitPoint; //cannot split points
539538
}
540539

541540
if ( !GEOSisValid_r( geosinit.ctxt, mGeos ) )
542-
return 7;
541+
return InvalidBaseGeometry;
543542

544543
//make sure splitLine is valid
545544
if ( ( mGeometry->dimension() == 1 && splitLine.numPoints() < 1 ) ||
546545
( mGeometry->dimension() == 2 && splitLine.numPoints() < 2 ) )
547-
return 1;
546+
return InvalidInput;
548547

549548
newGeometries.clear();
550549
GEOSGeometry *splitLineGeos = nullptr;
@@ -561,20 +560,22 @@ int QgsGeos::splitGeometry( const QgsLineString &splitLine,
561560
}
562561
else
563562
{
564-
return 1;
563+
return InvalidInput;
565564
}
566565

567566
if ( !GEOSisValid_r( geosinit.ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.ctxt, splitLineGeos ) )
568567
{
569568
GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
570-
return 1;
569+
return InvalidInput;
571570
}
572571

573572
if ( topological )
574573
{
575574
//find out candidate points for topological corrections
576-
if ( topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) != 0 )
577-
return 1;
575+
if ( !topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) )
576+
{
577+
return InvalidInput; // TODO: is it really an invalid input?
578+
}
578579
}
579580

580581
//call split function depending on geometry type
@@ -590,33 +591,33 @@ int QgsGeos::splitGeometry( const QgsLineString &splitLine,
590591
}
591592
else
592593
{
593-
return 1;
594+
return InvalidInput;
594595
}
595596
}
596-
CATCH_GEOS_WITH_ERRMSG( 2 )
597+
CATCH_GEOS_WITH_ERRMSG( EngineError )
597598

598599
return returnCode;
599600
}
600601

601602

602603

603-
int QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg ) const
604+
bool QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg ) const
604605
{
605606
//Find out the intersection points between splitLineGeos and this geometry.
606607
//These points need to be tested for topological correctness by the calling function
607608
//if topological editing is enabled
608609

609610
if ( !mGeos )
610611
{
611-
return 1;
612+
return false;
612613
}
613614

614615
try
615616
{
616617
testPoints.clear();
617618
GEOSGeometry *intersectionGeom = GEOSIntersection_r( geosinit.ctxt, mGeos, splitLine );
618619
if ( !intersectionGeom )
619-
return 1;
620+
return false;
620621

621622
bool simple = false;
622623
int nIntersectGeoms = 1;
@@ -656,7 +657,7 @@ int QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPoint
656657
}
657658
CATCH_GEOS_WITH_ERRMSG( 1 )
658659

659-
return 0;
660+
return true;
660661
}
661662

662663
GEOSGeometry *QgsGeos::linePointDifference( GEOSGeometry *GEOSsplitPoint ) const
@@ -725,22 +726,22 @@ GEOSGeometry *QgsGeos::linePointDifference( GEOSGeometry *GEOSsplitPoint ) const
725726
return asGeos( &lines, mPrecision );
726727
}
727728

728-
int QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
729+
QgsGeometryEngine::EngineOperationResult QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
729730
{
730731
if ( !splitLine )
731-
return 2;
732+
return InvalidInput;
732733

733734
if ( !mGeos )
734-
return 5;
735+
return InvalidBaseGeometry;
735736

736737
//first test if linestring intersects geometry. If not, return straight away
737738
if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
738-
return 1;
739+
return NothingHappened;
739740

740741
//check that split line has no linear intersection
741742
int linearIntersect = GEOSRelatePattern_r( geosinit.ctxt, mGeos, splitLine, "1********" );
742743
if ( linearIntersect > 0 )
743-
return 3;
744+
return InvalidInput;
744745

745746
int splitGeomType = GEOSGeomTypeId_r( geosinit.ctxt, splitLine );
746747

@@ -778,25 +779,25 @@ int QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeom
778779
}
779780

780781
GEOSGeom_destroy_r( geosinit.ctxt, splitGeom );
781-
return 0;
782+
return Success;
782783
}
783784

784-
int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
785+
QgsGeometryEngine::EngineOperationResult QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
785786
{
786787
if ( !splitLine )
787-
return 2;
788+
return InvalidInput;
788789

789790
if ( !mGeos )
790-
return 5;
791+
return InvalidBaseGeometry;
791792

792793
//first test if linestring intersects geometry. If not, return straight away
793794
if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
794-
return 1;
795+
return NothingHappened;
795796

796797
//first union all the polygon rings together (to get them noded, see JTS developer guide)
797798
GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
798799
if ( !nodedGeometry )
799-
return 2; //an error occurred during noding
800+
return NodedGeometryError; //an error occurred during noding
800801

801802
GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.ctxt, &nodedGeometry, 1 );
802803
if ( !polygons || numberOfGeometries( polygons ) == 0 )
@@ -806,7 +807,7 @@ int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeo
806807

807808
GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
808809

809-
return 4;
810+
return InvalidBaseGeometry;
810811
}
811812

812813
GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
@@ -859,7 +860,7 @@ int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeo
859860
{
860861
GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
861862
}
862-
return 1;
863+
return NothingHappened;
863864
}
864865

865866
int i;
@@ -871,13 +872,13 @@ int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeo
871872
for ( i = 0; i < testedGeometries.size(); ++i )
872873
GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
873874

874-
return 3;
875+
return InvalidBaseGeometry;
875876
}
876877

877878
for ( i = 0; i < testedGeometries.size(); ++i )
878879
newGeometries << fromGeos( testedGeometries[i] );
879880

880-
return 0;
881+
return Success;
881882
}
882883

883884
GEOSGeometry *QgsGeos::nodeGeometries( const GEOSGeometry *splitLine, const GEOSGeometry *geom )
@@ -1892,11 +1893,17 @@ QgsAbstractGeometry *QgsGeos::singleSidedBuffer( double distance, int segments,
18921893
return fromGeos( geos.get() );
18931894
}
18941895

1895-
QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithLine, int *errorCode, QString *errorMsg ) const
1896+
QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithLine, EngineOperationResult *errorCode, QString *errorMsg ) const
18961897
{
1897-
if ( !mGeos || reshapeWithLine.numPoints() < 2 || mGeometry->dimension() == 0 )
1898+
if ( !mGeos || mGeometry->dimension() == 0 )
1899+
{
1900+
if ( errorCode ) { *errorCode = InvalidBaseGeometry; }
1901+
return nullptr;
1902+
}
1903+
1904+
if ( reshapeWithLine.numPoints() < 2 )
18981905
{
1899-
if ( errorCode ) { *errorCode = 1; }
1906+
if ( errorCode ) { *errorCode = InvalidInput; }
19001907
return nullptr;
19011908
}
19021909

@@ -1906,7 +1913,7 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
19061913
int numGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, mGeos );
19071914
if ( numGeoms == -1 )
19081915
{
1909-
if ( errorCode ) { *errorCode = 1; }
1916+
if ( errorCode ) { *errorCode = InvalidBaseGeometry; }
19101917
GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
19111918
return nullptr;
19121919
}
@@ -1930,7 +1937,8 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
19301937
reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos, mPrecision );
19311938
}
19321939

1933-
if ( errorCode ) { *errorCode = 0; }
1940+
if ( errorCode )
1941+
*errorCode = Success;
19341942
QgsAbstractGeometry *reshapeResult = fromGeos( reshapedGeometry );
19351943
GEOSGeom_destroy_r( geosinit.ctxt, reshapedGeometry );
19361944
GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
@@ -1978,21 +1986,22 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
19781986
delete[] newGeoms;
19791987
if ( !newMultiGeom )
19801988
{
1981-
if ( errorCode ) { *errorCode = 3; }
1989+
if ( errorCode ) { *errorCode = EngineError; }
19821990
return nullptr;
19831991
}
19841992

19851993
if ( reshapeTookPlace )
19861994
{
1987-
if ( errorCode ) { *errorCode = 0; }
1995+
if ( errorCode )
1996+
*errorCode = Success;
19881997
QgsAbstractGeometry *reshapedMultiGeom = fromGeos( newMultiGeom );
19891998
GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
19901999
return reshapedMultiGeom;
19912000
}
19922001
else
19932002
{
19942003
GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
1995-
if ( errorCode ) { *errorCode = 1; }
2004+
if ( errorCode ) { *errorCode = NothingHappened; }
19962005
return nullptr;
19972006
}
19982007
}

‎src/core/geometry/qgsgeos.h‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ email : marco.hugentobler at sourcepole dot com
2020

2121
#include "qgis_core.h"
2222
#include "qgsgeometryengine.h"
23+
#include "qgsgeometry.h"
2324
#include <geos_c.h>
2425

2526
class QgsLineString;
@@ -106,11 +107,11 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
106107
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
107108
\param[out] errorMsg error messages emitted, if any
108109
\returns 0 in case of success, 1 if geometry has not been split, error else*/
109-
int splitGeometry( const QgsLineString &splitLine,
110-
QList<QgsAbstractGeometry *> &newGeometries,
111-
bool topological,
112-
QgsPointSequence &topologyTestPoints,
113-
QString *errorMsg = nullptr ) const override;
110+
EngineOperationResult splitGeometry( const QgsLineString &splitLine,
111+
QList<QgsAbstractGeometry *> &newGeometries,
112+
bool topological,
113+
QgsPointSequence &topologyTestPoints,
114+
QString *errorMsg = nullptr ) const override;
114115

115116
QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const override;
116117

@@ -131,8 +132,14 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
131132
int joinStyle, double miterLimit,
132133
QString *errorMsg = nullptr ) const;
133134

134-
135-
QgsAbstractGeometry *reshapeGeometry( const QgsLineString &reshapeWithLine, int *errorCode, QString *errorMsg = nullptr ) const;
135+
/**
136+
* Reshapes the geometry using a line
137+
* @param reshapeWithLine the line used to reshape lines or polygons
138+
* @param errorCode if specified, provides result of operation (success or reason of failure)
139+
* @param errorMsg if specified, provides more details about failure
140+
* @return the reshaped geometry
141+
*/
142+
QgsAbstractGeometry *reshapeGeometry( const QgsLineString &reshapeWithLine, EngineOperationResult *errorCode, QString *errorMsg = nullptr ) const;
136143

137144
/** Merges any connected lines in a LineString/MultiLineString geometry and
138145
* converts them to single line strings.
@@ -261,10 +268,10 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
261268
static GEOSGeometry *createGeosPolygon( const QgsAbstractGeometry *poly, double precision );
262269

263270
//utils for geometry split
264-
int topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg = nullptr ) const;
271+
bool topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg = nullptr ) const;
265272
GEOSGeometry *linePointDifference( GEOSGeometry *GEOSsplitPoint ) const;
266-
int splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
267-
int splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
273+
EngineOperationResult splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
274+
EngineOperationResult splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
268275

269276
//utils for reshape
270277
static GEOSGeometry *reshapeLine( const GEOSGeometry *line, const GEOSGeometry *reshapeLineGeos, double precision );

‎src/core/qgsvectorlayereditutils.cpp‎

Lines changed: 92 additions & 91 deletions
Large diffs are not rendered by default.

‎src/core/qgsvectorlayereditutils.h‎

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@
1919
#include "qgis_core.h"
2020
#include "qgis.h"
2121
#include "qgsfeature.h"
22-
23-
#include "qgsvectorlayer.h"
2422
#include "qgsgeometry.h"
23+
#include "qgsvectorlayer.h"
2524

2625
class QgsCurve;
2726

@@ -66,68 +65,40 @@ class CORE_EXPORT QgsVectorLayerEditUtils
6665
QgsVectorLayer::EditResult deleteVertex( QgsFeatureId featureId, int vertex );
6766

6867
/** Adds a ring to polygon/multipolygon features
69-
* \param ring ring to add
70-
* \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
68+
* @param ring ring to add
69+
* @param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
7170
* all intersecting features are tested and the ring is added to the first valid feature.
72-
* \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
73-
* \returns
74-
* 0 in case of success,
75-
* 1 problem with feature type,
76-
* 2 ring not closed,
77-
* 3 ring not valid,
78-
* 4 ring crosses existing rings,
79-
* 5 no feature found where ring can be inserted
71+
* @param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
72+
* @return OperationResult result code: success or reason of failure
8073
*/
81-
// TODO QGIS 3.0 returns an enum instead of a magic constant
82-
int addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr );
74+
QgsGeometry::OperationResult addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr );
8375

84-
/** Adds a ring to polygon/multipolygon features
85-
* \param ring ring to add
86-
* \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
76+
/**
77+
* Adds a ring to polygon/multipolygon features
78+
* @param ring ring to add
79+
* @param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
8780
* all intersecting features are tested and the ring is added to the first valid feature.
88-
* \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
89-
* \returns
90-
* 0 in case of success,
91-
* 1 problem with feature type,
92-
* 2 ring not closed,
93-
* 3 ring not valid,
94-
* 4 ring crosses existing rings,
95-
* 5 no feature found where ring can be inserted
96-
* \note available in Python bindings as addCurvedRing
81+
* @param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
82+
* @return OperationResult result code: success or reason of failure
83+
* @note available in python bindings as addCurvedRing
9784
*/
98-
// TODO QGIS 3.0 returns an enum instead of a magic constant
99-
int addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr ) SIP_PYNAME( addCurvedRing );
100-
101-
/** Adds a new part polygon to a multipart feature
102-
* \returns
103-
* 0 in case of success,
104-
* 1 if selected feature is not multipart,
105-
* 2 if ring is not a valid geometry,
106-
* 3 if new polygon ring not disjoint with existing rings,
107-
* 4 if no feature was selected,
108-
* 5 if several features are selected,
109-
* 6 if selected geometry not found
85+
QgsGeometry::OperationResult addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr ) SIP_PYNAME( addCurvedRing );
86+
87+
/**
88+
* Adds a new part polygon to a multipart feature
89+
* @returns QgsGeometry::OperationResult a result code: success or reason of failure
11090
*/
111-
// TODO QGIS 3.0 returns an enum instead of a magic constant
112-
int addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
113-
114-
/** Adds a new part polygon to a multipart feature
115-
* \returns
116-
* 0 in case of success,
117-
* 1 if selected feature is not multipart,
118-
* 2 if ring is not a valid geometry,
119-
* 3 if new polygon ring not disjoint with existing rings,
120-
* 4 if no feature was selected,
121-
* 5 if several features are selected,
122-
* 6 if selected geometry not found
123-
* \note available in Python bindings as addPartV2
91+
QgsGeometry::OperationResult addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
92+
93+
/**
94+
* Adds a new part polygon to a multipart feature
95+
* @returns QgsGeometry::OperationResult a result code: success or reason of failure
96+
* @note available in python bindings as addPartV2
12497
*/
125-
// TODO QGIS 3.0 returns an enum instead of a magic constant
126-
int addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
98+
QgsGeometry::OperationResult addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
12799

128-
//! \note available in Python bindings as addCurvedPart
129-
// TODO QGIS 3.0 returns an enum instead of a magic constant
130-
int addPart( QgsCurve *ring, QgsFeatureId featureId ) SIP_PYNAME( addCurvedPart );
100+
// @note available in python bindings as addCurvedPart
101+
QgsGeometry::OperationResult addPart( QgsCurve *ring, QgsFeatureId featureId ) SIP_PYNAME( addCurvedPart );
131102

132103
/** Translates feature by dx, dy
133104
* \param featureId id of the feature to translate
@@ -145,7 +116,7 @@ class CORE_EXPORT QgsVectorLayerEditUtils
145116
* 4 if there is a selection but no feature split
146117
*/
147118
// TODO QGIS 3.0 returns an enum instead of a magic constant
148-
int splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
119+
QgsGeometry::OperationResult splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
149120

150121
/** Splits features cut by the given line
151122
* \param splitLine line that splits the layer features
@@ -155,7 +126,7 @@ class CORE_EXPORT QgsVectorLayerEditUtils
155126
* 4 if there is a selection but no feature split
156127
*/
157128
// TODO QGIS 3.0 returns an enum instead of a magic constant
158-
int splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
129+
QgsGeometry::OperationResult splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
159130

160131
/** Adds topological points for every vertex of the geometry.
161132
* \param geom the geometry where each vertex is added to segments of other features
@@ -173,15 +144,15 @@ class CORE_EXPORT QgsVectorLayerEditUtils
173144
*/
174145
int addTopologicalPoints( const QgsPointXY &p );
175146

176-
protected:
177-
178-
/** Little helper function that gives bounding box from a list of points.
179-
\returns 0 in case of success */
180-
int boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
181-
182147
private:
183148

184-
QgsVectorLayer *L = nullptr;
149+
/**
150+
* Little helper function that gives bounding box from a list of points.
151+
* \returns True in case of success
152+
*/
153+
bool boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
154+
155+
QgsVectorLayer *mLayer = nullptr;
185156
};
186157

187158
#endif // QGSVECTORLAYEREDITUTILS_H

‎tests/src/python/test_qgsgeometry.py‎

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,14 +1423,14 @@ def testAddPart(self):
14231423
]
14241424

14251425
polyline = QgsGeometry.fromPolyline(points[0])
1426-
self.assertEqual(polyline.addPoints(points[1][0:1]), 2, "addPoints with one point line unexpectedly succeeded.")
1427-
self.assertEqual(polyline.addPoints(points[1][0:2]), 0, "addPoints with two point line failed.")
1426+
self.assertEqual(polyline.addPoints(points[1][0:1]), QgsGeometry.InvalidInput, "addPoints with one point line unexpectedly succeeded.")
1427+
self.assertEqual(polyline.addPoints(points[1][0:2]), QgsGeometry.Success, "addPoints with two point line failed.")
14281428
expwkt = "MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 0, 3 1))"
14291429
wkt = polyline.exportToWkt()
14301430
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
14311431

14321432
polyline = QgsGeometry.fromPolyline(points[0])
1433-
self.assertEqual(polyline.addPoints(points[1]), 0, "addPoints with %d point line failed." % len(points[1]))
1433+
self.assertEqual(polyline.addPoints(points[1]), QgsGeometry.Success, "addPoints with %d point line failed." % len(points[1]))
14341434
expwkt = "MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 0, 3 1, 5 1, 5 0, 6 0))"
14351435
wkt = polyline.exportToWkt()
14361436
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
@@ -1439,7 +1439,7 @@ def testAddPart(self):
14391439
polyline = QgsGeometry.fromPolyline(points[0])
14401440
polyline.geometry().addZValue(4.0)
14411441
points2 = [QgsPoint(p[0], p[1], 3.0, wkbType=QgsWkbTypes.PointZ) for p in points[1]]
1442-
self.assertEqual(polyline.addPointsV2(points2), 0)
1442+
self.assertEqual(polyline.addPointsV2(points2), QgsGeometry.Success)
14431443
expwkt = "MultiLineStringZ ((0 0 4, 1 0 4, 1 1 4, 2 1 4, 2 0 4),(3 0 3, 3 1 3, 5 1 3, 5 0 3, 6 0 3))"
14441444
wkt = polyline.exportToWkt()
14451445
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
@@ -1456,34 +1456,34 @@ def testAddPart(self):
14561456

14571457
polygon = QgsGeometry.fromPolygon(points[0])
14581458

1459-
self.assertEqual(polygon.addPoints(points[1][0][0:1]), 2, "addPoints with one point ring unexpectedly succeeded.")
1460-
self.assertEqual(polygon.addPoints(points[1][0][0:2]), 2, "addPoints with two point ring unexpectedly succeeded.")
1461-
self.assertEqual(polygon.addPoints(points[1][0][0:3]), 2, "addPoints with unclosed three point ring unexpectedly succeeded.")
1462-
self.assertEqual(polygon.addPoints([QgsPointXY(4, 0), QgsPointXY(5, 0), QgsPointXY(4, 0)]), 2, "addPoints with 'closed' three point ring unexpectedly succeeded.")
1459+
self.assertEqual(polygon.addPoints(points[1][0][0:1]), QgsGeometry.InvalidInput, "addPoints with one point ring unexpectedly succeeded.")
1460+
self.assertEqual(polygon.addPoints(points[1][0][0:2]), QgsGeometry.InvalidInput, "addPoints with two point ring unexpectedly succeeded.")
1461+
self.assertEqual(polygon.addPoints(points[1][0][0:3]), QgsGeometry.InvalidInput, "addPoints with unclosed three point ring unexpectedly succeeded.")
1462+
self.assertEqual(polygon.addPoints([QgsPointXY(4, 0), QgsPointXY(5, 0), QgsPointXY(4, 0)]), QgsGeometry.InvalidInput, "addPoints with 'closed' three point ring unexpectedly succeeded.")
14631463

1464-
self.assertEqual(polygon.addPoints(points[1][0]), 0, "addPoints failed")
1464+
self.assertEqual(polygon.addPoints(points[1][0]), QgsGeometry.Success, "addPoints failed")
14651465
expwkt = "MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))"
14661466
wkt = polygon.exportToWkt()
14671467
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
14681468

14691469
mp = QgsGeometry.fromMultiPolygon(points[:1])
14701470
p = QgsGeometry.fromPolygon(points[1])
14711471

1472-
self.assertEqual(mp.addPartGeometry(p), 0)
1472+
self.assertEqual(mp.addPartGeometry(p), QgsGeometry.Success)
14731473
wkt = mp.exportToWkt()
14741474
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
14751475

14761476
mp = QgsGeometry.fromMultiPolygon(points[:1])
14771477
mp2 = QgsGeometry.fromMultiPolygon(points[1:])
1478-
self.assertEqual(mp.addPartGeometry(mp2), 0)
1478+
self.assertEqual(mp.addPartGeometry(mp2), QgsGeometry.Success)
14791479
wkt = mp.exportToWkt()
14801480
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
14811481

14821482
# test adding a part with Z values
14831483
polygon = QgsGeometry.fromPolygon(points[0])
14841484
polygon.geometry().addZValue(4.0)
14851485
points2 = [QgsPoint(pi[0], pi[1], 3.0, wkbType=QgsWkbTypes.PointZ) for pi in points[1][0]]
1486-
self.assertEqual(polygon.addPointsV2(points2), 0)
1486+
self.assertEqual(polygon.addPointsV2(points2), QgsGeometry.Success)
14871487
expwkt = "MultiPolygonZ (((0 0 4, 1 0 4, 1 1 4, 2 1 4, 2 2 4, 0 2 4, 0 0 4)),((4 0 3, 5 0 3, 5 2 3, 3 2 3, 3 1 3, 4 1 3, 4 0 3)))"
14881488
wkt = polygon.exportToWkt()
14891489
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
@@ -1492,38 +1492,38 @@ def testAddPart(self):
14921492
empty = QgsGeometry()
14931493
# if not default type specified, addPart should fail
14941494
result = empty.addPoints([QgsPointXY(4, 0)])
1495-
assert result != 0, 'Got return code {}'.format(result)
1495+
assert result != QgsGeometry.Success, 'Got return code {}'.format(result)
14961496
result = empty.addPoints([QgsPointXY(4, 0)], QgsWkbTypes.PointGeometry)
1497-
self.assertEqual(result, 0, 'Got return code {}'.format(result))
1497+
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
14981498
wkt = empty.exportToWkt()
14991499
expwkt = 'MultiPoint ((4 0))'
15001500
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
15011501
result = empty.addPoints([QgsPointXY(5, 1)])
1502-
self.assertEqual(result, 0, 'Got return code {}'.format(result))
1502+
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
15031503
wkt = empty.exportToWkt()
15041504
expwkt = 'MultiPoint ((4 0),(5 1))'
15051505
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
15061506
# next try with lines
15071507
empty = QgsGeometry()
15081508
result = empty.addPoints(points[0][0], QgsWkbTypes.LineGeometry)
1509-
self.assertEqual(result, 0, 'Got return code {}'.format(result))
1509+
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
15101510
wkt = empty.exportToWkt()
15111511
expwkt = 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0))'
15121512
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
15131513
result = empty.addPoints(points[1][0])
1514-
self.assertEqual(result, 0, 'Got return code {}'.format(result))
1514+
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
15151515
wkt = empty.exportToWkt()
15161516
expwkt = 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0),(4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0))'
15171517
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
15181518
# finally try with polygons
15191519
empty = QgsGeometry()
15201520
result = empty.addPoints(points[0][0], QgsWkbTypes.PolygonGeometry)
1521-
self.assertEqual(result, 0, 'Got return code {}'.format(result))
1521+
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
15221522
wkt = empty.exportToWkt()
15231523
expwkt = 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)))'
15241524
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
15251525
result = empty.addPoints(points[1][0])
1526-
self.assertEqual(result, 0, 'Got return code {}'.format(result))
1526+
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
15271527
wkt = empty.exportToWkt()
15281528
expwkt = 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))'
15291529
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)

0 commit comments

Comments
 (0)
Please sign in to comment.