[QGIS Commit] r12767 - in trunk/qgis/src: app core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Fri Jan 15 06:11:52 EST 2010


Author: jef
Date: 2010-01-15 06:11:51 -0500 (Fri, 15 Jan 2010)
New Revision: 12767

Modified:
   trunk/qgis/src/app/qgsmaptoolnodetool.cpp
   trunk/qgis/src/core/qgsgeometry.cpp
   trunk/qgis/src/core/qgsgeometry.h
Log:
more geometry validity checks

Modified: trunk/qgis/src/app/qgsmaptoolnodetool.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolnodetool.cpp	2010-01-15 09:14:37 UTC (rev 12766)
+++ trunk/qgis/src/app/qgsmaptoolnodetool.cpp	2010-01-15 11:11:51 UTC (rev 12767)
@@ -899,6 +899,11 @@
 SelectionFeature::~SelectionFeature()
 {
   deleteVertexMap();
+
+  while ( !mGeomErrorMarkers.isEmpty() )
+  {
+    delete mGeomErrorMarkers.takeFirst();
+  }
 }
 
 void SelectionFeature::updateFeature()
@@ -1040,6 +1045,7 @@
   if ( count != 0 && ( !wasValid || isValid ) )
   {
     mVlayer->endEditCommand();
+    validateGeometry( f.geometry() );
   }
   else
   {
@@ -1151,11 +1157,6 @@
     VertexEntry entry = mVertexMap.takeLast();
     delete entry.vertexMarker;
   }
-
-  while ( !mGeomErrorMarkers.isEmpty() )
-  {
-    delete mGeomErrorMarkers.takeFirst();
-  }
 }
 
 bool SelectionFeature::isSelected( int vertexNr )

Modified: trunk/qgis/src/core/qgsgeometry.cpp
===================================================================
--- trunk/qgis/src/core/qgsgeometry.cpp	2010-01-15 09:14:37 UTC (rev 12766)
+++ trunk/qgis/src/core/qgsgeometry.cpp	2010-01-15 11:11:51 UTC (rev 12767)
@@ -6324,27 +6324,46 @@
   return true;
 }
 
-bool ringIntersectsRing( const QgsPolyline &ring0, const QgsPolyline &ring1 )
+void QgsGeometry::checkRingIntersections( QList<Error> &errors,
+    int p0, int i0, const QgsPolyline &ring0,
+    int p1, int i1, const QgsPolyline &ring1 )
 {
-  bool inside = false;
-  bool outside = false;
+  for ( int i = 0; i < ring0.size() - 1; i++ )
+  {
+    QgsVector v = ring0[i+1] - ring0[i];
 
-  for ( int i = 0; i < ring0.size(); i++ )
-  {
-    if ( pointInRing( ring1, ring0[i] ) )
+    for ( int j = 0; j < ring1.size() - 1; j++ )
     {
-      inside = true;
+      QgsVector w = ring1[j+1] - ring1[j];
+
+      QgsPoint s;
+      if ( intersectLines( ring0[i], v, ring1[j], w, s ) )
+      {
+        double d = -distLine2Point( ring0[i], v.perpVector(), s );
+
+        if ( d >= 0 && d <= v.length() )
+        {
+          d = -distLine2Point( ring1[j], w.perpVector(), s );
+          if ( d >= 0 && d <= w.length() )
+          {
+            QString msg = QObject::tr( "segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" )
+                          .arg( i0 ).arg( i ).arg( p0 )
+                          .arg( i1 ).arg( j ).arg( p1 )
+                          .arg( s.toString() );
+            QgsDebugMsg( msg );
+            errors << Error( msg, s );
+            if ( errors.size() > 100 )
+            {
+              QString msg = QObject::tr( "stopping validation after more than 100 errors" );
+              QgsDebugMsg( msg );
+              errors << Error( msg );
+              return;
+            }
+          }
+        }
+      }
     }
-    else
-    {
-      outside = true;
-    }
-
-    if ( outside && inside )
-      return true;
   }
-
-  return false;
 }
 
 void QgsGeometry::validatePolyline( QList<Error> &errors, int i, const QgsPolyline &line )
@@ -6406,6 +6425,7 @@
 
 void QgsGeometry::validatePolygon( QList<Error> &errors, int idx, const QgsPolygon &polygon )
 {
+  // check if holes are inside polygon
   for ( int i = 1; i < polygon.size(); i++ )
   {
     if ( !ringInRing( polygon[i], polygon[0] ) )
@@ -6416,19 +6436,16 @@
     }
   }
 
+  // check holes for intersections
   for ( int i = 1; i < polygon.size(); i++ )
   {
     for ( int j = i + 1; j < polygon.size(); j++ )
     {
-      if ( ringIntersectsRing( polygon[i], polygon[j] ) )
-      {
-        QString msg = QObject::tr( "interior rings %1 and %2 of polygon %3 intersect" ).arg( i ).arg( j ).arg( idx );
-        QgsDebugMsg( msg );
-        errors << Error( msg );
-      }
+      checkRingIntersections( errors, idx, i, polygon[i], idx, j, polygon[j] );
     }
   }
 
+  // check if rings are self-intersecting
   for ( int i = 0; i < polygon.size(); i++ )
   {
     validatePolyline( errors, i, polygon[i] );
@@ -6473,7 +6490,28 @@
     {
       QgsMultiPolygon mp = asMultiPolygon();
       for ( int i = 0; i < mp.size(); i++ )
+      {
         validatePolygon( errors, i, mp[i] );
+      }
+
+      for ( int i = 0; i < mp.size(); i++ )
+      {
+        for ( int j = i + 1;  j < mp.size(); j++ )
+        {
+          if ( ringInRing( mp[i][0], mp[j][0] ) )
+          {
+            errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) );
+          }
+          else if ( ringInRing( mp[j][0], mp[i][0] ) )
+          {
+            errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) );
+          }
+          else
+          {
+            checkRingIntersections( errors, i, 0, mp[i][0], j, 0, mp[j][0] );
+          }
+        }
+      }
     }
     break;
 

Modified: trunk/qgis/src/core/qgsgeometry.h
===================================================================
--- trunk/qgis/src/core/qgsgeometry.h	2010-01-15 09:14:37 UTC (rev 12766)
+++ trunk/qgis/src/core/qgsgeometry.h	2010-01-15 11:11:51 UTC (rev 12767)
@@ -511,6 +511,10 @@
     /** return polygon from wkb */
     QgsPolygon asPolygon( unsigned char*& ptr, bool hasZValue );
 
+    void checkRingIntersections( QList<Error> &errors,
+                                 int p0, int i0, const QgsPolyline &ring0,
+                                 int p1, int i1, const QgsPolyline &ring1 );
+
     void validatePolyline( QList<Error> &errors, int i, const QgsPolyline &polygon );
     void validatePolygon( QList<Error> &errors, int i, const QgsPolygon &polygon );
 



More information about the QGIS-commit mailing list