mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Return enum instead of int from QgsGeometry operations
This commit is contained in:
parent
8d615543b7
commit
86e8da74cb
@ -44,6 +44,23 @@ class QgsGeometry
|
|||||||
#include "qgsgeometry.h"
|
#include "qgsgeometry.h"
|
||||||
%End
|
%End
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum OperationResult
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
NothingHappened,
|
||||||
|
InvalidBaseGeometry,
|
||||||
|
InvalidInput,
|
||||||
|
GeometryEngineError,
|
||||||
|
AddPartSelectedGeometryNotFound,
|
||||||
|
AddPartNotMultiGeometry,
|
||||||
|
AddRingNotClosed,
|
||||||
|
AddRingNotValid,
|
||||||
|
AddRingCrossesExistingRings,
|
||||||
|
AddRingNotInExistingFeature,
|
||||||
|
SplitCannotSplitPoint,
|
||||||
|
};
|
||||||
|
|
||||||
QgsGeometry();
|
QgsGeometry();
|
||||||
%Docstring
|
%Docstring
|
||||||
Constructor
|
Constructor
|
||||||
@ -380,63 +397,58 @@ Returns true if WKB of the geometry is of WKBMulti* type
|
|||||||
:rtype: float
|
:rtype: float
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addRing( const QList<QgsPointXY> &ring );
|
OperationResult addRing( const QList<QgsPointXY> &ring );
|
||||||
%Docstring
|
%Docstring
|
||||||
Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
||||||
:return: 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
\param ring The ring to be added
|
||||||
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*
|
:return: OperationResult a result code: success or reason of failure
|
||||||
:rtype: int
|
:rtype: OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addRing( QgsCurve *ring /Transfer/ );
|
OperationResult addRing( QgsCurve *ring /Transfer/ );
|
||||||
%Docstring
|
%Docstring
|
||||||
Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
||||||
:return: 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
\param ring The ring to be added
|
||||||
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*
|
:return: OperationResult a result code: success or reason of failure
|
||||||
:rtype: int
|
:rtype: OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPoints/;
|
OperationResult addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPoints/;
|
||||||
%Docstring
|
%Docstring
|
||||||
Adds a new part to a the geometry.
|
Adds a new part to a the geometry.
|
||||||
\param points points describing part to add
|
\param points points describing part to add
|
||||||
\param geomType default geometry type to create if no existing geometry
|
\param geomType default geometry type to create if no existing geometry
|
||||||
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
:return: OperationResult a result code: success or reason of failure
|
||||||
not disjoint with existing polygons of the feature
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPointsV2/;
|
OperationResult addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) /PyName=addPointsV2/;
|
||||||
%Docstring
|
%Docstring
|
||||||
Adds a new part to a the geometry.
|
Adds a new part to a the geometry.
|
||||||
\param points points describing part to add
|
\param points points describing part to add
|
||||||
\param geomType default geometry type to create if no existing geometry
|
\param geomType default geometry type to create if no existing geometry
|
||||||
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
:return: OperationResult a result code: success or reason of failure
|
||||||
not disjoint with existing polygons of the feature
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addPart( QgsAbstractGeometry *part /Transfer/, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
|
OperationResult addPart( QgsAbstractGeometry *part /Transfer/, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
|
||||||
%Docstring
|
%Docstring
|
||||||
Adds a new part to this geometry.
|
Adds a new part to this geometry.
|
||||||
\param part part to add (ownership is transferred)
|
\param part part to add (ownership is transferred)
|
||||||
\param geomType default geometry type to create if no existing geometry
|
\param geomType default geometry type to create if no existing geometry
|
||||||
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
:return: OperationResult a result code: success or reason of failure
|
||||||
not disjoint with existing polygons of the feature
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
|
||||||
int addPart( const QgsGeometry &newPart ) /PyName=addPartGeometry/;
|
OperationResult addPart( const QgsGeometry &newPart ) /PyName=addPartGeometry/;
|
||||||
%Docstring
|
%Docstring
|
||||||
Adds a new island polygon to a multipolygon feature
|
Adds a new island polygon to a multipolygon feature
|
||||||
:return: 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
:return: OperationResult a result code: success or reason of failure
|
||||||
not disjoint with existing polygons of the feature
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
available in Python bindings as addPartGeometry
|
available in python bindings as addPartGeometry
|
||||||
.. versionadded:: 2.2
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
|
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
|
||||||
@ -448,52 +460,52 @@ not disjoint with existing polygons of the feature
|
|||||||
:rtype: QgsGeometry
|
:rtype: QgsGeometry
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int translate( double dx, double dy );
|
OperationResult translate( double dx, double dy );
|
||||||
%Docstring
|
%Docstring
|
||||||
Translate this geometry by dx, dy
|
Translate this geometry by dx, dy
|
||||||
:return: 0 in case of success*
|
:return: OperationResult a result code: success or reason of failure
|
||||||
:rtype: int
|
:rtype: OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int transform( const QgsCoordinateTransform &ct );
|
OperationResult transform( const QgsCoordinateTransform &ct );
|
||||||
%Docstring
|
%Docstring
|
||||||
Transform this geometry as described by CoordinateTransform ct
|
Transform this geometry as described by CoordinateTransform ct
|
||||||
:return: 0 in case of success*
|
:return: OperationResult a result code: success or reason of failure
|
||||||
:rtype: int
|
:rtype: OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int transform( const QTransform &ct );
|
OperationResult transform( const QTransform &ct );
|
||||||
%Docstring
|
%Docstring
|
||||||
Transform this geometry as described by QTransform ct
|
Transform this geometry as described by QTransform ct
|
||||||
.. versionadded:: 2.8
|
:return: OperationResult a result code: success or reason of failure
|
||||||
:return: 0 in case of success*
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int rotate( double rotation, const QgsPointXY ¢er );
|
OperationResult rotate( double rotation, const QgsPointXY ¢er );
|
||||||
%Docstring
|
%Docstring
|
||||||
Rotate this geometry around the Z axis
|
Rotate this geometry around the Z axis
|
||||||
.. versionadded:: 2.8
|
\param rotation clockwise rotation in degrees
|
||||||
\param rotation clockwise rotation in degrees
|
\param center rotation center
|
||||||
\param center rotation center
|
:return: OperationResult a result code: success or reason of failure
|
||||||
:return: 0 in case of success*
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int splitGeometry( const QList<QgsPointXY> &splitLine,
|
OperationResult splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints );
|
||||||
QList<QgsGeometry> &newGeometries /Out/,
|
|
||||||
bool topological,
|
|
||||||
QList<QgsPointXY> &topologyTestPoints /Out/ );
|
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
Splits this geometry according to a given line.
|
||||||
|
\param splitLine the line that splits the geometry
|
||||||
|
\param[out] newGeometries list of new geometries that have been created with the split
|
||||||
|
\param topological true if topological editing is enabled
|
||||||
|
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
|
||||||
|
:return: OperationResult a result code: success or reason of failure
|
||||||
|
:rtype: OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int reshapeGeometry( const QgsLineString &reshapeLineString );
|
OperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
|
||||||
%Docstring
|
%Docstring
|
||||||
Replaces a part of this geometry with another line
|
Replaces a part of this geometry with another line
|
||||||
:return: 0 in case of success
|
:return: OperationResult a result code: success or reason of failure
|
||||||
.. versionadded:: 1.3
|
:rtype: OperationResult
|
||||||
:rtype: int
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +21,19 @@ class QgsGeometryEngine
|
|||||||
#include "qgsgeometryengine.h"
|
#include "qgsgeometryengine.h"
|
||||||
%End
|
%End
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum EngineOperationResult
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
NothingHappened,
|
||||||
|
MethodNotImplemented,
|
||||||
|
EngineError,
|
||||||
|
NodedGeometryError,
|
||||||
|
InvalidBaseGeometry,
|
||||||
|
InvalidInput,
|
||||||
|
SplitCannotSplitPoint,
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~QgsGeometryEngine();
|
virtual ~QgsGeometryEngine();
|
||||||
|
|
||||||
virtual void geometryChanged() = 0;
|
virtual void geometryChanged() = 0;
|
||||||
@ -230,12 +243,12 @@ class QgsGeometryEngine
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual int splitGeometry( const QgsLineString &splitLine,
|
virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
|
||||||
QList<QgsAbstractGeometry *> &newGeometries,
|
QList<QgsAbstractGeometry *> &newGeometries,
|
||||||
bool topological,
|
bool topological,
|
||||||
QgsPointSequence &topologyTestPoints, QString *errorMsg = 0 ) const;
|
QgsPointSequence &topologyTestPoints, QString *errorMsg = 0 ) const;
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
:rtype: QgsGeometryEngine.EngineOperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = 0 ) const = 0 /Factory/;
|
virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = 0 ) const = 0 /Factory/;
|
||||||
|
@ -63,29 +63,51 @@ class QgsVectorLayerEditUtils
|
|||||||
:rtype: QgsVectorLayer.EditResult
|
:rtype: QgsVectorLayer.EditResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 );
|
QgsGeometry::OperationResult addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 );
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
Adds a ring to polygon/multipolygon features
|
||||||
|
@param ring ring to add
|
||||||
|
@param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
|
||||||
|
all intersecting features are tested and the ring is added to the first valid feature.
|
||||||
|
@param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
|
||||||
|
@return OperationResult result code: success or reason of failure
|
||||||
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 ) /PyName=addCurvedRing/;
|
QgsGeometry::OperationResult addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = 0 ) /PyName=addCurvedRing/;
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
Adds a ring to polygon/multipolygon features
|
||||||
|
@param ring ring to add
|
||||||
|
@param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
|
||||||
|
all intersecting features are tested and the ring is added to the first valid feature.
|
||||||
|
@param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
|
||||||
|
@return OperationResult result code: success or reason of failure
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
available in python bindings as addCurvedRing
|
||||||
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
|
QgsGeometry::OperationResult addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
Adds a new part polygon to a multipart feature
|
||||||
|
@returns QgsGeometry.OperationResult a result code: success or reason of failure
|
||||||
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
|
QgsGeometry::OperationResult addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
Adds a new part polygon to a multipart feature
|
||||||
|
@returns QgsGeometry.OperationResult a result code: success or reason of failure
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
available in python bindings as addPartV2
|
||||||
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addPart( QgsCurve *ring, QgsFeatureId featureId ) /PyName=addCurvedPart/;
|
QgsGeometry::OperationResult addPart( QgsCurve *ring, QgsFeatureId featureId ) /PyName=addCurvedPart/;
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int translateFeature( QgsFeatureId featureId, double dx, double dy );
|
int translateFeature( QgsFeatureId featureId, double dx, double dy );
|
||||||
@ -98,14 +120,14 @@ class QgsVectorLayerEditUtils
|
|||||||
:rtype: int
|
:rtype: int
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
QgsGeometry::OperationResult splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
QgsGeometry::OperationResult splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: int
|
:rtype: QgsGeometry.OperationResult
|
||||||
%End
|
%End
|
||||||
|
|
||||||
int addTopologicalPoints( const QgsGeometry &geom );
|
int addTopologicalPoints( const QgsGeometry &geom );
|
||||||
@ -130,15 +152,6 @@ class QgsVectorLayerEditUtils
|
|||||||
:rtype: int
|
:rtype: int
|
||||||
%End
|
%End
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
int boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
|
|
||||||
%Docstring
|
|
||||||
Little helper function that gives bounding box from a list of points.
|
|
||||||
:return: 0 in case of success *
|
|
||||||
:rtype: int
|
|
||||||
%End
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
@ -626,7 +626,7 @@ double QgsGeometry::closestSegmentWithContext(
|
|||||||
return sqrDist;
|
return sqrDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addRing( const QList<QgsPointXY> &ring )
|
QgsGeometry::OperationResult QgsGeometry::addRing( const QList<QgsPointXY> &ring )
|
||||||
{
|
{
|
||||||
detach( true );
|
detach( true );
|
||||||
|
|
||||||
@ -634,12 +634,12 @@ int QgsGeometry::addRing( const QList<QgsPointXY> &ring )
|
|||||||
return addRing( ringLine );
|
return addRing( ringLine );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addRing( QgsCurve *ring )
|
QgsGeometry::OperationResult QgsGeometry::addRing( QgsCurve *ring )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
delete ring;
|
delete ring;
|
||||||
return 1;
|
return InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
detach( true );
|
detach( true );
|
||||||
@ -647,14 +647,14 @@ int QgsGeometry::addRing( QgsCurve *ring )
|
|||||||
return QgsGeometryEditUtils::addRing( d->geometry, ring );
|
return QgsGeometryEditUtils::addRing( d->geometry, ring );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType )
|
QgsGeometry::OperationResult QgsGeometry::addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType )
|
||||||
{
|
{
|
||||||
QgsPointSequence l;
|
QgsPointSequence l;
|
||||||
convertPointList( points, l );
|
convertPointList( points, l );
|
||||||
return addPart( l, geomType );
|
return addPart( l, geomType );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType )
|
QgsGeometry::OperationResult QgsGeometry::addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType )
|
||||||
{
|
{
|
||||||
QgsAbstractGeometry *partGeom = nullptr;
|
QgsAbstractGeometry *partGeom = nullptr;
|
||||||
if ( points.size() == 1 )
|
if ( points.size() == 1 )
|
||||||
@ -670,7 +670,7 @@ int QgsGeometry::addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryT
|
|||||||
return addPart( partGeom, geomType );
|
return addPart( partGeom, geomType );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType geomType )
|
QgsGeometry::OperationResult QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType geomType )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
@ -687,7 +687,7 @@ int QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType g
|
|||||||
d->geometry = new QgsMultiPolygonV2();
|
d->geometry = new QgsMultiPolygonV2();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return QgsGeometry::AddPartNotMultiGeometry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -699,11 +699,15 @@ int QgsGeometry::addPart( QgsAbstractGeometry *part, QgsWkbTypes::GeometryType g
|
|||||||
return QgsGeometryEditUtils::addPart( d->geometry, part );
|
return QgsGeometryEditUtils::addPart( d->geometry, part );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addPart( const QgsGeometry &newPart )
|
QgsGeometry::OperationResult QgsGeometry::addPart( const QgsGeometry &newPart )
|
||||||
{
|
{
|
||||||
if ( !d->geometry || !newPart.d || !newPart.d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
|
}
|
||||||
|
if ( !newPart.d || !newPart.d->geometry )
|
||||||
|
{
|
||||||
|
return QgsGeometry::AddPartNotMultiGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
return addPart( newPart.d->geometry->clone() );
|
return addPart( newPart.d->geometry->clone() );
|
||||||
@ -744,11 +748,15 @@ QgsGeometry QgsGeometry::removeInteriorRings( double minimumRingArea ) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::addPart( GEOSGeometry *newPart )
|
QgsGeometry::OperationResult QgsGeometry::addPart( GEOSGeometry *newPart )
|
||||||
{
|
{
|
||||||
if ( !d->geometry || !newPart )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
|
}
|
||||||
|
if ( !newPart )
|
||||||
|
{
|
||||||
|
return QgsGeometry::AddPartNotMultiGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
detach( true );
|
detach( true );
|
||||||
@ -757,24 +765,24 @@ int QgsGeometry::addPart( GEOSGeometry *newPart )
|
|||||||
return QgsGeometryEditUtils::addPart( d->geometry, geom );
|
return QgsGeometryEditUtils::addPart( d->geometry, geom );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::translate( double dx, double dy )
|
QgsGeometry::OperationResult QgsGeometry::translate( double dx, double dy )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
detach( true );
|
detach( true );
|
||||||
|
|
||||||
d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
|
d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
|
||||||
return 0;
|
return QgsGeometry::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::rotate( double rotation, const QgsPointXY ¢er )
|
QgsGeometry::OperationResult QgsGeometry::rotate( double rotation, const QgsPointXY ¢er )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
detach( true );
|
detach( true );
|
||||||
@ -783,14 +791,14 @@ int QgsGeometry::rotate( double rotation, const QgsPointXY ¢er )
|
|||||||
t.rotate( -rotation );
|
t.rotate( -rotation );
|
||||||
t.translate( -center.x(), -center.y() );
|
t.translate( -center.x(), -center.y() );
|
||||||
d->geometry->transform( t );
|
d->geometry->transform( t );
|
||||||
return 0;
|
return QgsGeometry::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints )
|
QgsGeometry::OperationResult QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 0;
|
return InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QgsAbstractGeometry *> newGeoms;
|
QList<QgsAbstractGeometry *> newGeoms;
|
||||||
@ -798,9 +806,9 @@ int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeo
|
|||||||
QgsPointSequence tp;
|
QgsPointSequence tp;
|
||||||
|
|
||||||
QgsGeos geos( d->geometry );
|
QgsGeos geos( d->geometry );
|
||||||
int result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
|
QgsGeometryEngine::EngineOperationResult result = geos.splitGeometry( splitLineString, newGeoms, topological, tp );
|
||||||
|
|
||||||
if ( result == 0 )
|
if ( result == QgsGeometryEngine::Success )
|
||||||
{
|
{
|
||||||
detach( false );
|
detach( false );
|
||||||
d->geometry = newGeoms.at( 0 );
|
d->geometry = newGeoms.at( 0 );
|
||||||
@ -813,27 +821,69 @@ int QgsGeometry::splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeo
|
|||||||
}
|
}
|
||||||
|
|
||||||
convertPointList( tp, topologyTestPoints );
|
convertPointList( tp, topologyTestPoints );
|
||||||
return result;
|
|
||||||
|
switch ( result )
|
||||||
|
{
|
||||||
|
case QgsGeometryEngine::Success:
|
||||||
|
return QgsGeometry::Success;
|
||||||
|
case QgsGeometryEngine::MethodNotImplemented:
|
||||||
|
case QgsGeometryEngine::EngineError:
|
||||||
|
case QgsGeometryEngine::NodedGeometryError:
|
||||||
|
return QgsGeometry::GeometryEngineError;
|
||||||
|
case QgsGeometryEngine::InvalidBaseGeometry:
|
||||||
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
|
case QgsGeometryEngine::InvalidInput:
|
||||||
|
return QgsGeometry::InvalidInput;
|
||||||
|
case QgsGeometryEngine::SplitCannotSplitPoint:
|
||||||
|
return QgsGeometry::SplitCannotSplitPoint;
|
||||||
|
case QgsGeometryEngine::NothingHappened:
|
||||||
|
return QgsGeometry::NothingHappened;
|
||||||
|
//default: do not implement default to handle properly all cases
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should never be reached
|
||||||
|
Q_ASSERT( false );
|
||||||
|
return QgsGeometry::NothingHappened;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
|
QgsGeometry::OperationResult QgsGeometry::reshapeGeometry( const QgsLineString &reshapeLineString )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 0;
|
return InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsGeos geos( d->geometry );
|
QgsGeos geos( d->geometry );
|
||||||
int errorCode = 0;
|
QgsGeometryEngine::EngineOperationResult errorCode = QgsGeometryEngine::Success;
|
||||||
QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
|
QgsAbstractGeometry *geom = geos.reshapeGeometry( reshapeLineString, &errorCode );
|
||||||
if ( errorCode == 0 && geom )
|
if ( errorCode == QgsGeometryEngine::Success && geom )
|
||||||
{
|
{
|
||||||
detach( false );
|
detach( false );
|
||||||
delete d->geometry;
|
delete d->geometry;
|
||||||
d->geometry = geom;
|
d->geometry = geom;
|
||||||
return 0;
|
return Success;
|
||||||
}
|
}
|
||||||
return errorCode;
|
|
||||||
|
switch ( errorCode )
|
||||||
|
{
|
||||||
|
case QgsGeometryEngine::Success:
|
||||||
|
return Success;
|
||||||
|
case QgsGeometryEngine::MethodNotImplemented:
|
||||||
|
case QgsGeometryEngine::EngineError:
|
||||||
|
case QgsGeometryEngine::NodedGeometryError:
|
||||||
|
return GeometryEngineError;
|
||||||
|
case QgsGeometryEngine::InvalidBaseGeometry:
|
||||||
|
return InvalidBaseGeometry;
|
||||||
|
case QgsGeometryEngine::InvalidInput:
|
||||||
|
return InvalidInput;
|
||||||
|
case QgsGeometryEngine::SplitCannotSplitPoint: // should not happen
|
||||||
|
return GeometryEngineError;
|
||||||
|
case QgsGeometryEngine::NothingHappened:
|
||||||
|
return NothingHappened;
|
||||||
|
}
|
||||||
|
|
||||||
|
// should not be reached
|
||||||
|
return GeometryEngineError;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::makeDifferenceInPlace( const QgsGeometry &other )
|
int QgsGeometry::makeDifferenceInPlace( const QgsGeometry &other )
|
||||||
@ -2091,28 +2141,28 @@ bool QgsGeometry::requiresConversionToStraightSegments() const
|
|||||||
return d->geometry->hasCurvedSegments();
|
return d->geometry->hasCurvedSegments();
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::transform( const QgsCoordinateTransform &ct )
|
QgsGeometry::OperationResult QgsGeometry::transform( const QgsCoordinateTransform &ct )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
detach();
|
detach();
|
||||||
d->geometry->transform( ct );
|
d->geometry->transform( ct );
|
||||||
return 0;
|
return QgsGeometry::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometry::transform( const QTransform &ct )
|
QgsGeometry::OperationResult QgsGeometry::transform( const QTransform &ct )
|
||||||
{
|
{
|
||||||
if ( !d->geometry )
|
if ( !d->geometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
detach();
|
detach();
|
||||||
d->geometry->transform( ct );
|
d->geometry->transform( ct );
|
||||||
return 0;
|
return QgsGeometry::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsGeometry::mapToPixel( const QgsMapToPixel &mtp )
|
void QgsGeometry::mapToPixel( const QgsMapToPixel &mtp )
|
||||||
|
@ -96,6 +96,30 @@ struct QgsGeometryPrivate;
|
|||||||
class CORE_EXPORT QgsGeometry
|
class CORE_EXPORT QgsGeometry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Success or failure of a geometry operation.
|
||||||
|
* This gived details about cause of failure.
|
||||||
|
*/
|
||||||
|
enum OperationResult
|
||||||
|
{
|
||||||
|
Success = 0, //!< Operation succeeded
|
||||||
|
NothingHappened, //!< Nothing happened, without any error
|
||||||
|
InvalidBaseGeometry, //!< The base geometry on which the operation is done is invalid or empty
|
||||||
|
InvalidInput, //!< The input geometry (ring, part, split line, etc.) has not the correct geometry type
|
||||||
|
GeometryEngineError, //!< Geometry engine misses a method implemented or an error occured in the geometry engine
|
||||||
|
/* Add part issues */
|
||||||
|
AddPartSelectedGeometryNotFound, //!< The selected geometry cannot be found
|
||||||
|
AddPartNotMultiGeometry, //!< The source geometry is not multi
|
||||||
|
/* Add ring issues*/
|
||||||
|
AddRingNotClosed, //!< The imput ring is not closed
|
||||||
|
AddRingNotValid, //!< The input ring is not valid
|
||||||
|
AddRingCrossesExistingRings, //!< The input ring crosses existing rings (it is not disjoint)
|
||||||
|
AddRingNotInExistingFeature, //!< The input ring doesn't have any existing ring to fit into
|
||||||
|
/* Split features */
|
||||||
|
SplitCannotSplitPoint, //!< Cannot split points
|
||||||
|
};
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
QgsGeometry();
|
QgsGeometry();
|
||||||
|
|
||||||
@ -390,62 +414,58 @@ class CORE_EXPORT QgsGeometry
|
|||||||
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &afterVertex SIP_OUT ) const;
|
double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &afterVertex SIP_OUT ) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
/**
|
||||||
\returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
* Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
||||||
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
|
* \param ring The ring to be added
|
||||||
int addRing( const QList<QgsPointXY> &ring );
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
*/
|
||||||
|
OperationResult addRing( const QList<QgsPointXY> &ring );
|
||||||
|
|
||||||
/** Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
/**
|
||||||
\returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
* Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
||||||
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
|
* \param ring The ring to be added
|
||||||
int addRing( QgsCurve *ring SIP_TRANSFER );
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
*/
|
||||||
|
OperationResult addRing( QgsCurve *ring SIP_TRANSFER );
|
||||||
|
|
||||||
/** Adds a new part to a the geometry.
|
/**
|
||||||
|
* Adds a new part to a the geometry.
|
||||||
* \param points points describing part to add
|
* \param points points describing part to add
|
||||||
* \param geomType default geometry type to create if no existing geometry
|
* \param geomType default geometry type to create if no existing geometry
|
||||||
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
* not disjoint with existing polygons of the feature
|
|
||||||
*/
|
*/
|
||||||
int addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPoints );
|
OperationResult addPart( const QList<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPoints );
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
|
||||||
|
|
||||||
/** Adds a new part to a the geometry.
|
/**
|
||||||
|
* Adds a new part to a the geometry.
|
||||||
* \param points points describing part to add
|
* \param points points describing part to add
|
||||||
* \param geomType default geometry type to create if no existing geometry
|
* \param geomType default geometry type to create if no existing geometry
|
||||||
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
* not disjoint with existing polygons of the feature
|
|
||||||
*/
|
*/
|
||||||
int addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsV2 );
|
OperationResult addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsV2 );
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
|
||||||
|
|
||||||
/** Adds a new part to this geometry.
|
/**
|
||||||
|
* Adds a new part to this geometry.
|
||||||
* \param part part to add (ownership is transferred)
|
* \param part part to add (ownership is transferred)
|
||||||
* \param geomType default geometry type to create if no existing geometry
|
* \param geomType default geometry type to create if no existing geometry
|
||||||
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
* not disjoint with existing polygons of the feature
|
|
||||||
*/
|
*/
|
||||||
int addPart( QgsAbstractGeometry *part SIP_TRANSFER, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
|
OperationResult addPart( QgsAbstractGeometry *part SIP_TRANSFER, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
|
||||||
|
|
||||||
/** Adds a new island polygon to a multipolygon feature
|
/**
|
||||||
|
* Adds a new island polygon to a multipolygon feature
|
||||||
* \param newPart part to add. Ownership is NOT transferred.
|
* \param newPart part to add. Ownership is NOT transferred.
|
||||||
* \returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
* not disjoint with existing polygons of the feature
|
* \note not available in python bindings
|
||||||
* \note not available in Python bindings
|
|
||||||
*/
|
*/
|
||||||
int addPart( GEOSGeometry *newPart ) SIP_SKIP;
|
OperationResult addPart( GEOSGeometry *newPart ) SIP_SKIP;
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
|
||||||
|
|
||||||
/** Adds a new island polygon to a multipolygon feature
|
/**
|
||||||
\returns 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
* Adds a new island polygon to a multipolygon feature
|
||||||
not disjoint with existing polygons of the feature
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
\note available in Python bindings as addPartGeometry
|
* \note available in python bindings as addPartGeometry
|
||||||
\since QGIS 2.2
|
|
||||||
*/
|
*/
|
||||||
int addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
|
OperationResult addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the interior rings from a (multi)polygon geometry. If the minimumAllowedArea
|
* Removes the interior rings from a (multi)polygon geometry. If the minimumAllowedArea
|
||||||
@ -455,52 +475,57 @@ class CORE_EXPORT QgsGeometry
|
|||||||
*/
|
*/
|
||||||
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
|
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
|
||||||
|
|
||||||
/** Translate this geometry by dx, dy
|
/**
|
||||||
\returns 0 in case of success*/
|
* Translate this geometry by dx, dy
|
||||||
int translate( double dx, double dy );
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
|
|
||||||
/** Transform this geometry as described by CoordinateTransform ct
|
|
||||||
\returns 0 in case of success*/
|
|
||||||
int transform( const QgsCoordinateTransform &ct );
|
|
||||||
|
|
||||||
/** Transform this geometry as described by QTransform ct
|
|
||||||
\since QGIS 2.8
|
|
||||||
\returns 0 in case of success*/
|
|
||||||
int transform( const QTransform &ct );
|
|
||||||
|
|
||||||
/** Rotate this geometry around the Z axis
|
|
||||||
\since QGIS 2.8
|
|
||||||
\param rotation clockwise rotation in degrees
|
|
||||||
\param center rotation center
|
|
||||||
\returns 0 in case of success*/
|
|
||||||
int rotate( double rotation, const QgsPointXY ¢er );
|
|
||||||
|
|
||||||
/** Splits this geometry according to a given line.
|
|
||||||
\param splitLine the line that splits the geometry
|
|
||||||
\param[out] newGeometries list of new geometries that have been created with the split
|
|
||||||
\param topological true if topological editing is enabled
|
|
||||||
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
|
|
||||||
\returns 0 in case of success, 1 if geometry has not been split, error else*/
|
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
|
||||||
int splitGeometry( const QList<QgsPointXY> &splitLine,
|
|
||||||
QList<QgsGeometry> &newGeometries SIP_OUT,
|
|
||||||
bool topological,
|
|
||||||
QList<QgsPointXY> &topologyTestPoints SIP_OUT );
|
|
||||||
|
|
||||||
/** Replaces a part of this geometry with another line
|
|
||||||
* \returns 0 in case of success
|
|
||||||
* \since QGIS 1.3
|
|
||||||
*/
|
*/
|
||||||
int reshapeGeometry( const QgsLineString &reshapeLineString );
|
OperationResult translate( double dx, double dy );
|
||||||
|
|
||||||
/** Changes this geometry such that it does not intersect the other geometry
|
/**
|
||||||
|
* Transform this geometry as described by CoordinateTransform ct
|
||||||
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
|
*/
|
||||||
|
OperationResult transform( const QgsCoordinateTransform &ct );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform this geometry as described by QTransform ct
|
||||||
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
|
*/
|
||||||
|
OperationResult transform( const QTransform &ct );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate this geometry around the Z axis
|
||||||
|
* \param rotation clockwise rotation in degrees
|
||||||
|
* \param center rotation center
|
||||||
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
|
*/
|
||||||
|
OperationResult rotate( double rotation, const QgsPointXY ¢er );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits this geometry according to a given line.
|
||||||
|
* \param splitLine the line that splits the geometry
|
||||||
|
* \param[out] newGeometries list of new geometries that have been created with the split
|
||||||
|
* \param topological true if topological editing is enabled
|
||||||
|
* \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
|
||||||
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
|
*/
|
||||||
|
OperationResult splitGeometry( const QList<QgsPointXY> &splitLine, QList<QgsGeometry> &newGeometries, bool topological, QList<QgsPointXY> &topologyTestPoints );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces a part of this geometry with another line
|
||||||
|
* \returns OperationResult a result code: success or reason of failure
|
||||||
|
*/
|
||||||
|
OperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes this geometry such that it does not intersect the other geometry
|
||||||
* \param other geometry that should not be intersect
|
* \param other geometry that should not be intersect
|
||||||
* \returns 0 in case of success
|
|
||||||
* \note Not available in Python
|
* \note Not available in Python
|
||||||
*/
|
*/
|
||||||
int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
|
int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
|
||||||
|
|
||||||
/** Returns the geometry formed by modifying this geometry such that it does not
|
/**
|
||||||
|
* Returns the geometry formed by modifying this geometry such that it does not
|
||||||
* intersect the other geometry.
|
* intersect the other geometry.
|
||||||
* \param other geometry that should not be intersect
|
* \param other geometry that should not be intersect
|
||||||
* \returns difference geometry, or empty geometry if difference could not be calculated
|
* \returns difference geometry, or empty geometry if difference could not be calculated
|
||||||
|
@ -26,11 +26,12 @@ email : marco.hugentobler at sourcepole dot com
|
|||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
|
QgsGeometry::OperationResult QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *r )
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<QgsCurve> ring( r );
|
||||||
if ( !ring )
|
if ( !ring )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList< QgsCurvePolygon * > polygonList;
|
QList< QgsCurvePolygon * > polygonList;
|
||||||
@ -50,23 +51,20 @@ int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete ring;
|
return QgsGeometry::InvalidInput; //not polygon / multipolygon;
|
||||||
return 1; //not polygon / multipolygon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ring must be closed
|
//ring must be closed
|
||||||
if ( !ring->isClosed() )
|
if ( !ring->isClosed() )
|
||||||
{
|
{
|
||||||
delete ring;
|
return QgsGeometry::AddRingNotClosed;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
else if ( !ring->isRing() )
|
else if ( !ring->isRing() )
|
||||||
{
|
{
|
||||||
delete ring;
|
return QgsGeometry::AddRingNotValid;
|
||||||
return 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring ) );
|
std::unique_ptr<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring.get() ) );
|
||||||
ringGeom->prepareGeometry();
|
ringGeom->prepareGeometry();
|
||||||
|
|
||||||
//for each polygon, test if inside outer ring and no intersection with other interior ring
|
//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 )
|
|||||||
{
|
{
|
||||||
if ( !ringGeom->disjoint( ( *polyIter )->interiorRing( i ) ) )
|
if ( !ringGeom->disjoint( ( *polyIter )->interiorRing( i ) ) )
|
||||||
{
|
{
|
||||||
delete ring;
|
return QgsGeometry::AddRingCrossesExistingRings;
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,59 +89,62 @@ int QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, QgsCurve *ring )
|
|||||||
if ( QgsWkbTypes::hasM( geom->wkbType() ) )
|
if ( QgsWkbTypes::hasM( geom->wkbType() ) )
|
||||||
ring->addMValue( 0 );
|
ring->addMValue( 0 );
|
||||||
|
|
||||||
( *polyIter )->addInteriorRing( ring );
|
( *polyIter )->addInteriorRing( ring.release() );
|
||||||
return 0; //success
|
return QgsGeometry::Success; //success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete ring;
|
return QgsGeometry::AddRingNotInExistingFeature; //not contained in any outer ring
|
||||||
return 5; //not contained in any outer ring
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, QgsAbstractGeometry *part )
|
QgsGeometry::OperationResult QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, QgsAbstractGeometry *p )
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<QgsAbstractGeometry> part( p );
|
||||||
if ( !geom )
|
if ( !geom )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !part )
|
if ( !part )
|
||||||
{
|
{
|
||||||
return 2;
|
return QgsGeometry::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
//multitype?
|
//multitype?
|
||||||
QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom );
|
QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom );
|
||||||
if ( !geomCollection )
|
if ( !geomCollection )
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::AddPartNotMultiGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool added = false;
|
bool added = false;
|
||||||
if ( QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiSurface
|
if ( QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiSurface
|
||||||
|| QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiPolygon )
|
|| QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiPolygon )
|
||||||
{
|
{
|
||||||
QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( part );
|
std::unique_ptr<QgsCurve> curve( qgsgeometry_cast<QgsCurve *>( part.get() ) );
|
||||||
|
if ( curve )
|
||||||
|
part.release();
|
||||||
|
|
||||||
if ( curve && curve->isClosed() && curve->numPoints() >= 4 )
|
if ( curve && curve->isClosed() && curve->numPoints() >= 4 )
|
||||||
{
|
{
|
||||||
QgsCurvePolygon *poly = nullptr;
|
std::unique_ptr<QgsCurvePolygon> poly;
|
||||||
if ( QgsWkbTypes::flatType( curve->wkbType() ) == QgsWkbTypes::LineString )
|
if ( QgsWkbTypes::flatType( curve->wkbType() ) == QgsWkbTypes::LineString )
|
||||||
{
|
{
|
||||||
poly = new QgsPolygonV2();
|
poly.reset( new QgsPolygonV2() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
poly = new QgsCurvePolygon();
|
poly.reset( new QgsCurvePolygon() );
|
||||||
}
|
}
|
||||||
poly->setExteriorRing( curve );
|
poly->setExteriorRing( curve.release() );
|
||||||
added = geomCollection->addGeometry( poly );
|
added = geomCollection->addGeometry( poly.release() );
|
||||||
}
|
}
|
||||||
else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::Polygon )
|
else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::Polygon )
|
||||||
{
|
{
|
||||||
added = geomCollection->addGeometry( part );
|
added = geomCollection->addGeometry( part.release() );
|
||||||
}
|
}
|
||||||
else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::MultiPolygon )
|
else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::MultiPolygon )
|
||||||
{
|
{
|
||||||
QgsGeometryCollection *parts = static_cast<QgsGeometryCollection *>( part );
|
std::unique_ptr<QgsGeometryCollection> parts( static_cast<QgsGeometryCollection *>( part.release() ) );
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
int n = geomCollection->numGeometries();
|
int n = geomCollection->numGeometries();
|
||||||
@ -156,23 +156,19 @@ int QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, QgsAbstractGeometr
|
|||||||
{
|
{
|
||||||
while ( geomCollection->numGeometries() > n )
|
while ( geomCollection->numGeometries() > n )
|
||||||
geomCollection->removeGeometry( n );
|
geomCollection->removeGeometry( n );
|
||||||
delete part;
|
return QgsGeometry::InvalidInput;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete part;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete part;
|
return QgsGeometry::InvalidInput;
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
added = geomCollection->addGeometry( part );
|
added = geomCollection->addGeometry( part.release() );
|
||||||
}
|
}
|
||||||
return added ? 0 : 2;
|
return added ? QgsGeometry::Success : QgsGeometry::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsGeometryEditUtils::deleteRing( QgsAbstractGeometry *geom, int ringNum, int partNum )
|
bool QgsGeometryEditUtils::deleteRing( QgsAbstractGeometry *geom, int ringNum, int partNum )
|
||||||
|
@ -24,6 +24,7 @@ class QgsVectorLayer;
|
|||||||
#define SIP_NO_FILE
|
#define SIP_NO_FILE
|
||||||
|
|
||||||
#include "qgsfeature.h"
|
#include "qgsfeature.h"
|
||||||
|
#include "qgsgeometry.h"
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
/** \ingroup core
|
/** \ingroup core
|
||||||
@ -36,19 +37,24 @@ class QgsGeometryEditUtils
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Adds interior ring (taking ownership).
|
/**
|
||||||
\returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
* Add an interior \a ring to a \a geometry.
|
||||||
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
|
* Ownership of the \a ring is transferred.
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
* \returns 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
||||||
static int addRing( QgsAbstractGeometry *geom, QgsCurve *ring );
|
* 3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring
|
||||||
|
*/
|
||||||
|
static QgsGeometry::OperationResult addRing( QgsAbstractGeometry *geometry, QgsCurve *ring SIP_TRANSFER );
|
||||||
|
|
||||||
/** Adds part to multi type geometry (taking ownership)
|
/**
|
||||||
\returns 0 in case of success, 1 if not a multigeometry, 2 if part is not a valid geometry, 3 if new polygon ring
|
* Add a \a part to multi type \a geometry.
|
||||||
not disjoint with existing polygons of the feature*/
|
* Ownership of the \a part is transferred.
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
* \returns 0 in case of success, 1 if not a multigeometry, 2 if part is not a valid geometry, 3 if new polygon ring
|
||||||
static int addPart( QgsAbstractGeometry *geom, QgsAbstractGeometry *part );
|
* not disjoint with existing polygons of the feature
|
||||||
|
*/
|
||||||
|
static QgsGeometry::OperationResult addPart( QgsAbstractGeometry *geometry, QgsAbstractGeometry *part SIP_TRANSFER );
|
||||||
|
|
||||||
/** Deletes a ring from a geometry.
|
/**
|
||||||
|
* Deletes a ring from a geometry.
|
||||||
* \returns true if delete was successful
|
* \returns true if delete was successful
|
||||||
*/
|
*/
|
||||||
static bool deleteRing( QgsAbstractGeometry *geom, int ringNum, int partNum = 0 );
|
static bool deleteRing( QgsAbstractGeometry *geom, int ringNum, int partNum = 0 );
|
||||||
|
@ -18,6 +18,7 @@ email : marco.hugentobler at sourcepole dot com
|
|||||||
|
|
||||||
#include "qgis_core.h"
|
#include "qgis_core.h"
|
||||||
#include "qgslinestring.h"
|
#include "qgslinestring.h"
|
||||||
|
#include "qgsgeometry.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
@ -31,6 +32,24 @@ class QgsAbstractGeometry;
|
|||||||
class CORE_EXPORT QgsGeometryEngine
|
class CORE_EXPORT QgsGeometryEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Success or failure of a geometry operation.
|
||||||
|
* This gived details about cause of failure.
|
||||||
|
*/
|
||||||
|
enum EngineOperationResult
|
||||||
|
{
|
||||||
|
Success = 0, //!< Operation succeeded
|
||||||
|
NothingHappened, //!< Nothing happened, without any error
|
||||||
|
MethodNotImplemented, //!< Method not implemented in geometry engine
|
||||||
|
EngineError, //!< Error occured in the geometry engine
|
||||||
|
NodedGeometryError, //!< Error occured while creating a noded geometry
|
||||||
|
InvalidBaseGeometry, //!< The geometry on which the operation occurs is not valid
|
||||||
|
InvalidInput, //!< The input is not valid
|
||||||
|
/* split */
|
||||||
|
SplitCannotSplitPoint, //!< Points cannot be split
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~QgsGeometryEngine() = default;
|
virtual ~QgsGeometryEngine() = default;
|
||||||
|
|
||||||
virtual void geometryChanged() = 0;
|
virtual void geometryChanged() = 0;
|
||||||
@ -190,17 +209,17 @@ class CORE_EXPORT QgsGeometryEngine
|
|||||||
*/
|
*/
|
||||||
virtual bool isSimple( QString *errorMsg = nullptr ) const = 0;
|
virtual bool isSimple( QString *errorMsg = nullptr ) const = 0;
|
||||||
|
|
||||||
virtual int splitGeometry( const QgsLineString &splitLine,
|
virtual QgsGeometryEngine::EngineOperationResult splitGeometry( const QgsLineString &splitLine,
|
||||||
QList<QgsAbstractGeometry *> &newGeometries,
|
QList<QgsAbstractGeometry *> &newGeometries,
|
||||||
bool topological,
|
bool topological,
|
||||||
QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr ) const
|
QgsPointSequence &topologyTestPoints, QString *errorMsg = nullptr ) const
|
||||||
{
|
{
|
||||||
Q_UNUSED( splitLine );
|
Q_UNUSED( splitLine );
|
||||||
Q_UNUSED( newGeometries );
|
Q_UNUSED( newGeometries );
|
||||||
Q_UNUSED( topological );
|
Q_UNUSED( topological );
|
||||||
Q_UNUSED( topologyTestPoints );
|
Q_UNUSED( topologyTestPoints );
|
||||||
Q_UNUSED( errorMsg );
|
Q_UNUSED( errorMsg );
|
||||||
return 2;
|
return MethodNotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
|
virtual QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const = 0 SIP_FACTORY;
|
||||||
|
@ -25,7 +25,6 @@ email : marco.hugentobler at sourcepole dot com
|
|||||||
#include "qgsmultipolygon.h"
|
#include "qgsmultipolygon.h"
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgspolygon.h"
|
#include "qgspolygon.h"
|
||||||
#include "qgsgeometry.h"
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <QtCore/qmath.h>
|
#include <QtCore/qmath.h>
|
||||||
@ -519,32 +518,32 @@ double QgsGeos::length( QString *errorMsg ) const
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeos::splitGeometry( const QgsLineString &splitLine,
|
QgsGeometryEngine::EngineOperationResult QgsGeos::splitGeometry( const QgsLineString &splitLine,
|
||||||
QList<QgsAbstractGeometry *> &newGeometries,
|
QList<QgsAbstractGeometry *> &newGeometries,
|
||||||
bool topological,
|
bool topological,
|
||||||
QgsPointSequence &topologyTestPoints,
|
QgsPointSequence &topologyTestPoints,
|
||||||
QString *errorMsg ) const
|
QString *errorMsg ) const
|
||||||
{
|
{
|
||||||
|
|
||||||
int returnCode = 0;
|
EngineOperationResult returnCode = Success;
|
||||||
if ( !mGeometry || !mGeos )
|
if ( !mGeos || !mGeometry )
|
||||||
{
|
{
|
||||||
return 1;
|
return InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
//return if this type is point/multipoint
|
//return if this type is point/multipoint
|
||||||
if ( mGeometry->dimension() == 0 )
|
if ( mGeometry->dimension() == 0 )
|
||||||
{
|
{
|
||||||
return 1; //cannot split points
|
return SplitCannotSplitPoint; //cannot split points
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !GEOSisValid_r( geosinit.ctxt, mGeos ) )
|
if ( !GEOSisValid_r( geosinit.ctxt, mGeos ) )
|
||||||
return 7;
|
return InvalidBaseGeometry;
|
||||||
|
|
||||||
//make sure splitLine is valid
|
//make sure splitLine is valid
|
||||||
if ( ( mGeometry->dimension() == 1 && splitLine.numPoints() < 1 ) ||
|
if ( ( mGeometry->dimension() == 1 && splitLine.numPoints() < 1 ) ||
|
||||||
( mGeometry->dimension() == 2 && splitLine.numPoints() < 2 ) )
|
( mGeometry->dimension() == 2 && splitLine.numPoints() < 2 ) )
|
||||||
return 1;
|
return InvalidInput;
|
||||||
|
|
||||||
newGeometries.clear();
|
newGeometries.clear();
|
||||||
GEOSGeometry *splitLineGeos = nullptr;
|
GEOSGeometry *splitLineGeos = nullptr;
|
||||||
@ -561,20 +560,22 @@ int QgsGeos::splitGeometry( const QgsLineString &splitLine,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 1;
|
return InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !GEOSisValid_r( geosinit.ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.ctxt, splitLineGeos ) )
|
if ( !GEOSisValid_r( geosinit.ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.ctxt, splitLineGeos ) )
|
||||||
{
|
{
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
|
GEOSGeom_destroy_r( geosinit.ctxt, splitLineGeos );
|
||||||
return 1;
|
return InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( topological )
|
if ( topological )
|
||||||
{
|
{
|
||||||
//find out candidate points for topological corrections
|
//find out candidate points for topological corrections
|
||||||
if ( topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) != 0 )
|
if ( !topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) )
|
||||||
return 1;
|
{
|
||||||
|
return InvalidInput; // TODO: is it really an invalid input?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//call split function depending on geometry type
|
//call split function depending on geometry type
|
||||||
@ -590,17 +591,17 @@ int QgsGeos::splitGeometry( const QgsLineString &splitLine,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 1;
|
return InvalidInput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CATCH_GEOS_WITH_ERRMSG( 2 )
|
CATCH_GEOS_WITH_ERRMSG( EngineError )
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg ) const
|
bool QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg ) const
|
||||||
{
|
{
|
||||||
//Find out the intersection points between splitLineGeos and this geometry.
|
//Find out the intersection points between splitLineGeos and this geometry.
|
||||||
//These points need to be tested for topological correctness by the calling function
|
//These points need to be tested for topological correctness by the calling function
|
||||||
@ -608,7 +609,7 @@ int QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPoint
|
|||||||
|
|
||||||
if ( !mGeos )
|
if ( !mGeos )
|
||||||
{
|
{
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -616,7 +617,7 @@ int QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPoint
|
|||||||
testPoints.clear();
|
testPoints.clear();
|
||||||
GEOSGeometry *intersectionGeom = GEOSIntersection_r( geosinit.ctxt, mGeos, splitLine );
|
GEOSGeometry *intersectionGeom = GEOSIntersection_r( geosinit.ctxt, mGeos, splitLine );
|
||||||
if ( !intersectionGeom )
|
if ( !intersectionGeom )
|
||||||
return 1;
|
return false;
|
||||||
|
|
||||||
bool simple = false;
|
bool simple = false;
|
||||||
int nIntersectGeoms = 1;
|
int nIntersectGeoms = 1;
|
||||||
@ -656,7 +657,7 @@ int QgsGeos::topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPoint
|
|||||||
}
|
}
|
||||||
CATCH_GEOS_WITH_ERRMSG( 1 )
|
CATCH_GEOS_WITH_ERRMSG( 1 )
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GEOSGeometry *QgsGeos::linePointDifference( GEOSGeometry *GEOSsplitPoint ) const
|
GEOSGeometry *QgsGeos::linePointDifference( GEOSGeometry *GEOSsplitPoint ) const
|
||||||
@ -725,22 +726,22 @@ GEOSGeometry *QgsGeos::linePointDifference( GEOSGeometry *GEOSsplitPoint ) const
|
|||||||
return asGeos( &lines, mPrecision );
|
return asGeos( &lines, mPrecision );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
|
QgsGeometryEngine::EngineOperationResult QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
|
||||||
{
|
{
|
||||||
if ( !splitLine )
|
if ( !splitLine )
|
||||||
return 2;
|
return InvalidInput;
|
||||||
|
|
||||||
if ( !mGeos )
|
if ( !mGeos )
|
||||||
return 5;
|
return InvalidBaseGeometry;
|
||||||
|
|
||||||
//first test if linestring intersects geometry. If not, return straight away
|
//first test if linestring intersects geometry. If not, return straight away
|
||||||
if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
|
if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
|
||||||
return 1;
|
return NothingHappened;
|
||||||
|
|
||||||
//check that split line has no linear intersection
|
//check that split line has no linear intersection
|
||||||
int linearIntersect = GEOSRelatePattern_r( geosinit.ctxt, mGeos, splitLine, "1********" );
|
int linearIntersect = GEOSRelatePattern_r( geosinit.ctxt, mGeos, splitLine, "1********" );
|
||||||
if ( linearIntersect > 0 )
|
if ( linearIntersect > 0 )
|
||||||
return 3;
|
return InvalidInput;
|
||||||
|
|
||||||
int splitGeomType = GEOSGeomTypeId_r( geosinit.ctxt, splitLine );
|
int splitGeomType = GEOSGeomTypeId_r( geosinit.ctxt, splitLine );
|
||||||
|
|
||||||
@ -778,25 +779,25 @@ int QgsGeos::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeom
|
|||||||
}
|
}
|
||||||
|
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, splitGeom );
|
GEOSGeom_destroy_r( geosinit.ctxt, splitGeom );
|
||||||
return 0;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
|
QgsGeometryEngine::EngineOperationResult QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const
|
||||||
{
|
{
|
||||||
if ( !splitLine )
|
if ( !splitLine )
|
||||||
return 2;
|
return InvalidInput;
|
||||||
|
|
||||||
if ( !mGeos )
|
if ( !mGeos )
|
||||||
return 5;
|
return InvalidBaseGeometry;
|
||||||
|
|
||||||
//first test if linestring intersects geometry. If not, return straight away
|
//first test if linestring intersects geometry. If not, return straight away
|
||||||
if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
|
if ( !GEOSIntersects_r( geosinit.ctxt, splitLine, mGeos ) )
|
||||||
return 1;
|
return NothingHappened;
|
||||||
|
|
||||||
//first union all the polygon rings together (to get them noded, see JTS developer guide)
|
//first union all the polygon rings together (to get them noded, see JTS developer guide)
|
||||||
GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
|
GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
|
||||||
if ( !nodedGeometry )
|
if ( !nodedGeometry )
|
||||||
return 2; //an error occurred during noding
|
return NodedGeometryError; //an error occurred during noding
|
||||||
|
|
||||||
GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.ctxt, &nodedGeometry, 1 );
|
GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.ctxt, &nodedGeometry, 1 );
|
||||||
if ( !polygons || numberOfGeometries( polygons ) == 0 )
|
if ( !polygons || numberOfGeometries( polygons ) == 0 )
|
||||||
@ -806,7 +807,7 @@ int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeo
|
|||||||
|
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
|
GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
|
||||||
|
|
||||||
return 4;
|
return InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
|
GEOSGeom_destroy_r( geosinit.ctxt, nodedGeometry );
|
||||||
@ -859,7 +860,7 @@ int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeo
|
|||||||
{
|
{
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
|
GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
|
||||||
}
|
}
|
||||||
return 1;
|
return NothingHappened;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -871,13 +872,13 @@ int QgsGeos::splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeo
|
|||||||
for ( i = 0; i < testedGeometries.size(); ++i )
|
for ( i = 0; i < testedGeometries.size(); ++i )
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
|
GEOSGeom_destroy_r( geosinit.ctxt, testedGeometries[i] );
|
||||||
|
|
||||||
return 3;
|
return InvalidBaseGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( i = 0; i < testedGeometries.size(); ++i )
|
for ( i = 0; i < testedGeometries.size(); ++i )
|
||||||
newGeometries << fromGeos( testedGeometries[i] );
|
newGeometries << fromGeos( testedGeometries[i] );
|
||||||
|
|
||||||
return 0;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
GEOSGeometry *QgsGeos::nodeGeometries( const GEOSGeometry *splitLine, const GEOSGeometry *geom )
|
GEOSGeometry *QgsGeos::nodeGeometries( const GEOSGeometry *splitLine, const GEOSGeometry *geom )
|
||||||
@ -1892,11 +1893,17 @@ QgsAbstractGeometry *QgsGeos::singleSidedBuffer( double distance, int segments,
|
|||||||
return fromGeos( geos.get() );
|
return fromGeos( geos.get() );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithLine, int *errorCode, QString *errorMsg ) const
|
QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithLine, EngineOperationResult *errorCode, QString *errorMsg ) const
|
||||||
{
|
{
|
||||||
if ( !mGeos || reshapeWithLine.numPoints() < 2 || mGeometry->dimension() == 0 )
|
if ( !mGeos || mGeometry->dimension() == 0 )
|
||||||
{
|
{
|
||||||
if ( errorCode ) { *errorCode = 1; }
|
if ( errorCode ) { *errorCode = InvalidBaseGeometry; }
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( reshapeWithLine.numPoints() < 2 )
|
||||||
|
{
|
||||||
|
if ( errorCode ) { *errorCode = InvalidInput; }
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1906,7 +1913,7 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
|
|||||||
int numGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, mGeos );
|
int numGeoms = GEOSGetNumGeometries_r( geosinit.ctxt, mGeos );
|
||||||
if ( numGeoms == -1 )
|
if ( numGeoms == -1 )
|
||||||
{
|
{
|
||||||
if ( errorCode ) { *errorCode = 1; }
|
if ( errorCode ) { *errorCode = InvalidBaseGeometry; }
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
|
GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1930,7 +1937,8 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
|
|||||||
reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos, mPrecision );
|
reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos, mPrecision );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( errorCode ) { *errorCode = 0; }
|
if ( errorCode )
|
||||||
|
*errorCode = Success;
|
||||||
QgsAbstractGeometry *reshapeResult = fromGeos( reshapedGeometry );
|
QgsAbstractGeometry *reshapeResult = fromGeos( reshapedGeometry );
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, reshapedGeometry );
|
GEOSGeom_destroy_r( geosinit.ctxt, reshapedGeometry );
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
|
GEOSGeom_destroy_r( geosinit.ctxt, reshapeLineGeos );
|
||||||
@ -1978,13 +1986,14 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
|
|||||||
delete[] newGeoms;
|
delete[] newGeoms;
|
||||||
if ( !newMultiGeom )
|
if ( !newMultiGeom )
|
||||||
{
|
{
|
||||||
if ( errorCode ) { *errorCode = 3; }
|
if ( errorCode ) { *errorCode = EngineError; }
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( reshapeTookPlace )
|
if ( reshapeTookPlace )
|
||||||
{
|
{
|
||||||
if ( errorCode ) { *errorCode = 0; }
|
if ( errorCode )
|
||||||
|
*errorCode = Success;
|
||||||
QgsAbstractGeometry *reshapedMultiGeom = fromGeos( newMultiGeom );
|
QgsAbstractGeometry *reshapedMultiGeom = fromGeos( newMultiGeom );
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
|
GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
|
||||||
return reshapedMultiGeom;
|
return reshapedMultiGeom;
|
||||||
@ -1992,7 +2001,7 @@ QgsAbstractGeometry *QgsGeos::reshapeGeometry( const QgsLineString &reshapeWithL
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
|
GEOSGeom_destroy_r( geosinit.ctxt, newMultiGeom );
|
||||||
if ( errorCode ) { *errorCode = 1; }
|
if ( errorCode ) { *errorCode = NothingHappened; }
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ email : marco.hugentobler at sourcepole dot com
|
|||||||
|
|
||||||
#include "qgis_core.h"
|
#include "qgis_core.h"
|
||||||
#include "qgsgeometryengine.h"
|
#include "qgsgeometryengine.h"
|
||||||
|
#include "qgsgeometry.h"
|
||||||
#include <geos_c.h>
|
#include <geos_c.h>
|
||||||
|
|
||||||
class QgsLineString;
|
class QgsLineString;
|
||||||
@ -106,11 +107,11 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
|
|||||||
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
|
\param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
|
||||||
\param[out] errorMsg error messages emitted, if any
|
\param[out] errorMsg error messages emitted, if any
|
||||||
\returns 0 in case of success, 1 if geometry has not been split, error else*/
|
\returns 0 in case of success, 1 if geometry has not been split, error else*/
|
||||||
int splitGeometry( const QgsLineString &splitLine,
|
EngineOperationResult splitGeometry( const QgsLineString &splitLine,
|
||||||
QList<QgsAbstractGeometry *> &newGeometries,
|
QList<QgsAbstractGeometry *> &newGeometries,
|
||||||
bool topological,
|
bool topological,
|
||||||
QgsPointSequence &topologyTestPoints,
|
QgsPointSequence &topologyTestPoints,
|
||||||
QString *errorMsg = nullptr ) const override;
|
QString *errorMsg = nullptr ) const override;
|
||||||
|
|
||||||
QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const override;
|
QgsAbstractGeometry *offsetCurve( double distance, int segments, int joinStyle, double miterLimit, QString *errorMsg = nullptr ) const override;
|
||||||
|
|
||||||
@ -131,8 +132,14 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
|
|||||||
int joinStyle, double miterLimit,
|
int joinStyle, double miterLimit,
|
||||||
QString *errorMsg = nullptr ) const;
|
QString *errorMsg = nullptr ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
QgsAbstractGeometry *reshapeGeometry( const QgsLineString &reshapeWithLine, int *errorCode, QString *errorMsg = nullptr ) const;
|
* Reshapes the geometry using a line
|
||||||
|
* @param reshapeWithLine the line used to reshape lines or polygons
|
||||||
|
* @param errorCode if specified, provides result of operation (success or reason of failure)
|
||||||
|
* @param errorMsg if specified, provides more details about failure
|
||||||
|
* @return the reshaped geometry
|
||||||
|
*/
|
||||||
|
QgsAbstractGeometry *reshapeGeometry( const QgsLineString &reshapeWithLine, EngineOperationResult *errorCode, QString *errorMsg = nullptr ) const;
|
||||||
|
|
||||||
/** Merges any connected lines in a LineString/MultiLineString geometry and
|
/** Merges any connected lines in a LineString/MultiLineString geometry and
|
||||||
* converts them to single line strings.
|
* converts them to single line strings.
|
||||||
@ -261,10 +268,10 @@ class CORE_EXPORT QgsGeos: public QgsGeometryEngine
|
|||||||
static GEOSGeometry *createGeosPolygon( const QgsAbstractGeometry *poly, double precision );
|
static GEOSGeometry *createGeosPolygon( const QgsAbstractGeometry *poly, double precision );
|
||||||
|
|
||||||
//utils for geometry split
|
//utils for geometry split
|
||||||
int topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg = nullptr ) const;
|
bool topologicalTestPointsSplit( const GEOSGeometry *splitLine, QgsPointSequence &testPoints, QString *errorMsg = nullptr ) const;
|
||||||
GEOSGeometry *linePointDifference( GEOSGeometry *GEOSsplitPoint ) const;
|
GEOSGeometry *linePointDifference( GEOSGeometry *GEOSsplitPoint ) const;
|
||||||
int splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
|
EngineOperationResult splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
|
||||||
int splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
|
EngineOperationResult splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsAbstractGeometry *> &newGeometries ) const;
|
||||||
|
|
||||||
//utils for reshape
|
//utils for reshape
|
||||||
static GEOSGeometry *reshapeLine( const GEOSGeometry *line, const GEOSGeometry *reshapeLineGeos, double precision );
|
static GEOSGeometry *reshapeLine( const GEOSGeometry *line, const GEOSGeometry *reshapeLineGeos, double precision );
|
||||||
|
@ -29,41 +29,41 @@
|
|||||||
|
|
||||||
|
|
||||||
QgsVectorLayerEditUtils::QgsVectorLayerEditUtils( QgsVectorLayer *layer )
|
QgsVectorLayerEditUtils::QgsVectorLayerEditUtils( QgsVectorLayer *layer )
|
||||||
: L( layer )
|
: mLayer( layer )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
|
bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
||||||
return false; // geometry not found
|
return false; // geometry not found
|
||||||
|
|
||||||
QgsGeometry geometry = f.geometry();
|
QgsGeometry geometry = f.geometry();
|
||||||
|
|
||||||
geometry.insertVertex( x, y, beforeVertex );
|
geometry.insertVertex( x, y, beforeVertex );
|
||||||
|
|
||||||
L->editBuffer()->changeGeometry( atFeatureId, geometry );
|
mLayer->editBuffer()->changeGeometry( atFeatureId, geometry );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsVectorLayerEditUtils::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
|
bool QgsVectorLayerEditUtils::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
||||||
return false; // geometry not found
|
return false; // geometry not found
|
||||||
|
|
||||||
QgsGeometry geometry = f.geometry();
|
QgsGeometry geometry = f.geometry();
|
||||||
|
|
||||||
geometry.insertVertex( point, beforeVertex );
|
geometry.insertVertex( point, beforeVertex );
|
||||||
|
|
||||||
L->editBuffer()->changeGeometry( atFeatureId, geometry );
|
mLayer->editBuffer()->changeGeometry( atFeatureId, geometry );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,29 +75,29 @@ bool QgsVectorLayerEditUtils::moveVertex( double x, double y, QgsFeatureId atFea
|
|||||||
|
|
||||||
bool QgsVectorLayerEditUtils::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
|
bool QgsVectorLayerEditUtils::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
||||||
return false; // geometry not found
|
return false; // geometry not found
|
||||||
|
|
||||||
QgsGeometry geometry = f.geometry();
|
QgsGeometry geometry = f.geometry();
|
||||||
|
|
||||||
geometry.moveVertex( p, atVertex );
|
geometry.moveVertex( p, atVertex );
|
||||||
|
|
||||||
L->editBuffer()->changeGeometry( atFeatureId, geometry );
|
mLayer->editBuffer()->changeGeometry( atFeatureId, geometry );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QgsVectorLayer::EditResult QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId featureId, int vertex )
|
QgsVectorLayer::EditResult QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId featureId, int vertex )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return QgsVectorLayer::InvalidLayer;
|
return QgsVectorLayer::InvalidLayer;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
||||||
return QgsVectorLayer::FetchFeatureFailed; // geometry not found
|
return QgsVectorLayer::FetchFeatureFailed; // geometry not found
|
||||||
|
|
||||||
QgsGeometry geometry = f.geometry();
|
QgsGeometry geometry = f.geometry();
|
||||||
@ -111,38 +111,38 @@ QgsVectorLayer::EditResult QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId f
|
|||||||
geometry.setGeometry( nullptr );
|
geometry.setGeometry( nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
L->editBuffer()->changeGeometry( featureId, geometry );
|
mLayer->editBuffer()->changeGeometry( featureId, geometry );
|
||||||
return !geometry.isNull() ? QgsVectorLayer::Success : QgsVectorLayer::EmptyGeometry;
|
return !geometry.isNull() ? QgsVectorLayer::Success : QgsVectorLayer::EmptyGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
|
||||||
{
|
{
|
||||||
QgsLineString *ringLine = new QgsLineString( ring );
|
QgsLineString *ringLine = new QgsLineString( ring );
|
||||||
return addRing( ringLine, targetFeatureIds, modifiedFeatureId );
|
return addRing( ringLine, targetFeatureIds, modifiedFeatureId );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds, QgsFeatureId *modifiedFeatureId )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
{
|
{
|
||||||
delete ring;
|
delete ring;
|
||||||
return 5;
|
return QgsGeometry::AddRingNotInExistingFeature;
|
||||||
}
|
}
|
||||||
|
|
||||||
int addRingReturnCode = 5; //default: return code for 'ring not inserted'
|
QgsGeometry::OperationResult addRingReturnCode = QgsGeometry::AddRingNotInExistingFeature; //default: return code for 'ring not inserted'
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
|
|
||||||
QgsFeatureIterator fit;
|
QgsFeatureIterator fit;
|
||||||
if ( !targetFeatureIds.isEmpty() )
|
if ( !targetFeatureIds.isEmpty() )
|
||||||
{
|
{
|
||||||
//check only specified features
|
//check only specified features
|
||||||
fit = L->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
|
fit = mLayer->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//check all intersecting features
|
//check all intersecting features
|
||||||
QgsRectangle bBox = ring->boundingBox();
|
QgsRectangle bBox = ring->boundingBox();
|
||||||
fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//find first valid feature we can add the ring to
|
//find first valid feature we can add the ring to
|
||||||
@ -156,21 +156,22 @@ int QgsVectorLayerEditUtils::addRing( QgsCurve *ring, const QgsFeatureIds &targe
|
|||||||
|
|
||||||
addRingReturnCode = g.addRing( static_cast< QgsCurve * >( ring->clone() ) );
|
addRingReturnCode = g.addRing( static_cast< QgsCurve * >( ring->clone() ) );
|
||||||
if ( addRingReturnCode == 0 )
|
if ( addRingReturnCode == 0 )
|
||||||
{
|
if ( addRingReturnCode == QgsGeometry::Success )
|
||||||
L->editBuffer()->changeGeometry( f.id(), g );
|
{
|
||||||
if ( modifiedFeatureId )
|
mLayer->editBuffer()->changeGeometry( f.id(), g );
|
||||||
*modifiedFeatureId = f.id();
|
if ( modifiedFeatureId )
|
||||||
|
*modifiedFeatureId = f.id();
|
||||||
|
|
||||||
//setModified( true, true );
|
//setModified( true, true );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete ring;
|
delete ring;
|
||||||
return addRingReturnCode;
|
return addRingReturnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::addPart( const QList<QgsPointXY> &points, QgsFeatureId featureId )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::addPart( const QList<QgsPointXY> &points, QgsFeatureId featureId )
|
||||||
{
|
{
|
||||||
QgsPointSequence l;
|
QgsPointSequence l;
|
||||||
for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd(); ++it )
|
for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd(); ++it )
|
||||||
@ -180,16 +181,16 @@ int QgsVectorLayerEditUtils::addPart( const QList<QgsPointXY> &points, QgsFeatur
|
|||||||
return addPart( l, featureId );
|
return addPart( l, featureId );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::addPart( const QgsPointSequence &points, QgsFeatureId featureId )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::addPart( const QgsPointSequence &points, QgsFeatureId featureId )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 6;
|
return QgsGeometry::AddPartSelectedGeometryNotFound;
|
||||||
|
|
||||||
QgsGeometry geometry;
|
QgsGeometry geometry;
|
||||||
bool firstPart = false;
|
bool firstPart = false;
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
|
||||||
return 6; //not found
|
return QgsGeometry::AddPartSelectedGeometryNotFound; //not found
|
||||||
|
|
||||||
if ( !f.hasGeometry() )
|
if ( !f.hasGeometry() )
|
||||||
{
|
{
|
||||||
@ -201,30 +202,30 @@ int QgsVectorLayerEditUtils::addPart( const QgsPointSequence &points, QgsFeature
|
|||||||
geometry = f.geometry();
|
geometry = f.geometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
int errorCode = geometry.addPart( points, L->geometryType() ) ;
|
QgsGeometry::OperationResult errorCode = geometry.addPart( points, mLayer->geometryType() ) ;
|
||||||
if ( errorCode == 0 )
|
if ( errorCode == QgsGeometry::Success )
|
||||||
{
|
{
|
||||||
if ( firstPart && QgsWkbTypes::isSingleType( L->wkbType() )
|
if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
|
||||||
&& L->dataProvider()->doesStrictFeatureTypeCheck() )
|
&& mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
|
||||||
{
|
{
|
||||||
//convert back to single part if required by layer
|
//convert back to single part if required by layer
|
||||||
geometry.convertToSingleType();
|
geometry.convertToSingleType();
|
||||||
}
|
}
|
||||||
L->editBuffer()->changeGeometry( featureId, geometry );
|
mLayer->editBuffer()->changeGeometry( featureId, geometry );
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::addPart( QgsCurve *ring, QgsFeatureId featureId )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::addPart( QgsCurve *ring, QgsFeatureId featureId )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 6;
|
return QgsGeometry::AddPartSelectedGeometryNotFound;
|
||||||
|
|
||||||
QgsGeometry geometry;
|
QgsGeometry geometry;
|
||||||
bool firstPart = false;
|
bool firstPart = false;
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
|
||||||
return 6; //not found
|
return QgsGeometry::AddPartSelectedGeometryNotFound;
|
||||||
|
|
||||||
if ( !f.hasGeometry() )
|
if ( !f.hasGeometry() )
|
||||||
{
|
{
|
||||||
@ -236,16 +237,16 @@ int QgsVectorLayerEditUtils::addPart( QgsCurve *ring, QgsFeatureId featureId )
|
|||||||
geometry = f.geometry();
|
geometry = f.geometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
int errorCode = geometry.addPart( ring, L->geometryType() ) ;
|
QgsGeometry::OperationResult errorCode = geometry.addPart( ring, mLayer->geometryType() ) ;
|
||||||
if ( errorCode == 0 )
|
if ( errorCode == QgsGeometry::Success )
|
||||||
{
|
{
|
||||||
if ( firstPart && QgsWkbTypes::isSingleType( L->wkbType() )
|
if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
|
||||||
&& L->dataProvider()->doesStrictFeatureTypeCheck() )
|
&& mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
|
||||||
{
|
{
|
||||||
//convert back to single part if required by layer
|
//convert back to single part if required by layer
|
||||||
geometry.convertToSingleType();
|
geometry.convertToSingleType();
|
||||||
}
|
}
|
||||||
L->editBuffer()->changeGeometry( featureId, geometry );
|
mLayer->editBuffer()->changeGeometry( featureId, geometry );
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
@ -253,11 +254,11 @@ int QgsVectorLayerEditUtils::addPart( QgsCurve *ring, QgsFeatureId featureId )
|
|||||||
|
|
||||||
int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
|
int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.hasGeometry() )
|
||||||
return 1; //geometry not found
|
return 1; //geometry not found
|
||||||
|
|
||||||
QgsGeometry geometry = f.geometry();
|
QgsGeometry geometry = f.geometry();
|
||||||
@ -265,30 +266,30 @@ int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx
|
|||||||
int errorCode = geometry.translate( dx, dy );
|
int errorCode = geometry.translate( dx, dy );
|
||||||
if ( errorCode == 0 )
|
if ( errorCode == 0 )
|
||||||
{
|
{
|
||||||
L->editBuffer()->changeGeometry( featureId, geometry );
|
mLayer->editBuffer()->changeGeometry( featureId, geometry );
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 4;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
|
|
||||||
QgsFeatureList newFeatures; //store all the newly created features
|
QgsFeatureList newFeatures; //store all the newly created features
|
||||||
double xMin, yMin, xMax, yMax;
|
double xMin, yMin, xMax, yMax;
|
||||||
QgsRectangle bBox; //bounding box of the split line
|
QgsRectangle bBox; //bounding box of the split line
|
||||||
int returnCode = 0;
|
QgsGeometry::OperationResult returnCode = QgsGeometry::Success;
|
||||||
int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
|
QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
|
||||||
int numberOfSplitFeatures = 0;
|
int numberOfSplitFeatures = 0;
|
||||||
|
|
||||||
QgsFeatureIterator features;
|
QgsFeatureIterator features;
|
||||||
const QgsFeatureIds selectedIds = L->selectedFeatureIds();
|
const QgsFeatureIds selectedIds = mLayer->selectedFeatureIds();
|
||||||
|
|
||||||
if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
|
if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
|
||||||
{
|
{
|
||||||
features = L->getSelectedFeatures();
|
features = mLayer->getSelectedFeatures();
|
||||||
}
|
}
|
||||||
else //else consider all the feature that intersect the bounding box of the split line
|
else //else consider all the feature that intersect the bounding box of the split line
|
||||||
{
|
{
|
||||||
@ -301,7 +302,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bBox.isEmpty() )
|
if ( bBox.isEmpty() )
|
||||||
@ -321,7 +322,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine,
|
|||||||
{
|
{
|
||||||
//If we have a single point, we still create a non-null box
|
//If we have a single point, we still create a non-null box
|
||||||
double bufferDistance = 0.000001;
|
double bufferDistance = 0.000001;
|
||||||
if ( L->crs().isGeographic() )
|
if ( mLayer->crs().isGeographic() )
|
||||||
bufferDistance = 0.00000001;
|
bufferDistance = 0.00000001;
|
||||||
bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
|
bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
|
||||||
bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
|
bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
|
||||||
@ -330,7 +331,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
features = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsFeature feat;
|
QgsFeature feat;
|
||||||
@ -344,16 +345,16 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine,
|
|||||||
QList<QgsPointXY> topologyTestPoints;
|
QList<QgsPointXY> topologyTestPoints;
|
||||||
QgsGeometry featureGeom = feat.geometry();
|
QgsGeometry featureGeom = feat.geometry();
|
||||||
splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
|
splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
|
||||||
if ( splitFunctionReturn == 0 )
|
if ( splitFunctionReturn == QgsGeometry::Success )
|
||||||
{
|
{
|
||||||
//change this geometry
|
//change this geometry
|
||||||
L->editBuffer()->changeGeometry( feat.id(), featureGeom );
|
mLayer->editBuffer()->changeGeometry( feat.id(), featureGeom );
|
||||||
|
|
||||||
//insert new features
|
//insert new features
|
||||||
for ( int i = 0; i < newGeometries.size(); ++i )
|
for ( int i = 0; i < newGeometries.size(); ++i )
|
||||||
{
|
{
|
||||||
QgsFeature f = QgsVectorLayerUtils::createFeature( L, newGeometries.at( i ), feat.attributes().toMap() );
|
QgsFeature f = QgsVectorLayerUtils::createFeature( mLayer, newGeometries.at( i ), feat.attributes().toMap() );
|
||||||
L->editBuffer()->addFeature( f );
|
mLayer->editBuffer()->addFeature( f );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( topologicalEditing )
|
if ( topologicalEditing )
|
||||||
@ -366,7 +367,7 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine,
|
|||||||
}
|
}
|
||||||
++numberOfSplitFeatures;
|
++numberOfSplitFeatures;
|
||||||
}
|
}
|
||||||
else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
|
else if ( splitFunctionReturn != QgsGeometry::Success && splitFunctionReturn != QgsGeometry::NothingHappened ) // i.e. no split but no error occurred
|
||||||
{
|
{
|
||||||
returnCode = splitFunctionReturn;
|
returnCode = splitFunctionReturn;
|
||||||
}
|
}
|
||||||
@ -376,28 +377,28 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPointXY> &splitLine,
|
|||||||
{
|
{
|
||||||
//There is a selection but no feature has been split.
|
//There is a selection but no feature has been split.
|
||||||
//Maybe user forgot that only the selected features are split
|
//Maybe user forgot that only the selected features are split
|
||||||
returnCode = 4;
|
returnCode = QgsGeometry::NothingHappened;
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing )
|
QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 4;
|
return QgsGeometry::InvalidBaseGeometry;
|
||||||
|
|
||||||
double xMin, yMin, xMax, yMax;
|
double xMin, yMin, xMax, yMax;
|
||||||
QgsRectangle bBox; //bounding box of the split line
|
QgsRectangle bBox; //bounding box of the split line
|
||||||
int returnCode = 0;
|
QgsGeometry::OperationResult returnCode = QgsGeometry::Success;
|
||||||
int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
|
QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
|
||||||
int numberOfSplitParts = 0;
|
int numberOfSplitParts = 0;
|
||||||
|
|
||||||
QgsFeatureIterator fit;
|
QgsFeatureIterator fit;
|
||||||
|
|
||||||
if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
|
if ( mLayer->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
|
||||||
{
|
{
|
||||||
fit = L->getSelectedFeatures();
|
fit = mLayer->getSelectedFeatures();
|
||||||
}
|
}
|
||||||
else //else consider all the feature that intersect the bounding box of the split line
|
else //else consider all the feature that intersect the bounding box of the split line
|
||||||
{
|
{
|
||||||
@ -410,7 +411,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 1;
|
return QgsGeometry::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bBox.isEmpty() )
|
if ( bBox.isEmpty() )
|
||||||
@ -430,7 +431,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
{
|
{
|
||||||
//If we have a single point, we still create a non-null box
|
//If we have a single point, we still create a non-null box
|
||||||
double bufferDistance = 0.000001;
|
double bufferDistance = 0.000001;
|
||||||
if ( L->crs().isGeographic() )
|
if ( mLayer->crs().isGeographic() )
|
||||||
bufferDistance = 0.00000001;
|
bufferDistance = 0.00000001;
|
||||||
bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
|
bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
|
||||||
bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
|
bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
|
||||||
@ -439,7 +440,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
int addPartRet = 0;
|
int addPartRet = 0;
|
||||||
@ -469,7 +470,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
|
|
||||||
if ( !addPartRet )
|
if ( !addPartRet )
|
||||||
{
|
{
|
||||||
L->editBuffer()->changeGeometry( feat.id(), featureGeom );
|
mLayer->editBuffer()->changeGeometry( feat.id(), featureGeom );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -489,7 +490,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
L->editBuffer()->changeGeometry( feat.id(), featureGeom );
|
mLayer->editBuffer()->changeGeometry( feat.id(), featureGeom );
|
||||||
|
|
||||||
if ( topologicalEditing )
|
if ( topologicalEditing )
|
||||||
{
|
{
|
||||||
@ -507,11 +508,11 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( numberOfSplitParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
|
if ( numberOfSplitParts == 0 && mLayer->selectedFeatureCount() > 0 && returnCode == 0 )
|
||||||
{
|
{
|
||||||
//There is a selection but no feature has been split.
|
//There is a selection but no feature has been split.
|
||||||
//Maybe user forgot that only the selected features are split
|
//Maybe user forgot that only the selected features are split
|
||||||
returnCode = 4;
|
returnCode = QgsGeometry::NothingHappened;
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
@ -520,7 +521,7 @@ int QgsVectorLayerEditUtils::splitParts( const QList<QgsPointXY> &splitLine, boo
|
|||||||
|
|
||||||
int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsGeometry &geom )
|
int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsGeometry &geom )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ( geom.isNull() )
|
if ( geom.isNull() )
|
||||||
@ -628,18 +629,18 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsGeometry &geom )
|
|||||||
|
|
||||||
int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPointXY &p )
|
int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPointXY &p )
|
||||||
{
|
{
|
||||||
if ( !L->isSpatial() )
|
if ( !mLayer->isSpatial() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
double segmentSearchEpsilon = L->crs().isGeographic() ? 1e-12 : 1e-8;
|
double segmentSearchEpsilon = mLayer->crs().isGeographic() ? 1e-12 : 1e-8;
|
||||||
|
|
||||||
//work with a tolerance because coordinate projection may introduce some rounding
|
//work with a tolerance because coordinate projection may introduce some rounding
|
||||||
double threshold = 0.0000001;
|
double threshold = 0.0000001;
|
||||||
if ( L->crs().mapUnits() == QgsUnitTypes::DistanceMeters )
|
if ( mLayer->crs().mapUnits() == QgsUnitTypes::DistanceMeters )
|
||||||
{
|
{
|
||||||
threshold = 0.001;
|
threshold = 0.001;
|
||||||
}
|
}
|
||||||
else if ( L->crs().mapUnits() == QgsUnitTypes::DistanceFeet )
|
else if ( mLayer->crs().mapUnits() == QgsUnitTypes::DistanceFeet )
|
||||||
{
|
{
|
||||||
threshold = 0.0001;
|
threshold = 0.0001;
|
||||||
}
|
}
|
||||||
@ -649,7 +650,7 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPointXY &p )
|
|||||||
double sqrSnappingTolerance = threshold * threshold;
|
double sqrSnappingTolerance = threshold * threshold;
|
||||||
|
|
||||||
QgsFeature f;
|
QgsFeature f;
|
||||||
QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest()
|
QgsFeatureIterator fit = mLayer->getFeatures( QgsFeatureRequest()
|
||||||
.setFilterRect( searchRect )
|
.setFilterRect( searchRect )
|
||||||
.setFlags( QgsFeatureRequest::ExactIntersect )
|
.setFlags( QgsFeatureRequest::ExactIntersect )
|
||||||
.setSubsetOfAttributes( QgsAttributeList() ) );
|
.setSubsetOfAttributes( QgsAttributeList() ) );
|
||||||
@ -685,7 +686,7 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPointXY &p )
|
|||||||
if ( sqrDistVertexSnap < sqrSnappingTolerance )
|
if ( sqrDistVertexSnap < sqrSnappingTolerance )
|
||||||
continue; // the vertex already exists - do not insert it
|
continue; // the vertex already exists - do not insert it
|
||||||
|
|
||||||
if ( !L->insertVertex( p.x(), p.y(), fid, segmentAfterVertex ) )
|
if ( !mLayer->insertVertex( p.x(), p.y(), fid, segmentAfterVertex ) )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( "failed to insert topo point" );
|
QgsDebugMsg( "failed to insert topo point" );
|
||||||
}
|
}
|
||||||
@ -695,11 +696,11 @@ int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsPointXY &p )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
|
bool QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const
|
||||||
{
|
{
|
||||||
if ( list.size() < 1 )
|
if ( list.size() < 1 )
|
||||||
{
|
{
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmin = std::numeric_limits<double>::max();
|
xmin = std::numeric_limits<double>::max();
|
||||||
@ -727,5 +728,5 @@ int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPointXY> &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,8 @@
|
|||||||
#include "qgis_core.h"
|
#include "qgis_core.h"
|
||||||
#include "qgis.h"
|
#include "qgis.h"
|
||||||
#include "qgsfeature.h"
|
#include "qgsfeature.h"
|
||||||
|
|
||||||
#include "qgsvectorlayer.h"
|
|
||||||
#include "qgsgeometry.h"
|
#include "qgsgeometry.h"
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
|
||||||
class QgsCurve;
|
class QgsCurve;
|
||||||
|
|
||||||
@ -66,68 +65,40 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
|||||||
QgsVectorLayer::EditResult deleteVertex( QgsFeatureId featureId, int vertex );
|
QgsVectorLayer::EditResult deleteVertex( QgsFeatureId featureId, int vertex );
|
||||||
|
|
||||||
/** Adds a ring to polygon/multipolygon features
|
/** Adds a ring to polygon/multipolygon features
|
||||||
* \param ring ring to add
|
* @param ring ring to add
|
||||||
* \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
|
* @param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
|
||||||
* all intersecting features are tested and the ring is added to the first valid feature.
|
* all intersecting features are tested and the ring is added to the first valid feature.
|
||||||
* \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
|
* @param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
|
||||||
* \returns
|
* @return OperationResult result code: success or reason of failure
|
||||||
* 0 in case of success,
|
|
||||||
* 1 problem with feature type,
|
|
||||||
* 2 ring not closed,
|
|
||||||
* 3 ring not valid,
|
|
||||||
* 4 ring crosses existing rings,
|
|
||||||
* 5 no feature found where ring can be inserted
|
|
||||||
*/
|
*/
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
QgsGeometry::OperationResult addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr );
|
||||||
int addRing( const QList<QgsPointXY> &ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr );
|
|
||||||
|
|
||||||
/** Adds a ring to polygon/multipolygon features
|
/**
|
||||||
* \param ring ring to add
|
* Adds a ring to polygon/multipolygon features
|
||||||
* \param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
|
* @param ring ring to add
|
||||||
|
* @param targetFeatureIds if specified, only these features will be the candidates for adding a ring. Otherwise
|
||||||
* all intersecting features are tested and the ring is added to the first valid feature.
|
* all intersecting features are tested and the ring is added to the first valid feature.
|
||||||
* \param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
|
* @param modifiedFeatureId if specified, feature ID for feature that ring was added to will be stored in this parameter
|
||||||
* \returns
|
* @return OperationResult result code: success or reason of failure
|
||||||
* 0 in case of success,
|
* @note available in python bindings as addCurvedRing
|
||||||
* 1 problem with feature type,
|
|
||||||
* 2 ring not closed,
|
|
||||||
* 3 ring not valid,
|
|
||||||
* 4 ring crosses existing rings,
|
|
||||||
* 5 no feature found where ring can be inserted
|
|
||||||
* \note available in Python bindings as addCurvedRing
|
|
||||||
*/
|
*/
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
QgsGeometry::OperationResult addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr ) SIP_PYNAME( addCurvedRing );
|
||||||
int addRing( QgsCurve *ring, const QgsFeatureIds &targetFeatureIds = QgsFeatureIds(), QgsFeatureId *modifiedFeatureId = nullptr ) SIP_PYNAME( addCurvedRing );
|
|
||||||
|
|
||||||
/** Adds a new part polygon to a multipart feature
|
/**
|
||||||
* \returns
|
* Adds a new part polygon to a multipart feature
|
||||||
* 0 in case of success,
|
* @returns QgsGeometry::OperationResult a result code: success or reason of failure
|
||||||
* 1 if selected feature is not multipart,
|
|
||||||
* 2 if ring is not a valid geometry,
|
|
||||||
* 3 if new polygon ring not disjoint with existing rings,
|
|
||||||
* 4 if no feature was selected,
|
|
||||||
* 5 if several features are selected,
|
|
||||||
* 6 if selected geometry not found
|
|
||||||
*/
|
*/
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
QgsGeometry::OperationResult addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
|
||||||
int addPart( const QList<QgsPointXY> &ring, QgsFeatureId featureId );
|
|
||||||
|
|
||||||
/** Adds a new part polygon to a multipart feature
|
/**
|
||||||
* \returns
|
* Adds a new part polygon to a multipart feature
|
||||||
* 0 in case of success,
|
* @returns QgsGeometry::OperationResult a result code: success or reason of failure
|
||||||
* 1 if selected feature is not multipart,
|
* @note available in python bindings as addPartV2
|
||||||
* 2 if ring is not a valid geometry,
|
|
||||||
* 3 if new polygon ring not disjoint with existing rings,
|
|
||||||
* 4 if no feature was selected,
|
|
||||||
* 5 if several features are selected,
|
|
||||||
* 6 if selected geometry not found
|
|
||||||
* \note available in Python bindings as addPartV2
|
|
||||||
*/
|
*/
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
QgsGeometry::OperationResult addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
|
||||||
int addPart( const QgsPointSequence &ring, QgsFeatureId featureId );
|
|
||||||
|
|
||||||
//! \note available in Python bindings as addCurvedPart
|
// @note available in python bindings as addCurvedPart
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
QgsGeometry::OperationResult addPart( QgsCurve *ring, QgsFeatureId featureId ) SIP_PYNAME( addCurvedPart );
|
||||||
int addPart( QgsCurve *ring, QgsFeatureId featureId ) SIP_PYNAME( addCurvedPart );
|
|
||||||
|
|
||||||
/** Translates feature by dx, dy
|
/** Translates feature by dx, dy
|
||||||
* \param featureId id of the feature to translate
|
* \param featureId id of the feature to translate
|
||||||
@ -145,7 +116,7 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
|||||||
* 4 if there is a selection but no feature split
|
* 4 if there is a selection but no feature split
|
||||||
*/
|
*/
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
||||||
int splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
QgsGeometry::OperationResult splitParts( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
||||||
|
|
||||||
/** Splits features cut by the given line
|
/** Splits features cut by the given line
|
||||||
* \param splitLine line that splits the layer features
|
* \param splitLine line that splits the layer features
|
||||||
@ -155,7 +126,7 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
|||||||
* 4 if there is a selection but no feature split
|
* 4 if there is a selection but no feature split
|
||||||
*/
|
*/
|
||||||
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
// TODO QGIS 3.0 returns an enum instead of a magic constant
|
||||||
int splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
QgsGeometry::OperationResult splitFeatures( const QList<QgsPointXY> &splitLine, bool topologicalEditing = false );
|
||||||
|
|
||||||
/** Adds topological points for every vertex of the geometry.
|
/** Adds topological points for every vertex of the geometry.
|
||||||
* \param geom the geometry where each vertex is added to segments of other features
|
* \param geom the geometry where each vertex is added to segments of other features
|
||||||
@ -173,15 +144,15 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
|||||||
*/
|
*/
|
||||||
int addTopologicalPoints( const QgsPointXY &p );
|
int addTopologicalPoints( const QgsPointXY &p );
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/** Little helper function that gives bounding box from a list of points.
|
|
||||||
\returns 0 in case of success */
|
|
||||||
int boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QgsVectorLayer *L = nullptr;
|
/**
|
||||||
|
* Little helper function that gives bounding box from a list of points.
|
||||||
|
* \returns True in case of success
|
||||||
|
*/
|
||||||
|
bool boundingBoxFromPointList( const QList<QgsPointXY> &list, double &xmin, double &ymin, double &xmax, double &ymax ) const;
|
||||||
|
|
||||||
|
QgsVectorLayer *mLayer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QGSVECTORLAYEREDITUTILS_H
|
#endif // QGSVECTORLAYEREDITUTILS_H
|
||||||
|
@ -1423,14 +1423,14 @@ class TestQgsGeometry(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
|
|
||||||
polyline = QgsGeometry.fromPolyline(points[0])
|
polyline = QgsGeometry.fromPolyline(points[0])
|
||||||
self.assertEqual(polyline.addPoints(points[1][0:1]), 2, "addPoints with one point line unexpectedly succeeded.")
|
self.assertEqual(polyline.addPoints(points[1][0:1]), QgsGeometry.InvalidInput, "addPoints with one point line unexpectedly succeeded.")
|
||||||
self.assertEqual(polyline.addPoints(points[1][0:2]), 0, "addPoints with two point line failed.")
|
self.assertEqual(polyline.addPoints(points[1][0:2]), QgsGeometry.Success, "addPoints with two point line failed.")
|
||||||
expwkt = "MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 0, 3 1))"
|
expwkt = "MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 0, 3 1))"
|
||||||
wkt = polyline.exportToWkt()
|
wkt = polyline.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
|
|
||||||
polyline = QgsGeometry.fromPolyline(points[0])
|
polyline = QgsGeometry.fromPolyline(points[0])
|
||||||
self.assertEqual(polyline.addPoints(points[1]), 0, "addPoints with %d point line failed." % len(points[1]))
|
self.assertEqual(polyline.addPoints(points[1]), QgsGeometry.Success, "addPoints with %d point line failed." % len(points[1]))
|
||||||
expwkt = "MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 0, 3 1, 5 1, 5 0, 6 0))"
|
expwkt = "MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 0, 3 1, 5 1, 5 0, 6 0))"
|
||||||
wkt = polyline.exportToWkt()
|
wkt = polyline.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
@ -1439,7 +1439,7 @@ class TestQgsGeometry(unittest.TestCase):
|
|||||||
polyline = QgsGeometry.fromPolyline(points[0])
|
polyline = QgsGeometry.fromPolyline(points[0])
|
||||||
polyline.geometry().addZValue(4.0)
|
polyline.geometry().addZValue(4.0)
|
||||||
points2 = [QgsPoint(p[0], p[1], 3.0, wkbType=QgsWkbTypes.PointZ) for p in points[1]]
|
points2 = [QgsPoint(p[0], p[1], 3.0, wkbType=QgsWkbTypes.PointZ) for p in points[1]]
|
||||||
self.assertEqual(polyline.addPointsV2(points2), 0)
|
self.assertEqual(polyline.addPointsV2(points2), QgsGeometry.Success)
|
||||||
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))"
|
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))"
|
||||||
wkt = polyline.exportToWkt()
|
wkt = polyline.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
@ -1456,12 +1456,12 @@ class TestQgsGeometry(unittest.TestCase):
|
|||||||
|
|
||||||
polygon = QgsGeometry.fromPolygon(points[0])
|
polygon = QgsGeometry.fromPolygon(points[0])
|
||||||
|
|
||||||
self.assertEqual(polygon.addPoints(points[1][0][0:1]), 2, "addPoints with one point ring unexpectedly succeeded.")
|
self.assertEqual(polygon.addPoints(points[1][0][0:1]), QgsGeometry.InvalidInput, "addPoints with one point ring unexpectedly succeeded.")
|
||||||
self.assertEqual(polygon.addPoints(points[1][0][0:2]), 2, "addPoints with two point ring unexpectedly succeeded.")
|
self.assertEqual(polygon.addPoints(points[1][0][0:2]), QgsGeometry.InvalidInput, "addPoints with two point ring unexpectedly succeeded.")
|
||||||
self.assertEqual(polygon.addPoints(points[1][0][0:3]), 2, "addPoints with unclosed three point ring unexpectedly succeeded.")
|
self.assertEqual(polygon.addPoints(points[1][0][0:3]), QgsGeometry.InvalidInput, "addPoints with unclosed three point ring unexpectedly succeeded.")
|
||||||
self.assertEqual(polygon.addPoints([QgsPointXY(4, 0), QgsPointXY(5, 0), QgsPointXY(4, 0)]), 2, "addPoints with 'closed' three point ring unexpectedly succeeded.")
|
self.assertEqual(polygon.addPoints([QgsPointXY(4, 0), QgsPointXY(5, 0), QgsPointXY(4, 0)]), QgsGeometry.InvalidInput, "addPoints with 'closed' three point ring unexpectedly succeeded.")
|
||||||
|
|
||||||
self.assertEqual(polygon.addPoints(points[1][0]), 0, "addPoints failed")
|
self.assertEqual(polygon.addPoints(points[1][0]), QgsGeometry.Success, "addPoints failed")
|
||||||
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)))"
|
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)))"
|
||||||
wkt = polygon.exportToWkt()
|
wkt = polygon.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
@ -1469,13 +1469,13 @@ class TestQgsGeometry(unittest.TestCase):
|
|||||||
mp = QgsGeometry.fromMultiPolygon(points[:1])
|
mp = QgsGeometry.fromMultiPolygon(points[:1])
|
||||||
p = QgsGeometry.fromPolygon(points[1])
|
p = QgsGeometry.fromPolygon(points[1])
|
||||||
|
|
||||||
self.assertEqual(mp.addPartGeometry(p), 0)
|
self.assertEqual(mp.addPartGeometry(p), QgsGeometry.Success)
|
||||||
wkt = mp.exportToWkt()
|
wkt = mp.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
|
|
||||||
mp = QgsGeometry.fromMultiPolygon(points[:1])
|
mp = QgsGeometry.fromMultiPolygon(points[:1])
|
||||||
mp2 = QgsGeometry.fromMultiPolygon(points[1:])
|
mp2 = QgsGeometry.fromMultiPolygon(points[1:])
|
||||||
self.assertEqual(mp.addPartGeometry(mp2), 0)
|
self.assertEqual(mp.addPartGeometry(mp2), QgsGeometry.Success)
|
||||||
wkt = mp.exportToWkt()
|
wkt = mp.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
|
|
||||||
@ -1483,7 +1483,7 @@ class TestQgsGeometry(unittest.TestCase):
|
|||||||
polygon = QgsGeometry.fromPolygon(points[0])
|
polygon = QgsGeometry.fromPolygon(points[0])
|
||||||
polygon.geometry().addZValue(4.0)
|
polygon.geometry().addZValue(4.0)
|
||||||
points2 = [QgsPoint(pi[0], pi[1], 3.0, wkbType=QgsWkbTypes.PointZ) for pi in points[1][0]]
|
points2 = [QgsPoint(pi[0], pi[1], 3.0, wkbType=QgsWkbTypes.PointZ) for pi in points[1][0]]
|
||||||
self.assertEqual(polygon.addPointsV2(points2), 0)
|
self.assertEqual(polygon.addPointsV2(points2), QgsGeometry.Success)
|
||||||
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)))"
|
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)))"
|
||||||
wkt = polygon.exportToWkt()
|
wkt = polygon.exportToWkt()
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
@ -1492,38 +1492,38 @@ class TestQgsGeometry(unittest.TestCase):
|
|||||||
empty = QgsGeometry()
|
empty = QgsGeometry()
|
||||||
# if not default type specified, addPart should fail
|
# if not default type specified, addPart should fail
|
||||||
result = empty.addPoints([QgsPointXY(4, 0)])
|
result = empty.addPoints([QgsPointXY(4, 0)])
|
||||||
assert result != 0, 'Got return code {}'.format(result)
|
assert result != QgsGeometry.Success, 'Got return code {}'.format(result)
|
||||||
result = empty.addPoints([QgsPointXY(4, 0)], QgsWkbTypes.PointGeometry)
|
result = empty.addPoints([QgsPointXY(4, 0)], QgsWkbTypes.PointGeometry)
|
||||||
self.assertEqual(result, 0, 'Got return code {}'.format(result))
|
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
|
||||||
wkt = empty.exportToWkt()
|
wkt = empty.exportToWkt()
|
||||||
expwkt = 'MultiPoint ((4 0))'
|
expwkt = 'MultiPoint ((4 0))'
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
result = empty.addPoints([QgsPointXY(5, 1)])
|
result = empty.addPoints([QgsPointXY(5, 1)])
|
||||||
self.assertEqual(result, 0, 'Got return code {}'.format(result))
|
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
|
||||||
wkt = empty.exportToWkt()
|
wkt = empty.exportToWkt()
|
||||||
expwkt = 'MultiPoint ((4 0),(5 1))'
|
expwkt = 'MultiPoint ((4 0),(5 1))'
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
# next try with lines
|
# next try with lines
|
||||||
empty = QgsGeometry()
|
empty = QgsGeometry()
|
||||||
result = empty.addPoints(points[0][0], QgsWkbTypes.LineGeometry)
|
result = empty.addPoints(points[0][0], QgsWkbTypes.LineGeometry)
|
||||||
self.assertEqual(result, 0, 'Got return code {}'.format(result))
|
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
|
||||||
wkt = empty.exportToWkt()
|
wkt = empty.exportToWkt()
|
||||||
expwkt = 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0))'
|
expwkt = 'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0))'
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
result = empty.addPoints(points[1][0])
|
result = empty.addPoints(points[1][0])
|
||||||
self.assertEqual(result, 0, 'Got return code {}'.format(result))
|
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
|
||||||
wkt = empty.exportToWkt()
|
wkt = empty.exportToWkt()
|
||||||
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))'
|
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))'
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
# finally try with polygons
|
# finally try with polygons
|
||||||
empty = QgsGeometry()
|
empty = QgsGeometry()
|
||||||
result = empty.addPoints(points[0][0], QgsWkbTypes.PolygonGeometry)
|
result = empty.addPoints(points[0][0], QgsWkbTypes.PolygonGeometry)
|
||||||
self.assertEqual(result, 0, 'Got return code {}'.format(result))
|
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
|
||||||
wkt = empty.exportToWkt()
|
wkt = empty.exportToWkt()
|
||||||
expwkt = 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)))'
|
expwkt = 'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)))'
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
result = empty.addPoints(points[1][0])
|
result = empty.addPoints(points[1][0])
|
||||||
self.assertEqual(result, 0, 'Got return code {}'.format(result))
|
self.assertEqual(result, QgsGeometry.Success, 'Got return code {}'.format(result))
|
||||||
wkt = empty.exportToWkt()
|
wkt = empty.exportToWkt()
|
||||||
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)))'
|
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)))'
|
||||||
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
assert compareWkt(expwkt, wkt), "Expected:\n%s\nGot:\n%s\n" % (expwkt, wkt)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user