@@ -6324,27 +6324,46 @@ static bool ringInRing( const QgsPolyline &inside, const QgsPolyline &outside )
6324
6324
return true ;
6325
6325
}
6326
6326
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 )
6328
6330
{
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++ )
6333
6332
{
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++ )
6339
6336
{
6340
- outside = true ;
6341
- }
6337
+ QgsVector w = ring1[j+1 ] - ring1[j];
6342
6338
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 );
6346
6343
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
+ }
6348
6367
}
6349
6368
6350
6369
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
6406
6425
6407
6426
void QgsGeometry::validatePolygon ( QList<Error> &errors, int idx, const QgsPolygon &polygon )
6408
6427
{
6428
+ // check if holes are inside polygon
6409
6429
for ( int i = 1 ; i < polygon.size (); i++ )
6410
6430
{
6411
6431
if ( !ringInRing ( polygon[i], polygon[0 ] ) )
@@ -6416,19 +6436,16 @@ void QgsGeometry::validatePolygon( QList<Error> &errors, int idx, const QgsPolyg
6416
6436
}
6417
6437
}
6418
6438
6439
+ // check holes for intersections
6419
6440
for ( int i = 1 ; i < polygon.size (); i++ )
6420
6441
{
6421
6442
for ( int j = i + 1 ; j < polygon.size (); j++ )
6422
6443
{
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] );
6429
6445
}
6430
6446
}
6431
6447
6448
+ // check if rings are self-intersecting
6432
6449
for ( int i = 0 ; i < polygon.size (); i++ )
6433
6450
{
6434
6451
validatePolyline ( errors, i, polygon[i] );
@@ -6473,7 +6490,28 @@ void QgsGeometry::validateGeometry( QList<Error> &errors )
6473
6490
{
6474
6491
QgsMultiPolygon mp = asMultiPolygon ();
6475
6492
for ( int i = 0 ; i < mp.size (); i++ )
6493
+ {
6476
6494
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
+ }
6477
6515
}
6478
6516
break ;
6479
6517
0 commit comments