[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