void QgsGeometryValidator::validatePolygon( int idx, const QgsPolygonXY &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 ); } }
std::unique_ptr<QgsPolygon> QgsGeometryFactory::fromPolygonXY( const QgsPolygonXY &polygon ) { std::unique_ptr< QgsPolygon > poly = qgis::make_unique< QgsPolygon >(); QVector<QgsCurve *> holes; holes.reserve( polygon.size() ); for ( int i = 0; i < polygon.size(); ++i ) { std::unique_ptr< QgsLineString > l = linestringFromPolyline( polygon.at( i ) ); l->close(); if ( i == 0 ) { poly->setExteriorRing( l.release() ); } else { holes.push_back( l.release() ); } } poly->setInteriorRings( holes ); return poly; }
int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsGeometry &geom ) { if ( !mLayer->isSpatial() ) return 1; if ( geom.isNull() ) { return 1; } int returnVal = 0; QgsWkbTypes::Type wkbType = geom.wkbType(); switch ( QgsWkbTypes::geometryType( wkbType ) ) { //line case QgsWkbTypes::LineGeometry: { if ( !QgsWkbTypes::isMultiType( wkbType ) ) { QgsPolylineXY line = geom.asPolyline(); QgsPolylineXY::const_iterator line_it = line.constBegin(); for ( ; line_it != line.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } else { QgsMultiPolylineXY multiLine = geom.asMultiPolyline(); QgsPolylineXY currentPolyline; for ( int i = 0; i < multiLine.size(); ++i ) { QgsPolylineXY::const_iterator line_it = currentPolyline.constBegin(); for ( ; line_it != currentPolyline.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } } break; } case QgsWkbTypes::PolygonGeometry: { if ( !QgsWkbTypes::isMultiType( wkbType ) ) { QgsPolygonXY polygon = geom.asPolygon(); QgsPolylineXY currentRing; for ( int i = 0; i < polygon.size(); ++i ) { currentRing = polygon.at( i ); QgsPolylineXY::const_iterator line_it = currentRing.constBegin(); for ( ; line_it != currentRing.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } } else { QgsMultiPolygonXY multiPolygon = geom.asMultiPolygon(); QgsPolygonXY currentPolygon; QgsPolylineXY currentRing; for ( int i = 0; i < multiPolygon.size(); ++i ) { currentPolygon = multiPolygon.at( i ); for ( int j = 0; j < currentPolygon.size(); ++j ) { currentRing = currentPolygon.at( j ); QgsPolylineXY::const_iterator line_it = currentRing.constBegin(); for ( ; line_it != currentRing.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } } } break; } case QgsWkbTypes::PointGeometry: case QgsWkbTypes::UnknownGeometry: case QgsWkbTypes::NullGeometry: break; } return returnVal; }
ErrorList topolTest::checkSegmentLength( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( layer1 ); Q_UNUSED( layer2 ); Q_UNUSED( isExtent ); int i = 0; ErrorList errorList; QgsFeature f; QList<FeatureLayer>::iterator it; QgsPolygonXY pol; QgsMultiPolygonXY mpol; QgsPolylineXY segm; QgsPolylineXY ls; QgsMultiPolylineXY mls; QList<FeatureLayer> fls; TopolErrorShort *err = nullptr; double distance; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { if ( !( ++i % 100 ) ) { emit progress( i ); } if ( testCanceled() ) { break; } QgsGeometry g1 = it->feature.geometry(); // switching by type here, because layer can contain both single and multi version geometries switch ( g1.wkbType() ) { case QgsWkbTypes::LineString: case QgsWkbTypes::LineString25D: ls = g1.asPolyline(); for ( int i = 1; i < ls.size(); ++i ) { distance = std::sqrt( ls[i - 1].sqrDist( ls[i] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << ls[i - 1] << ls[i]; QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm ); err = new TopolErrorShort( g1.boundingBox(), conflict, fls ); //err = new TopolErrorShort(g1->boundingBox(), QgsGeometry::fromPolyline(segm), fls); errorList << err; //break on getting the first error break; } } break; case QgsWkbTypes::Polygon: case QgsWkbTypes::Polygon25D: pol = g1.asPolygon(); for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = std::sqrt( pol[i][j - 1].sqrDist( pol[i][j] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << pol[i][j - 1] << pol[i][j]; QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm ); err = new TopolErrorShort( g1.boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QgsWkbTypes::MultiLineString: case QgsWkbTypes::MultiLineString25D: mls = g1.asMultiPolyline(); for ( int k = 0; k < mls.size(); ++k ) { QgsPolylineXY &ls = mls[k]; for ( int i = 1; i < ls.size(); ++i ) { distance = std::sqrt( ls[i - 1].sqrDist( ls[i] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << ls[i - 1] << ls[i]; QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm ); err = new TopolErrorShort( g1.boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QgsWkbTypes::MultiPolygon: case QgsWkbTypes::MultiPolygon25D: mpol = g1.asMultiPolygon(); for ( int k = 0; k < mpol.size(); ++k ) { QgsPolygonXY &pol = mpol[k]; for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = pol[i][j - 1].sqrDist( pol[i][j] ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << pol[i][j - 1] << pol[i][j]; QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm ); err = new TopolErrorShort( g1.boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } } break; default: continue; } } return errorList; }