Skip to content

Commit 97e3154

Browse files
author
mhugent
committedSep 19, 2008
Fix for problem where splitting was slow for large polygons and with topological editing enabled (bug #1161)
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@9351 c8812cc2-4d05-0410-92ff-de0c093fc19c

File tree

4 files changed

+93
-24
lines changed

4 files changed

+93
-24
lines changed
 

‎python/core/qgsgeometry.sip

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,14 @@ not disjoint with existing polygons of the feature*/
192192
@return 0 in case of success*/
193193
int translate(double dx, double dy);
194194

195-
/**Splits this geometry according to a given line. Note that the geometry is only splitted once. If there are several intersections
196-
between geometry and splitLine, only the first one is considered.
195+
/**Splits this geometry according to a given line. Note that the geometry is only splitted once. If there are several intersections
196+
between geometry and splitLine, only the first one is considered.
197197
@param splitLine the line that splits the geometry
198198
@param newGeometrys OUT: list of new geometries that have been created with the split
199-
@return 0 in case of success, which means the geometry has been split in two parts, \
200-
1 if line intersects multiple times but only one split could be done, \
201-
2 if intersection too complicated to proceed (several polygon intersections), \ \
202-
else other error*/
203-
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries);
199+
@param topological true if topological editing is enabled
200+
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
201+
@return 0 in case of success, 1 if geometry has not been split, error else*/
202+
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints);
204203

205204
/**Changes this geometry such that it does not intersect the other geometry
206205
@param other geometry that should not be intersect

‎src/core/qgsgeometry.cpp

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3119,7 +3119,7 @@ int QgsGeometry::transform( QgsCoordinateTransform& ct )
31193119
return 0;
31203120
}
31213121

3122-
int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries )
3122+
int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints )
31233123
{
31243124
int returnCode = 0;
31253125

@@ -3156,7 +3156,16 @@ int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeome
31563156
return 1;
31573157
}
31583158

3159-
//for line/multiline: call splitLinearGeometry
3159+
if(topological)
3160+
{
3161+
//find out candidate points for topological corrections
3162+
if(topologicalTestPointsSplit(splitLineGeos, topologyTestPoints) != 0)
3163+
{
3164+
return 1;
3165+
}
3166+
}
3167+
3168+
//call split function depending on geometry type
31603169
if ( vectorType() == QGis::Line )
31613170
{
31623171
returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
@@ -4885,6 +4894,64 @@ int QgsGeometry::splitPolygonGeometry( GEOSGeometry* splitLine, QList<QgsGeometr
48854894
return 0;
48864895
}
48874896

4897+
int QgsGeometry::topologicalTestPointsSplit( const GEOSGeometry* splitLine, QList<QgsPoint>& testPoints) const
4898+
{
4899+
//Find out the intersection points between splitLineGeos and this geometry.
4900+
//These points need to be tested for topological correctness by the calling function
4901+
//if topological editing is enabled
4902+
4903+
testPoints.clear();
4904+
GEOSGeometry* intersectionGeom = GEOSIntersection(mGeos, splitLine);
4905+
if(intersectionGeom == NULL)
4906+
{
4907+
return 1;
4908+
}
4909+
4910+
bool simple = false;
4911+
int nIntersectGeoms = 1;
4912+
if(GEOSGeomTypeId(intersectionGeom) == (GEOS_LINESTRING) || GEOSGeomTypeId(intersectionGeom) == (GEOS_POINT))
4913+
{
4914+
simple = true;
4915+
}
4916+
4917+
if(!simple)
4918+
{
4919+
nIntersectGeoms = GEOSGetNumGeometries(intersectionGeom);
4920+
}
4921+
4922+
for(int i = 0; i < nIntersectGeoms; ++i)
4923+
{
4924+
GEOSGeometry* currentIntersectGeom;
4925+
if(simple)
4926+
{
4927+
currentIntersectGeom = intersectionGeom;
4928+
}
4929+
else
4930+
{
4931+
currentIntersectGeom = GEOSGetGeometryN(intersectionGeom, i);
4932+
}
4933+
4934+
GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq(currentIntersectGeom);
4935+
unsigned int sequenceSize = 0;
4936+
double x, y;
4937+
if(GEOSCoordSeq_getSize(lineSequence, &sequenceSize) != 0)
4938+
{
4939+
for(int i = 0; i < sequenceSize; ++i)
4940+
{
4941+
if(GEOSCoordSeq_getX(lineSequence, i, &x) != 0)
4942+
{
4943+
if(GEOSCoordSeq_getY(lineSequence, i, &y) != 0)
4944+
{
4945+
testPoints.push_back(QgsPoint(x, y));
4946+
}
4947+
}
4948+
}
4949+
}
4950+
}
4951+
GEOSGeom_destroy(intersectionGeom);
4952+
return 0;
4953+
}
4954+
48884955
GEOSGeometry *QgsGeometry::nodeGeometries( const GEOSGeometry *splitLine, GEOSGeometry *geom ) const
48894956
{
48904957
if ( !splitLine || !geom )

‎src/core/qgsgeometry.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,10 @@ class CORE_EXPORT QgsGeometry
242242
between geometry and splitLine, only the first one is considered.
243243
@param splitLine the line that splits the geometry
244244
@param newGeometrys OUT: list of new geometries that have been created with the split
245+
@param topological true if topological editing is enabled
246+
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
245247
@return 0 in case of success, 1 if geometry has not been split, error else*/
246-
int splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries );
248+
int splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints);
247249

