[QGIS Commit] r9351 - in trunk/qgis: python/core src/core
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Fri Sep 19 02:54:12 EDT 2008
Author: mhugent
Date: 2008-09-19 02:54:12 -0400 (Fri, 19 Sep 2008)
New Revision: 9351
Modified:
trunk/qgis/python/core/qgsgeometry.sip
trunk/qgis/src/core/qgsgeometry.cpp
trunk/qgis/src/core/qgsgeometry.h
trunk/qgis/src/core/qgsvectorlayer.cpp
Log:
Fix for problem where splitting was slow for large polygons and with topological editing enabled (bug #1161)
Modified: trunk/qgis/python/core/qgsgeometry.sip
===================================================================
--- trunk/qgis/python/core/qgsgeometry.sip 2008-09-18 18:07:52 UTC (rev 9350)
+++ trunk/qgis/python/core/qgsgeometry.sip 2008-09-19 06:54:12 UTC (rev 9351)
@@ -192,15 +192,14 @@
@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
Modified: trunk/qgis/src/core/qgsgeometry.cpp
===================================================================
--- trunk/qgis/src/core/qgsgeometry.cpp 2008-09-18 18:07:52 UTC (rev 9350)
+++ trunk/qgis/src/core/qgsgeometry.cpp 2008-09-19 06:54:12 UTC (rev 9351)
@@ -3119,7 +3119,7 @@
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;
@@ -3156,7 +3156,16 @@
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 );
@@ -4885,6 +4894,64 @@
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 )
Modified: trunk/qgis/src/core/qgsgeometry.h
===================================================================
--- trunk/qgis/src/core/qgsgeometry.h 2008-09-18 18:07:52 UTC (rev 9350)
+++ trunk/qgis/src/core/qgsgeometry.h 2008-09-19 06:54:12 UTC (rev 9351)
@@ -242,8 +242,10 @@
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
@@ -398,12 +400,13 @@
@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*/
Modified: trunk/qgis/src/core/qgsvectorlayer.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.cpp 2008-09-18 18:07:52 UTC (rev 9350)
+++ trunk/qgis/src/core/qgsvectorlayer.cpp 2008-09-19 06:54:12 UTC (rev 9351)
@@ -1722,8 +1722,9 @@
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
@@ -1737,18 +1738,17 @@
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() );
- }
+ 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
{
More information about the QGIS-commit
mailing list