Skip to content

Commit 414609e

Browse files
author
mhugent
committedJan 20, 2008
Changed feature splitting mechanism such that it is possible to generate several new features with one split
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@8008 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

5 files changed

+215
-826
lines changed

5 files changed

+215
-826
lines changed
 

‎src/app/qgsmaptoolsplitfeatures.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,10 @@ void QgsMapToolSplitFeatures::canvasReleaseEvent(QMouseEvent * e)
7979
//bring up dialog if a split was not possible (polygon) or only done once (line)
8080
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
8181
int returnCode = vlayer->splitFeatures(mCaptureList, topologicalEditing);
82-
if(returnCode == 1)
82+
if(returnCode != 0)
8383
{
8484
//several intersections but only one split (most likely line)
85-
QMessageBox::warning(0, tr("Intersection problem"), tr("One or more geometries are intersected several times by the split lines. Those geometries are only split once."));
86-
}
87-
else if(returnCode == 2)
88-
{
89-
//too complex intersection (most likely several polygon intersections)
90-
QMessageBox::warning(0, tr("Intersection problem"), tr("One or more geometries cannot be split because the intersection is too complex. Note that polygon splits can only be done if the split line intersects the polygon once. Also inner polygon rings cannot be split"));
85+
QMessageBox::warning(0, tr("Split error"), tr("An error occured during feature splitting"));
9186
}
9287

9388
mCaptureList.clear();

‎src/core/qgsgeometry.cpp

Lines changed: 174 additions & 765 deletions
Large diffs are not rendered by default.

‎src/core/qgsgeometry.h

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,23 @@ email : morb at ozemail dot com dot au
2727
#if GEOS_VERSION_MAJOR < 3
2828
#define GEOS_GEOM geos
2929
#define GEOS_IO geos
30+
#define GEOS_LINEMERGE geos
31+
#define GEOS_POLYGONIZE geos
3032
#define GEOS_UTIL geos
3133
#define GEOS_SIZE_T int
3234
#define COORD_SEQ_FACTORY DefaultCoordinateSequenceFactory
35+
#include "geos/opPolygonize.h"
36+
#include "geos/opLinemerge.h"
3337
#else
3438
#define GEOS_GEOM geos::geom
3539
#define GEOS_IO geos::io
40+
#define GEOS_LINEMERGE geos::operation::linemerge
41+
#define GEOS_POLYGONIZE geos::operation::polygonize
3642
#define GEOS_UTIL geos::util
3743
#define GEOS_SIZE_T size_t
3844
#define COORD_SEQ_FACTORY CoordinateArraySequenceFactory
45+
#include "geos/operation/polygonize/Polygonizer.h"
46+
#include "geos/operation/linemerge/LineMerger.h"
3947
#endif
4048

4149
#include "qgspoint.h"
@@ -256,10 +264,7 @@ not disjoint with existing polygons of the feature*/
256264
between geometry and splitLine, only the first one is considered.
257265
@param splitLine the line that splits the geometry
258266
@param newGeometrys OUT: list of new geometries that have been created with the split
259-
@return 0 in case of success, which means the geometry has been split in two parts, \
260-
1 if line intersects multiple times but only one split could be done, \
261-
2 if intersection too complicated to proceed (several polygon intersections), \ \
262-
else other error*/
267+
@return 0 in case of success, 1 if geometry has not been split, error else*/
263268
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries);
264269