248250
/**Changes this geometry such that it does not intersect the other geometry
249251
@param other geometry that should not be intersect
@@ -398,12 +400,13 @@ class CORE_EXPORT QgsGeometry
398400
@splitLine the line that splits the feature
399401
@newGeometry new geometry if splitting was successful
400402
@return 0 in case of success, 1 if geometry has not been split, error else*/
401-
int splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries );
403+
int splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries);
402404
/**Splits polygon/multipolygon geometries
403405
@return 0 in case of success, 1 if geometry has not been split, error else*/
404406
int splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries );
405-
/**Finds the vertices next to point where the line is split. If it is split at a vertex, beforeVertex
406-
and afterVertex are the same*/
407+
/**Finds out the points that need to be tested for topological correctnes if this geometry will be split
408+
@return 0 in case of success*/
409+
int topologicalTestPointsSplit( const GEOSGeometry* splitLine, QList<QgsPoint>& testPoints) const;
407410

408411
/**Nodes together a split line and a (multi-) polygon geometry in a multilinestring
409412
@return the noded multiline geometry or 0 in case of error. The calling function takes ownership of the node geometry*/

‎src/core/qgsvectorlayer.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,8 +1722,9 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
17221722
for ( ; select_it != featureList.end(); ++select_it )
17231723
{
17241724
QList<QgsGeometry*> newGeometries;
1725+
QList<QgsPoint> topologyTestPoints;
17251726
QgsGeometry* newGeometry = 0;
1726-
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries );
1727+
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints);
17271728
if ( splitFunctionReturn == 0 )
17281729
{
17291730
//change this geometry
@@ -1737,18 +1738,17 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
17371738
newFeature.setGeometry( newGeometry );
17381739
newFeature.setAttributeMap( select_it->attributeMap() );
17391740
newFeatures.append( newFeature );
1740-
if ( topologicalEditing ) //add topological points for new feature
1741-
{
1742-
addTopologicalPoints( newGeometry );
1743-
}
17441741
}
1745-
setModified( true, true );
17461742

1747-
//add topological points for this geometry if necessary
1748-
if ( topologicalEditing )
1749-
{
1750-
addTopologicalPoints( select_it->geometry() );
1751-
}
1743+
setModified( true, true );
1744+
if(topologicalEditing)
1745+
{
1746+
QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
1747+
for(; topol_it != topologyTestPoints.constEnd(); ++topol_it)
1748+
{
1749+
addTopologicalPoints(*topol_it);
1750+
}
1751+
}
17521752
}
17531753
else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
17541754
{

0 commit comments

Comments
 (0)
Please sign in to comment.