Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mhugent committed Sep 19, 2008
1 parent 4a9d90f commit 97e3154
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 24 deletions.
13 changes: 6 additions & 7 deletions python/core/qgsgeometry.sip
Expand Up @@ -192,15 +192,14 @@ not disjoint with existing polygons of the feature*/
@return 0 in case of success*/
int translate(double dx, double dy);

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

/**Changes this geometry such that it does not intersect the other geometry
@param other geometry that should not be intersect
Expand Down
71 changes: 69 additions & 2 deletions src/core/qgsgeometry.cpp
Expand Up @@ -3119,7 +3119,7 @@ int QgsGeometry::transform( QgsCoordinateTransform& ct )
return 0;
}

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

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

//for line/multiline: call splitLinearGeometry
if(topological)
{
//find out candidate points for topological corrections
if(topologicalTestPointsSplit(splitLineGeos, topologyTestPoints) != 0)
{
return 1;
}
}

//call split function depending on geometry type
if ( vectorType() == QGis::Line )
{
returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
Expand Down Expand Up @@ -4885,6 +4894,64 @@ int QgsGeometry::splitPolygonGeometry( GEOSGeometry* splitLine, QList<QgsGeometr
return 0;
}

int QgsGeometry::topologicalTestPointsSplit( const GEOSGeometry* splitLine, QList<QgsPoint>& testPoints) const
{
//Find out the intersection points between splitLineGeos and this geometry.
//These points need to be tested for topological correctness by the calling function
//if topological editing is enabled

testPoints.clear();
GEOSGeometry* intersectionGeom = GEOSIntersection(mGeos, splitLine);
if(intersectionGeom == NULL)
{
return 1;
}

bool simple = false;
int nIntersectGeoms = 1;
if(GEOSGeomTypeId(intersectionGeom) == (GEOS_LINESTRING) || GEOSGeomTypeId(intersectionGeom) == (GEOS_POINT))
{
simple = true;
}

if(!simple)
{
nIntersectGeoms = GEOSGetNumGeometries(intersectionGeom);
}

for(int i = 0; i < nIntersectGeoms; ++i)
{
GEOSGeometry* currentIntersectGeom;
if(simple)
{
currentIntersectGeom = intersectionGeom;
}
else
{
currentIntersectGeom = GEOSGetGeometryN(intersectionGeom, i);
}

GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq(currentIntersectGeom);
unsigned int sequenceSize = 0;
double x, y;
if(GEOSCoordSeq_getSize(lineSequence, &sequenceSize) != 0)
{
for(int i = 0; i < sequenceSize; ++i)
{
if(GEOSCoordSeq_getX(lineSequence, i, &x) != 0)
{
if(GEOSCoordSeq_getY(lineSequence, i, &y) != 0)
{
testPoints.push_back(QgsPoint(x, y));
}
}
}
}
}
GEOSGeom_destroy(intersectionGeom);
return 0;
}

GEOSGeometry *QgsGeometry::nodeGeometries( const GEOSGeometry *splitLine, GEOSGeometry *geom ) const
{
if ( !splitLine || !geom )
Expand Down
11 changes: 7 additions & 4 deletions src/core/qgsgeometry.h
Expand Up @@ -242,8 +242,10 @@ class CORE_EXPORT QgsGeometry
between geometry and splitLine, only the first one is considered.
@param splitLine the line that splits the geometry
@param newGeometrys OUT: list of new geometries that have been created with the split
@param topological true if topological editing is enabled
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
@return 0 in case of success, 1 if geometry has not been split, error else*/
int splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries );
int splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints);

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

/**Nodes together a split line and a (multi-) polygon geometry in a multilinestring
@return the noded multiline geometry or 0 in case of error. The calling function takes ownership of the node geometry*/
Expand Down
22 changes: 11 additions & 11 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -1722,8 +1722,9 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
for ( ; select_it != featureList.end(); ++select_it )
{
QList<QgsGeometry*> newGeometries;
QList<QgsPoint> topologyTestPoints;
QgsGeometry* newGeometry = 0;
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries );
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints);
if ( splitFunctionReturn == 0 )
{
//change this geometry
Expand All @@ -1737,18 +1738,17 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
newFeature.setGeometry( newGeometry );
newFeature.setAttributeMap( select_it->attributeMap() );
newFeatures.append( newFeature );
if ( topologicalEditing ) //add topological points for new feature
{
addTopologicalPoints( newGeometry );
}
}
setModified( true, true );

//add topological points for this geometry if necessary
if ( topologicalEditing )
{
addTopologicalPoints( select_it->geometry() );
}
setModified( true, true );
if(topologicalEditing)
{
QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
for(; topol_it != topologyTestPoints.constEnd(); ++topol_it)
{
addTopologicalPoints(*topol_it);
}
}
}
else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
{
Expand Down

0 comments on commit 97e3154

Please sign in to comment.