void QgsGeometryValidator::validatePolygon( int idx, const QgsPolygon &polygon ) { // check if holes are inside polygon for ( int i = 1; !mStop && i < polygon.size(); i++ ) { if ( !ringInRing( polygon[i], polygon[0] ) ) { QString msg = QObject::tr( "ring %1 of polygon %2 not in exterior ring" ).arg( i ).arg( idx ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg ) ); mErrorCount++; } } // check holes for intersections for ( int i = 1; !mStop && i < polygon.size(); i++ ) { for ( int j = i + 1; !mStop && j < polygon.size(); j++ ) { checkRingIntersections( idx, i, polygon[i], idx, j, polygon[j] ); } } // check if rings are self-intersecting for ( int i = 0; !mStop && i < polygon.size(); i++ ) { validatePolyline( i, polygon[i], true ); } }
void QgsGeometryValidator::run() { mErrorCount = 0; QSettings settings; if ( settings.value( QStringLiteral( "/qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 ) { char *r = nullptr; const GEOSGeometry *g0 = mG.asGeos(); GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler(); if ( !g0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:could not produce geometry for GEOS (check log window)" ) ) ); } else { GEOSGeometry *g1 = nullptr; if ( GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ) != 1 ) { if ( g1 ) { const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 ); unsigned int n; if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 ) { double x, y; GEOSCoordSeq_getX_r( handle, cs, 0, &x ); GEOSCoordSeq_getY_r( handle, cs, 0, &y ); emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ), QgsPoint( x, y ) ) ); mErrorCount++; } GEOSGeom_destroy_r( handle, g1 ); } else { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ) ) ); mErrorCount++; } GEOSFree_r( handle, r ); } } return; } QgsDebugMsg( "validation thread started." ); QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mG.wkbType() ); //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint ) // break; if ( flatType == QgsWkbTypes::LineString ) { validatePolyline( 0, mG.asPolyline() ); } else if ( flatType == QgsWkbTypes::MultiLineString ) { QgsMultiPolyline mp = mG.asMultiPolyline(); for ( int i = 0; !mStop && i < mp.size(); i++ ) validatePolyline( i, mp[i] ); } else if ( flatType == QgsWkbTypes::Polygon ) { validatePolygon( 0, mG.asPolygon() ); } else if ( flatType == QgsWkbTypes::MultiPolygon ) { QgsMultiPolygon mp = mG.asMultiPolygon(); for ( int i = 0; !mStop && i < mp.size(); i++ ) { validatePolygon( i, mp[i] ); } for ( int i = 0; !mStop && i < mp.size(); i++ ) { if ( mp[i].isEmpty() ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) ); mErrorCount++; continue; } for ( int j = i + 1; !mStop && j < mp.size(); j++ ) { if ( mp[j].isEmpty() ) continue; if ( ringInRing( mp[i][0], mp[j][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) ); mErrorCount++; } else if ( ringInRing( mp[j][0], mp[i][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) ); mErrorCount++; } else { checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] ); } } } } else if ( flatType == QgsWkbTypes::Unknown ) { QgsDebugMsg( QObject::tr( "Unknown geometry type" ) ); emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mG.wkbType() ) ) ); mErrorCount++; } QgsDebugMsg( "validation finished." ); if ( mStop ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) ); } else if ( mErrorCount > 0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) ); } #if 0 else { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) ); } #endif }
void QgsGeometryValidator::run() { mErrorCount = 0; switch ( mMethod ) { case QgsGeometry::ValidatorGeos: { char *r = nullptr; geos::unique_ptr g0( mGeometry.exportToGeos() ); GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler(); if ( !g0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: could not produce geometry for GEOS (check log window)" ) ) ); } else { GEOSGeometry *g1 = nullptr; char res = GEOSisValidDetail_r( handle, g0.get(), GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ); if ( res != 1 ) { if ( g1 ) { const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 ); unsigned int n; if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 ) { double x, y; GEOSCoordSeq_getX_r( handle, cs, 0, &x ); GEOSCoordSeq_getY_r( handle, cs, 0, &y ); emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ), QgsPointXY( x, y ) ) ); mErrorCount++; } GEOSGeom_destroy_r( handle, g1 ); } else { emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ) ) ); mErrorCount++; } GEOSFree_r( handle, r ); } } break; } case QgsGeometry::ValidatorQgisInternal: { QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mGeometry.wkbType() ); //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint ) // break; if ( flatType == QgsWkbTypes::LineString ) { validatePolyline( 0, mGeometry.asPolyline() ); } else if ( flatType == QgsWkbTypes::MultiLineString ) { QgsMultiPolylineXY mp = mGeometry.asMultiPolyline(); for ( int i = 0; !mStop && i < mp.size(); i++ ) validatePolyline( i, mp[i] ); } else if ( flatType == QgsWkbTypes::Polygon ) { validatePolygon( 0, mGeometry.asPolygon() ); } else if ( flatType == QgsWkbTypes::MultiPolygon ) { QgsMultiPolygonXY mp = mGeometry.asMultiPolygon(); for ( int i = 0; !mStop && i < mp.size(); i++ ) { validatePolygon( i, mp[i] ); } for ( int i = 0; !mStop && i < mp.size(); i++ ) { if ( mp[i].isEmpty() ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) ); mErrorCount++; continue; } for ( int j = i + 1; !mStop && j < mp.size(); j++ ) { if ( mp[j].isEmpty() ) continue; if ( ringInRing( mp[i][0], mp[j][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) ); mErrorCount++; } else if ( ringInRing( mp[j][0], mp[i][0] ) ) { emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) ); mErrorCount++; } else { checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] ); } } } } else if ( flatType == QgsWkbTypes::Unknown ) { QgsDebugMsg( QObject::tr( "Unknown geometry type" ) ); emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mGeometry.wkbType() ) ) ); mErrorCount++; } if ( mStop ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) ); } else if ( mErrorCount > 0 ) { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) ); } #if 0 else { emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) ); } #endif break; } } }