265270
/**Changes this geometry such that it does not intersect the other geometry
@@ -412,44 +417,19 @@ not disjoint with existing polygons of the feature*/
412417
/**Splits line/multiline geometries
413418
@splitLine the line that splits the feature
414419
@newGeometry new geometry if splitting was successful
415-
@return 0 in case of success, 1: splitLine intersects several times but only one split \
416-
can be done, else other errors*/
417-
int splitLinearGeometry(GEOS_GEOM::LineString* splitLine, QgsGeometry** newGeometry);
420+
@return 0 in case of success, 1 if geometry has not been split, error else*/
421+
int splitLinearGeometry(GEOS_GEOM::LineString* splitLine, QList<QgsGeometry*>& newGeometries);
418422
/**Splits polygon/multipolygon geometries
419-
@return 0 in case of success, 1 no split because of too complicated intersection, \
420-
else other errors*/
421-
int splitPolygonGeometry(GEOS_GEOM::LineString* splitLine, QgsGeometry** newGeometry);
423+
@return 0 in case of success, 1 if geometry has not been split, error else*/
424+
int splitPolygonGeometry(GEOS_GEOM::LineString* splitLine, QList<QgsGeometry*>& newGeometries);
422425
/**Finds the vertices next to point where the line is split. If it is split at a vertex, beforeVertex
423426
and afterVertex are the same*/
424-
int findVerticesNextToSplit(const QgsPoint& splitPoint, int& beforeVertex, int& afterVertex);
425-
/**Test if a point is a geometry vertex
426-
@param p point to test
427-
@param vertexNr vertex number (if point is a vertex)
428-
@return true if p is vertex of this geometry*/
429-
bool vertexContainedInGeometry(const QgsPoint& p, int& vertexNr);
430-
/**Splits this geometry into two lines*/
431-
int splitThisLine(const QgsPoint& splitPoint, int beforeVertex, int afterVertex, QgsGeometry** newGeometry);
432-
/**Splits this geometry into two multilines*/
433-
int splitThisMultiline(const QgsPoint& splitPoint, int beforeVertex, int afterVertex, QgsGeometry** newGeometry);
434-
/**Splits this geometry into two polygons
435-
@return 0 in case of success, 1 error because split intersects inner ring, else other error*/
436-
int splitThisPolygon(const GEOS_GEOM::CoordinateSequence* splitLine, int beforeVertex1, int afterVertex1, \
437-
int beforeVertex2, int afterVertex2, QgsGeometry** newGeometry);
438-
/**Splits this geometry into two multipolygons
439-
@return 0 in case of success, 1 error because split intersects inner ring, else other error*/
440-
int splitThisMultiPolygon(const GEOS_GEOM::CoordinateSequence* splitLine, int beforeVertex1, int afterVertex1, \
441-
int beforeVertex2, int afterVertex2, QgsGeometry** newGeometry);
442-
/**splits a QgsPolyline object. Used by 'splitThisLine' and 'splitThisMultiLine'*/
443-
int splitQgsPolyline(const QgsPoint& splitPoint, int beforeVertex, int afterVertex, const QgsPolyline* origLine, QgsPolyline** changedLine, QgsPolyline** newLine) const;
444-
/**split a QgsPolygon object. Used by 'splitThisPolygon' and 'splitThisMultiPolygon'
445-
@return 0 in case of success, 1 error because split intersects inner ring, else other error*/
446-
int splitQgsPolygon(const GEOS_GEOM::CoordinateSequence* splitLine, int beforeVertex1, int afterVertex1, \
447-
int beforeVertex2, int afterVertex2, const QgsPolygon* origPoly, QgsPolygon** changedPoly, QgsPolygon** newPoly) const;
448-
449-
/**Converts a polyline (that represents a polygon boundary or a ring) to geos polygon.
450-
The caller function takes ownership of the created object.
451-
@return the converted polygon or 0 in case of error*/
452-
GEOS_GEOM::Polygon* polylineToGeosPolygon(const QgsPolyline& line) const;
427+
428+
/**Nodes together a split line and a (multi-) polygon geometry in a multilinestring
429+
@return the noded multiline geometry or 0 in case of error. The calling function takes ownership of the node geometry*/
430+
GEOS_GEOM::Geometry* nodeGeometries(const GEOS_GEOM::LineString* splitLine, const GEOS_GEOM::Geometry* poly) const;
431+
432+
int mergeGeometriesMultiTypeSplit(QList<GEOS_GEOM::Geometry*>& splitResult);
453433

454434
/** return point from wkb */
455435
QgsPoint asPoint(unsigned char*& ptr, bool hasZValue);

‎src/core/qgsvectorlayer.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,12 +1710,12 @@ int QgsVectorLayer::splitFeatures(const QList<QgsPoint>& splitLine, bool topolog
17101710
}
17111711
else
17121712
{
1713-
return 3;
1713+
return 1;
17141714
}
17151715

17161716
if(bBox.isEmpty())
17171717
{
1718-
return 4;
1718+
return 2;
17191719
}
17201720

17211721
QList<QgsFeature> featureList;
@@ -1727,29 +1727,35 @@ int QgsVectorLayer::splitFeatures(const QList<QgsPoint>& splitLine, bool topolog
17271727
QList<QgsGeometry*> newGeometries;
17281728
QgsGeometry* newGeometry = 0;
17291729
splitFunctionReturn = select_it->geometry()->splitGeometry(splitLine, newGeometries);
1730-
if(splitFunctionReturn < 2)
1730+
if(splitFunctionReturn == 0)
17311731
{
17321732
//change this geometry
17331733
mChangedGeometries.insert(select_it->featureId(), *(select_it->geometry()));
17341734

1735-
//insert new feature
1736-
newGeometry = newGeometries.at(0);
1737-
QgsFeature newFeature;
1738-
newFeature.setGeometry(newGeometry);
1739-
newFeature.setAttributeMap(select_it->attributeMap());
1740-
newFeatures.append(newFeature);
1735+
//insert new features
1736+
for(int i = 0; i < newGeometries.size(); ++i)
1737+
{
1738+
newGeometry = newGeometries.at(i);
1739+
QgsFeature newFeature;
1740+
newFeature.setGeometry(newGeometry);
1741+
newFeature.setAttributeMap(select_it->attributeMap());
1742+
newFeatures.append(newFeature);
1743+
if(topologicalEditing) //add topological points for new feature
1744+
{
1745+
addTopologicalPoints(newGeometry);
1746+
}
1747+
}
17411748
setModified(true, true);
17421749

1743-
//add topological points if necessary
1750+
//add topological points for this geometry if necessary
17441751
if(topologicalEditing)
17451752
{
17461753
addTopologicalPoints(select_it->geometry());
1747-
addTopologicalPoints(newGeometry);
17481754
}
17491755
}
1750-
if(splitFunctionReturn > 0 && splitFunctionReturn < 3)
1756+
else if(splitFunctionReturn > 1) //1 means no split but also no error
17511757
{
1752-
returnCode = splitFunctionReturn;
1758+
returnCode = 3;
17531759
}
17541760
}
17551761

‎src/core/qgsvectorlayer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,7 @@ existing rings, 5 no feature found where ring can be inserted*/
252252
/**Splits features cut by the given line
253253
@param splitLine line that splits the layer features
254254
@param topologicalEditing true if topological editing is enabled
255-
@return 0 in case of success, 1 if several intersections but only 1 split done, \
256-
2 if intersection too complex to be handled, else other error*/
255+
@return 0 in case of success*/
257256
int splitFeatures(const QList<QgsPoint>& splitLine, bool topologicalEditing = false);
258257

259258
/**Changes the specified geometry such that it has no intersections with other \

0 commit comments

Comments
 (0)
Please sign in to comment.