Skip to content

Commit 10b080d

Browse files
author
jef
committedJan 15, 2010
more geometry validity checks
git-svn-id: http://svn.osgeo.org/qgis/trunk@12767 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 45fcf55 commit 10b080d

File tree

3 files changed

+70
-27
lines changed

3 files changed

+70
-27
lines changed
 

‎src/app/qgsmaptoolnodetool.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,11 @@ SelectionFeature::SelectionFeature()
899899
SelectionFeature::~SelectionFeature()
900900
{
901901
deleteVertexMap();
902+
903+
while ( !mGeomErrorMarkers.isEmpty() )
904+
{
905+
delete mGeomErrorMarkers.takeFirst();
906+
}
902907
}
903908

904909
void SelectionFeature::updateFeature()
@@ -1040,6 +1045,7 @@ void SelectionFeature::deleteSelectedVertexes()
10401045
if ( count != 0 && ( !wasValid || isValid ) )
10411046
{
10421047
mVlayer->endEditCommand();
1048+
validateGeometry( f.geometry() );
10431049
}
10441050
else
10451051
{
@@ -1151,11 +1157,6 @@ void SelectionFeature::deleteVertexMap()
11511157
VertexEntry entry = mVertexMap.takeLast();
11521158
delete entry.vertexMarker;
11531159
}
1154-
1155-
while ( !mGeomErrorMarkers.isEmpty() )
1156-
{
1157-
delete mGeomErrorMarkers.takeFirst();
1158-
}
11591160
}
11601161

11611162
bool SelectionFeature::isSelected( int vertexNr )

‎src/core/qgsgeometry.cpp

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6324,27 +6324,46 @@ static bool ringInRing( const QgsPolyline &inside, const QgsPolyline &outside )
63246324
return true;
63256325
}
63266326

6327-
bool ringIntersectsRing( const QgsPolyline &ring0, const QgsPolyline &ring1 )
6327+
void QgsGeometry::checkRingIntersections( QList<Error> &errors,
6328+
int p0, int i0, const QgsPolyline &ring0,
6329+
int p1, int i1, const QgsPolyline &ring1 )
63286330
{
6329-
bool inside = false;
6330-
bool outside = false;
6331-
6332-
for ( int i = 0; i < ring0.size(); i++ )
6331+
for ( int i = 0; i < ring0.size() - 1; i++ )
63336332
{
6334-
if ( pointInRing( ring1, ring0[i] ) )
6335-
{
6336-
inside = true;
6337-
}
6338-
else
6333+
QgsVector v = ring0[i+1] - ring0[i];
6334+
6335+
for ( int j = 0; j < ring1.size() - 1; j++ )
63396336
{
6340-
outside = true;
6341-
}
6337+
QgsVector w = ring1[j+1] - ring1[j];
63426338

6343-
if ( outside && inside )
6344-
return true;
6345-
}
6339+
QgsPoint s;
6340+
if ( intersectLines( ring0[i], v, ring1[j], w, s ) )
6341+
{
6342+
double d = -distLine2Point( ring0[i], v.perpVector(), s );
63466343

6347-
return false;
6344+
if ( d >= 0 && d <= v.length() )
6345+
{
6346+
d = -distLine2Point( ring1[j], w.perpVector(), s );
6347+
if ( d >= 0 && d <= w.length() )
6348+
{
6349+
QString msg = QObject::tr( "segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" )
6350+
.arg( i0 ).arg( i ).arg( p0 )
6351+
.arg( i1 ).arg( j ).arg( p1 )
6352+
.arg( s.toString() );
6353+
QgsDebugMsg( msg );
6354+
errors << Error( msg, s );
6355+
if ( errors.size() > 100 )
6356+
{
6357+
QString msg = QObject::tr( "stopping validation after more than 100 errors" );
6358+
QgsDebugMsg( msg );
6359+
errors << Error( msg );
6360+
return;
6361+
}
6362+
}
6363+
}
6364+
}
6365+
}
6366+
}
63486367
}
63496368

63506369
void QgsGeometry::validatePolyline( QList<Error> &errors, int i, const QgsPolyline &line )
@@ -6406,6 +6425,7 @@ void QgsGeometry::validatePolyline( QList<Error> &errors, int i, const QgsPolyli
64066425

64076426
void QgsGeometry::validatePolygon( QList<Error> &errors, int idx, const QgsPolygon &polygon )
64086427
{
6428+
// check if holes are inside polygon
64096429
for ( int i = 1; i < polygon.size(); i++ )
64106430
{
64116431
if ( !ringInRing( polygon[i], polygon[0] ) )
@@ -6416,19 +6436,16 @@ void QgsGeometry::validatePolygon( QList<Error> &errors, int idx, const QgsPolyg
64166436
}
64176437
}
64186438

6439+
// check holes for intersections
64196440
for ( int i = 1; i < polygon.size(); i++ )
64206441
{
64216442
for ( int j = i + 1; j < polygon.size(); j++ )
64226443
{
6423-
if ( ringIntersectsRing( polygon[i], polygon[j] ) )
6424-
{
6425-
QString msg = QObject::tr( "interior rings %1 and %2 of polygon %3 intersect" ).arg( i ).arg( j ).arg( idx );
6426-
QgsDebugMsg( msg );
6427-
errors << Error( msg );
6428-
}
6444+
checkRingIntersections( errors, idx, i, polygon[i], idx, j, polygon[j] );
64296445
}
64306446
}
64316447

6448+
// check if rings are self-intersecting
64326449
for ( int i = 0; i < polygon.size(); i++ )
64336450
{
64346451
validatePolyline( errors, i, polygon[i] );
@@ -6473,7 +6490,28 @@ void QgsGeometry::validateGeometry( QList<Error> &errors )
64736490
{
64746491
QgsMultiPolygon mp = asMultiPolygon();
64756492
for ( int i = 0; i < mp.size(); i++ )
6493+
{
64766494
validatePolygon( errors, i, mp[i] );
6495+
}
6496+
6497+
for ( int i = 0; i < mp.size(); i++ )
6498+
{
6499+
for ( int j = i + 1; j < mp.size(); j++ )
6500+
{
6501+
if ( ringInRing( mp[i][0], mp[j][0] ) )
6502+
{
6503+
errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) );
6504+
}
6505+
else if ( ringInRing( mp[j][0], mp[i][0] ) )
6506+
{
6507+
errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) );
6508+
}
6509+
else
6510+
{
6511+
checkRingIntersections( errors, i, 0, mp[i][0], j, 0, mp[j][0] );
6512+
}
6513+
}
6514+
}
64776515
}
64786516
break;
64796517

‎src/core/qgsgeometry.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,10 @@ class CORE_EXPORT QgsGeometry
511511
/** return polygon from wkb */
512512
QgsPolygon asPolygon( unsigned char*& ptr, bool hasZValue );
513513

514+
void checkRingIntersections( QList<Error> &errors,
515+
int p0, int i0, const QgsPolyline &ring0,
516+
int p1, int i1, const QgsPolyline &ring1 );
517+
514518
void validatePolyline( QList<Error> &errors, int i, const QgsPolyline &polygon );
515519
void validatePolygon( QList<Error> &errors, int i, const QgsPolygon &polygon );
516520

0 commit comments

Comments
 (0)
Please sign in to comment.