ErrorList topolTest::checkDanglingLines( QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( layer2 ); int i = 0; ErrorList errorList; QgsFeature f; if ( layer1->geometryType() != QgsWkbTypes::LineGeometry ) { return errorList; } QList<FeatureLayer>::iterator it; qDebug() << mFeatureList1.count(); QgsPointXY startPoint; QgsPointXY endPoint; std::multimap<QgsPointXY, QgsFeatureId, PointComparer> endVerticesMap; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCanceled() ) break; QgsGeometry g1 = it->feature.geometry(); if ( g1.isNull() ) { QgsMessageLog::logMessage( tr( "First geometry invalid in dangling line test." ), tr( "Topology plugin" ) ); continue; } if ( !_canExportToGeos( g1 ) ) { QgsMessageLog::logMessage( tr( "Failed to import first geometry into GEOS in dangling line test." ), tr( "Topology plugin" ) ); continue; } if ( g1.isMultipart() ) { QgsMultiPolylineXY lines = g1.asMultiPolyline(); for ( int m = 0; m < lines.count(); m++ ) { QgsPolylineXY line = lines[m]; startPoint = line[0]; endPoint = line[line.size() - 1]; endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( startPoint, it->feature.id() ) ); endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( endPoint, it->feature.id() ) ); } } else { QgsPolylineXY polyline = g1.asPolyline(); startPoint = polyline[0]; endPoint = polyline[polyline.size() - 1]; endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( startPoint, it->feature.id() ) ); endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( endPoint, it->feature.id() ) ); } } QgsGeometry canvasExtentPoly = QgsGeometry::fromWkt( qgsInterface->mapCanvas()->extent().asWktPolygon() ); for ( std::multimap<QgsPointXY, QgsFeatureId, PointComparer>::iterator pointIt = endVerticesMap.begin(), end = endVerticesMap.end(); pointIt != end; pointIt = endVerticesMap.upper_bound( pointIt->first ) ) { QgsPointXY p = pointIt->first; QgsFeatureId k = pointIt->second; size_t repetitions = endVerticesMap.count( p ); //QgsGeometry* extentPoly = if ( repetitions == 1 ) { QgsGeometry conflictGeom = QgsGeometry::fromPointXY( p ); if ( isExtent ) { if ( canvasExtentPoly.disjoint( conflictGeom ) ) { continue; } } QgsRectangle bBox = conflictGeom.boundingBox(); QgsFeature feat; FeatureLayer ftrLayer1; //need to fetch attributes?? being safe side by fetching.. layer1->getFeatures( QgsFeatureRequest().setFilterFid( k ) ).nextFeature( feat ); ftrLayer1.feature = feat; ftrLayer1.layer = layer1; QList<FeatureLayer> errorFtrLayers; errorFtrLayers << ftrLayer1 << ftrLayer1; TopolErrorDangle *err = new TopolErrorDangle( bBox, conflictGeom, errorFtrLayers ); errorList << err; } } return errorList; }
ErrorList topolTest::checkPointCoveredBySegment( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ) { Q_UNUSED( tolerance ); int i = 0; ErrorList errorList; if ( layer1->geometryType() != QGis::Point ) { return errorList; } if ( layer2->geometryType() == QGis::Point ) { return errorList; } QgsSpatialIndex* index = mLayerIndexes[layer2->id()]; QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); QList<FeatureLayer>::Iterator it; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); QgsRectangle bb = g1->boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::Iterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); bool touched = false; for ( ; cit != crossingIdsEnd; ++cit ) { QgsFeature& f = mFeatureMap2[*cit].feature; const QgsGeometry* g2 = f.constGeometry(); if ( !g2 ) { QgsMessageLog::logMessage( tr( "Invalid geometry in covering test." ), tr( "Topology plugin" ) ); continue; } // test if point touches other geometry if ( g1->touches( g2 ) ) { touched = true; break; } } if ( !touched ) { QgsGeometry* conflictGeom = new QgsGeometry( *g1 ); if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom ) ) { delete conflictGeom; continue; } } QList<FeatureLayer> fls; fls << *it << *it; //bb.scale(10); TopolErrorCovered* err = new TopolErrorCovered( bb, conflictGeom, fls ); errorList << err; } } delete canvasExtentPoly; return errorList; }
ErrorList topolTest::checkPointInPolygon( QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { int i = 0; ErrorList errorList; if ( layer1->geometryType() != QgsWkbTypes::PointGeometry ) { return errorList; } if ( layer2->geometryType() != QgsWkbTypes::PolygonGeometry ) { return errorList; } QgsSpatialIndex *index = mLayerIndexes[layer2->id()]; QgsGeometry canvasExtentPoly = QgsGeometry::fromWkt( qgsInterface->mapCanvas()->extent().asWktPolygon() ); QList<FeatureLayer>::Iterator it; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCanceled() ) break; QgsGeometry g1 = it->feature.geometry(); QgsRectangle bb = g1.boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::ConstIterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); bool touched = false; for ( ; cit != crossingIdsEnd; ++cit ) { QgsFeature &f = mFeatureMap2[*cit].feature; QgsGeometry g2 = f.geometry(); if ( g2.isNull() || !_canExportToGeos( g2 ) ) { QgsMessageLog::logMessage( tr( "Second geometry missing or GEOS import failed." ), tr( "Topology plugin" ) ); continue; } if ( g2.contains( g1 ) ) { touched = true; break; } } if ( !touched ) { QgsGeometry conflictGeom = g1; if ( isExtent ) { if ( canvasExtentPoly.disjoint( conflictGeom ) ) { continue; } } QList<FeatureLayer> fls; fls << *it << *it; //bb.scale(10); TopolErrorPointNotInPolygon *err = new TopolErrorPointNotInPolygon( bb, conflictGeom, fls ); errorList << err; } } return errorList; }
ErrorList topolTest::checkGaps( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); Q_UNUSED( layer2 ); int i = 0; ErrorList errorList; GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); // could be enabled for lines and points too // so duplicate rule may be removed? if ( layer1->geometryType() != QGis::Polygon ) { return errorList; } QList<FeatureLayer>::Iterator it; QgsGeometry* g1; QList<GEOSGeometry*> geomList; qDebug() << mFeatureList1.count() << " features in list!"; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { qDebug() << "reading features-" << i; if ( !( ++i % 100 ) ) { emit progress( i ); } if ( testCancelled() ) { break; } g1 = it->feature.geometry(); if ( !g1 ) { continue; } if ( !g1->asGeos() ) { continue; } if ( !g1->isGeosValid() ) { qDebug() << "invalid geometry found..skipping.." << it->feature.id(); continue; } if ( g1->isMultipart() ) { QgsMultiPolygon polys = g1->asMultiPolygon(); for ( int m = 0; m < polys.count(); m++ ) { QgsPolygon polygon = polys[m]; QgsGeometry* polyGeom = QgsGeometry::fromPolygon( polygon ); geomList.push_back( GEOSGeom_clone_r( geosctxt, polyGeom->asGeos() ) ); delete polyGeom; } } else { geomList.push_back( GEOSGeom_clone_r( geosctxt, g1->asGeos() ) ); } } GEOSGeometry** geomArray = new GEOSGeometry*[geomList.size()]; for ( int i = 0; i < geomList.size(); ++i ) { //qDebug() << "filling geometry array-" << i; geomArray[i] = geomList.at( i ); } qDebug() << "creating geometry collection-"; if ( geomList.size() == 0 ) { //qDebug() << "geometry list is empty!"; delete [] geomArray; return errorList; } GEOSGeometry* collection = 0; collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOLYGON, geomArray, geomList.size() ); qDebug() << "performing cascaded union..might take time..-"; GEOSGeometry* unionGeom = GEOSUnionCascaded_r( geosctxt, collection ); //delete[] geomArray; QgsGeometry test; test.fromGeos( unionGeom ); //qDebug() << "wktmerged - " << test.exportToWkt(); QString extentWkt = test.boundingBox().asWktPolygon(); QgsGeometry* extentGeom = QgsGeometry::fromWkt( extentWkt ); QgsGeometry* bufferExtent = extentGeom->buffer( 2, 3 ); delete extentGeom; //qDebug() << "extent wkt - " << bufferExtent->exportToWkt(); QgsGeometry* diffGeoms = bufferExtent->difference( &test ); delete bufferExtent; if ( !diffGeoms ) { qDebug() << "difference result 0-"; return errorList; } //qDebug() << "difference gometry - " << diffGeoms->exportToWkt(); QList<QgsGeometry*> geomColl = diffGeoms->asGeometryCollection(); QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); for ( int i = 1; i < geomColl.count() ; ++i ) { QgsGeometry* conflictGeom = geomColl[i]; if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom ) ) { continue; } if ( canvasExtentPoly->crosses( conflictGeom ) ) { conflictGeom = conflictGeom->intersection( canvasExtentPoly ); } } QgsRectangle bBox = conflictGeom->boundingBox(); QgsFeature feat; FeatureLayer ftrLayer1; ftrLayer1.layer = layer1; QList<FeatureLayer> errorFtrLayers; errorFtrLayers << ftrLayer1 << ftrLayer1; TopolErrorGaps* err = new TopolErrorGaps( bBox, conflictGeom, errorFtrLayers ); errorList << err; } delete canvasExtentPoly; return errorList; }
ErrorList topolTest::checkPseudos( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); Q_UNUSED( layer2 ); int i = 0; ErrorList errorList; QgsFeature f; if ( layer1->geometryType() != QGis::Line ) { return errorList; } QList<FeatureLayer>::Iterator it; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); qDebug() << mFeatureList1.count(); QgsPoint startPoint; QgsPoint endPoint; std::multimap<QgsPoint, QgsFeatureId, PointComparer> endVerticesMap; for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); if ( !g1 ) { QgsMessageLog::logMessage( tr( "Skipping invalid first geometry in pseudo line test." ), tr( "Topology plugin" ) ); continue; } if ( !g1->asGeos() ) { QgsMessageLog::logMessage( tr( "Failed to import first geometry into GEOS in pseudo line test." ), tr( "Topology plugin" ) ); continue; } if ( g1->isMultipart() ) { QgsMultiPolyline lines = g1->asMultiPolyline(); for ( int m = 0; m < lines.count(); m++ ) { QgsPolyline line = lines[m]; startPoint = line[0]; endPoint = line[line.size() - 1]; endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( startPoint, it->feature.id() ) ); endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( endPoint, it->feature.id() ) ); } } else { QgsPolyline polyline = g1->asPolyline(); startPoint = polyline[0]; endPoint = polyline[polyline.size()-1]; endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( startPoint, it->feature.id() ) ); endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( endPoint, it->feature.id() ) ); } } QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); for ( std::multimap<QgsPoint, QgsFeatureId, PointComparer>::iterator pointIt = endVerticesMap.begin(), end = endVerticesMap.end(); pointIt != end; pointIt = endVerticesMap.upper_bound( pointIt->first ) ) { QgsPoint p = pointIt->first; QgsFeatureId k = pointIt->second; size_t repetitions = endVerticesMap.count( p ); if ( repetitions == 2 ) { QgsGeometry* conflictGeom = QgsGeometry::fromPoint( p ); if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom ) ) { delete conflictGeom; continue; } } QgsRectangle bBox = conflictGeom->boundingBox(); QgsFeature feat; FeatureLayer ftrLayer1; //need to fetch attributes?? being safe side by fetching.. layer1->getFeatures( QgsFeatureRequest().setFilterFid( k ) ).nextFeature( feat ); ftrLayer1.feature = feat; ftrLayer1.layer = layer1; QList<FeatureLayer> errorFtrLayers; errorFtrLayers << ftrLayer1 << ftrLayer1; TopolErrorPseudos* err = new TopolErrorPseudos( bBox, conflictGeom, errorFtrLayers ); errorList << err; } } delete canvasExtentPoly; return errorList; }
ErrorList topolTest::checkOverlaps( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); Q_UNUSED( layer2 ); int i = 0; ErrorList errorList; // could be enabled for lines and points too // so duplicate rule may be removed? if ( layer1->geometryType() != QGis::Polygon ) { return errorList; } QList<QgsFeatureId> *duplicateIds = new QList<QgsFeatureId>(); QgsSpatialIndex* index = mLayerIndexes[layer1->id()]; if ( !index ) { qDebug() << "no index present"; delete duplicateIds; return errorList; } QMap<QgsFeatureId, FeatureLayer>::Iterator it; QMap<QgsFeatureId, FeatureLayer>::ConstIterator FeatureListEnd = mFeatureMap2.end(); for ( it = mFeatureMap2.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); QgsFeatureId currentId = it->feature.id(); if ( duplicateIds->contains( currentId ) ) { //is already a duplicate geometry..skip.. continue; } if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); if ( !g1->isGeosValid() ) { qDebug() << "invalid geometry(g1) found..skipping.." << it->feature.id(); continue; } QgsRectangle bb = g1->boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::Iterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); bool duplicate = false; QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); for ( ; cit != crossingIdsEnd; ++cit ) { duplicate = false; // skip itself if ( mFeatureMap2[*cit].feature.id() == it->feature.id() ) continue; const QgsGeometry* g2 = mFeatureMap2[*cit].feature.constGeometry(); if ( !g2 ) { QgsMessageLog::logMessage( tr( "Invalid second geometry in overlaps test." ), tr( "Topology plugin" ) ); continue; } if ( !g2->asGeos() ) { QgsMessageLog::logMessage( tr( "Failed to import second geometry into GEOS in overlaps test." ), tr( "Topology plugin" ) ); continue; } if ( !g2->isGeosValid() ) { QgsMessageLog::logMessage( tr( "Skipping invalid second geometry of feature %1 in overlaps test." ).arg( it->feature.id() ), tr( "Topology plugin" ) ); continue; } qDebug() << "checking overlap for" << it->feature.id(); if ( g1->overlaps( g2 ) ) { duplicate = true; duplicateIds->append( mFeatureMap2[*cit].feature.id() ); } if ( duplicate ) { QList<FeatureLayer> fls; fls << *it << *it; QScopedPointer< QgsGeometry > conflictGeom( g1->intersection( g2 ) ); if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom.data() ) ) { continue; } if ( canvasExtentPoly->crosses( conflictGeom.data() ) ) { conflictGeom.reset( conflictGeom->intersection( canvasExtentPoly ) ); } } TopolErrorOverlaps* err = new TopolErrorOverlaps( bb, conflictGeom.take(), fls ); errorList << err; } } delete canvasExtentPoly; } delete duplicateIds; return errorList; }
ErrorList topolTest::checkDuplicates( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); Q_UNUSED( layer2 ); //TODO: multilines - check all separate pieces int i = 0; ErrorList errorList; QList<QgsFeatureId> duplicateIds; QgsSpatialIndex* index = mLayerIndexes[layer1->id()]; QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); QMap<QgsFeatureId, FeatureLayer>::Iterator it; QMap<QgsFeatureId, FeatureLayer>::ConstIterator FeatureListEnd = mFeatureMap2.end(); for ( it = mFeatureMap2.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); QgsFeatureId currentId = it->feature.id(); if ( duplicateIds.contains( currentId ) ) { //is already a duplicate geometry..skip.. continue; } if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); QgsRectangle bb = g1->boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::Iterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); bool duplicate = false; for ( ; cit != crossingIdsEnd; ++cit ) { duplicate = false; // skip itself if ( mFeatureMap2[*cit].feature.id() == it->feature.id() ) continue; const QgsGeometry* g2 = mFeatureMap2[*cit].feature.constGeometry(); if ( !g2 ) { QgsMessageLog::logMessage( tr( "Invalid second geometry in duplicate geometry test." ), tr( "Topology plugin" ) ); continue; } if ( !g2->asGeos() ) { QgsMessageLog::logMessage( tr( "Failed to import second geometry into GEOS in duplicate geometry test." ), tr( "Topology plugin" ) ); continue; } if ( g1->equals( g2 ) ) { duplicate = true; duplicateIds.append( mFeatureMap2[*cit].feature.id() ); } if ( duplicate ) { QList<FeatureLayer> fls; fls << *it << *it; QScopedPointer<QgsGeometry> conflict( new QgsGeometry( *g1 ) ); if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflict.data() ) ) { continue; } if ( canvasExtentPoly->crosses( conflict.data() ) ) { conflict.reset( conflict->intersection( canvasExtentPoly ) ); } } TopolErrorDuplicates* err = new TopolErrorDuplicates( bb, conflict.take(), fls ); errorList << err; } } } delete canvasExtentPoly; return errorList; }
ErrorList topolTest::checkyLineEndsCoveredByPoints( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); int i = 0; ErrorList errorList; if ( layer1->geometryType() != QGis::Line ) { return errorList; } if ( layer2->geometryType() != QGis::Point ) { return errorList; } QgsSpatialIndex* index = mLayerIndexes[layer2->id()]; QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); QList<FeatureLayer>::Iterator it; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); QgsGeometry* startPoint = QgsGeometry::fromPoint( g1->asPolyline().first() ); QgsGeometry* endPoint = QgsGeometry::fromPoint( g1->asPolyline().last() ); QgsRectangle bb = g1->boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::Iterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); bool touched = false; bool touchStartPoint = false; bool touchEndPoint = false; for ( ; cit != crossingIdsEnd; ++cit ) { QgsFeature& f = mFeatureMap2[*cit].feature; const QgsGeometry* g2 = f.constGeometry(); if ( !g2 || !g2->asGeos() ) { QgsMessageLog::logMessage( tr( "Second geometry missing or GEOS import failed." ), tr( "Topology plugin" ) ); continue; } if ( g2->intersects( startPoint ) ) { touchStartPoint = true; } if ( g2->intersects( endPoint ) ) { touchEndPoint = true; } if ( touchStartPoint && touchEndPoint ) { touched = true; break; } } delete startPoint; delete endPoint; if ( !touched ) { QScopedPointer<QgsGeometry> conflictGeom( new QgsGeometry( *g1 ) ); if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom.data() ) ) { continue; } if ( canvasExtentPoly->crosses( conflictGeom.data() ) ) { conflictGeom.reset( conflictGeom->intersection( canvasExtentPoly ) ); } } QList<FeatureLayer> fls; fls << *it << *it; //bb.scale(10); TopolErrorLineEndsNotCoveredByPoints* err = new TopolErrorLineEndsNotCoveredByPoints( bb, conflictGeom.take(), fls ); errorList << err; } } delete canvasExtentPoly; return errorList; }
ErrorList topolTest::checkOverlapWithLayer( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ) { Q_UNUSED( tolerance ); int i = 0; ErrorList errorList; bool skipItself = layer1 == layer2; QgsSpatialIndex* index = mLayerIndexes[layer2->id()]; QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); QList<FeatureLayer>::Iterator it; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); QgsRectangle bb = g1->boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::Iterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); for ( ; cit != crossingIdsEnd; ++cit ) { QgsFeature& f = mFeatureMap2[*cit].feature; const QgsGeometry* g2 = f.constGeometry(); // skip itself, when invoked with the same layer if ( skipItself && f.id() == it->feature.id() ) continue; if ( !g2 ) { QgsMessageLog::logMessage( tr( "Second geometry missing." ), tr( "Topology plugin" ) ); continue; } if ( g1->overlaps( g2 ) ) { QgsRectangle r = bb; QgsRectangle r2 = g2->boundingBox(); r.combineExtentWith( &r2 ); QScopedPointer<QgsGeometry> conflictGeom( g1->intersection( g2 ) ); // could this for some reason return NULL? if ( !conflictGeom ) { continue; } if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom.data() ) ) { continue; } if ( canvasExtentPoly->crosses( conflictGeom.data() ) ) { conflictGeom.reset( conflictGeom->intersection( canvasExtentPoly ) ); } } //c = new QgsGeometry; QList<FeatureLayer> fls; FeatureLayer fl; fl.feature = f; fl.layer = layer2; fls << *it << fl; TopolErrorIntersection* err = new TopolErrorIntersection( r, conflictGeom.take(), fls ); errorList << err; } } } delete canvasExtentPoly; return errorList; }
ErrorList topolTest::checkyLineEndsCoveredByPoints( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); int i = 0; ErrorList errorList; if ( layer1->geometryType() != QgsWkbTypes::LineGeometry ) { return errorList; } if ( layer2->geometryType() != QgsWkbTypes::PointGeometry ) { return errorList; } QgsSpatialIndex* index = mLayerIndexes[layer2->id()]; QgsGeometry canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); QList<FeatureLayer>::Iterator it; for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCancelled() ) break; QgsGeometry g1 = it->feature.geometry(); QgsPolyline g1Polyline = g1.asPolyline(); QgsGeometry startPoint = QgsGeometry::fromPoint( g1Polyline.at( 0 ) ); QgsGeometry endPoint = QgsGeometry::fromPoint( g1Polyline.last() ); QgsRectangle bb = g1.boundingBox(); QList<QgsFeatureId> crossingIds; crossingIds = index->intersects( bb ); QList<QgsFeatureId>::Iterator cit = crossingIds.begin(); QList<QgsFeatureId>::ConstIterator crossingIdsEnd = crossingIds.end(); bool touched = false; bool touchStartPoint = false; bool touchEndPoint = false; for ( ; cit != crossingIdsEnd; ++cit ) { QgsFeature& f = mFeatureMap2[*cit].feature; QgsGeometry g2 = f.geometry(); if ( g2.isEmpty() || !_canExportToGeos( g2 ) ) { QgsMessageLog::logMessage( tr( "Second geometry missing or GEOS import failed." ), tr( "Topology plugin" ) ); continue; } if ( g2.intersects( startPoint ) ) { touchStartPoint = true; } if ( g2.intersects( endPoint ) ) { touchEndPoint = true; } if ( touchStartPoint && touchEndPoint ) { touched = true; break; } } if ( !touched ) { QgsGeometry conflictGeom = g1; if ( isExtent ) { if ( canvasExtentPoly.disjoint( conflictGeom ) ) { continue; } if ( canvasExtentPoly.crosses( conflictGeom ) ) { conflictGeom = conflictGeom.intersection( canvasExtentPoly ); } } QList<FeatureLayer> fls; fls << *it << *it; //bb.scale(10); TopolErrorLineEndsNotCoveredByPoints* err = new TopolErrorLineEndsNotCoveredByPoints( bb, conflictGeom, fls ); errorList << err; } } return errorList; }