[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