void QgsRubberBand::addGeometry( QgsGeometry* geom, QgsVectorLayer* layer ) { if ( !geom ) { return; } //maprender object of canvas const QgsMapSettings& ms = mMapCanvas->mapSettings(); int idx = mPoints.size(); switch ( geom->wkbType() ) { case QGis::WKBPoint: case QGis::WKBPoint25D: { QgsPoint pt; if ( layer ) { pt = ms.layerToMapCoordinates( layer, geom->asPoint() ); } else { pt = geom->asPoint(); } addPoint( pt, false, idx ); removeLastPoint( idx, false ); } break; case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: { QgsMultiPoint mpt = geom->asMultiPoint(); for ( int i = 0; i < mpt.size(); ++i, ++idx ) { QgsPoint pt = mpt[i]; if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, pt ), false, idx ); removeLastPoint( idx, false ); } else { addPoint( pt, false, idx ); removeLastPoint( idx, false ); } } } break; case QGis::WKBLineString: case QGis::WKBLineString25D: { QgsPolyline line = geom->asPolyline(); for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: { QgsMultiPolyline mline = geom->asMultiPolyline(); for ( int i = 0; i < mline.size(); ++i, ++idx ) { QgsPolyline line = mline[i]; if ( line.size() == 0 ) { --idx; } for ( int j = 0; j < line.size(); ++j ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: { QgsPolygon poly = geom->asPolygon(); QgsPolyline line = poly[0]; for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: { QgsMultiPolygon multipoly = geom->asMultiPolygon(); for ( int i = 0; i < multipoly.size(); ++i, ++idx ) { QgsPolygon poly = multipoly[i]; QgsPolyline line = poly[0]; for ( int j = 0; j < line.count(); ++j ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QGis::WKBUnknown: default: return; } updateRect(); update(); }
/*! Draw the shape in response to an update event. */ void QgsHighlight::paint( QPainter* p ) { if ( !mGeometry ) { return; } p->setPen( mPen ); p->setBrush( mBrush ); switch ( mGeometry->wkbType() ) { case QGis::WKBPoint: case QGis::WKBPoint25D: { paintPoint( p, mGeometry->asPoint() ); } break; case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: { QgsMultiPoint m = mGeometry->asMultiPoint(); for ( int i = 0; i < m.size(); i++ ) { paintPoint( p, m[i] ); } } break; case QGis::WKBLineString: case QGis::WKBLineString25D: { paintLine( p, mGeometry->asPolyline() ); } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: { QgsMultiPolyline m = mGeometry->asMultiPolyline(); for ( int i = 0; i < m.size(); i++ ) { paintLine( p, m[i] ); } } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: { paintPolygon( p, mGeometry->asPolygon() ); } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: { QgsMultiPolygon m = mGeometry->asMultiPolygon(); for ( int i = 0; i < m.size(); i++ ) { paintPolygon( p, m[i] ); } } break; case QGis::WKBUnknown: default: return; } }
QgsGeometry* QgsMapToolDeletePart::partUnderPoint( QPoint point, QgsFeatureId& fid, int& partNum ) { QgsFeature f; QgsGeometry* geomPart = new QgsGeometry(); switch ( vlayer->geometryType() ) { case QGis::Point: case QGis::Line: { QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Vertex | QgsPointLocator::Edge ); if ( !match.isValid() ) return geomPart; int snapVertex = match.vertexIndex(); vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f ); const QgsGeometry* g = f.constGeometry(); if ( !g->isMultipart() ) { fid = match.featureId(); delete geomPart; return QgsGeometry::fromPoint( match.point() ); } if ( g->wkbType() == QGis::WKBMultiPoint || g->wkbType() == QGis::WKBMultiPoint25D ) { fid = match.featureId(); partNum = snapVertex; delete geomPart; return QgsGeometry::fromPoint( match.point() ); } if ( g->wkbType() == QGis::WKBMultiLineString || g->wkbType() == QGis::WKBMultiLineString25D ) { QgsMultiPolyline mline = g->asMultiPolyline(); for ( int part = 0; part < mline.count(); part++ ) { if ( snapVertex < mline[part].count() ) { fid = match.featureId(); partNum = part; delete geomPart; return QgsGeometry::fromPolyline( mline[part] ); } snapVertex -= mline[part].count(); } } break; } case QGis::Polygon: { QgsPoint layerCoords = toLayerCoordinates( vlayer, point ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ) ); fit.nextFeature( f ); const QgsGeometry* g = f.constGeometry(); if ( !g ) return geomPart; if ( !g->isMultipart() ) { fid = f.id(); return geomPart; } QgsMultiPolygon mpolygon = g->asMultiPolygon(); for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons { const QgsPolygon& polygon = mpolygon[part]; QgsGeometry* partGeo = QgsGeometry::fromPolygon( polygon ); if ( partGeo->contains( &layerCoords ) ) { fid = f.id(); partNum = part; delete geomPart; return partGeo; } delete partGeo; } break; } default: { break; } } return geomPart; }
QgsGeometry* QgsMapToolDeletePart::partUnderPoint( QPoint point, int& fid, int& partNum ) { QgsFeature f; QgsGeometry* geomPart = new QgsGeometry(); switch ( vlayer->geometryType() ) { case QGis::Point: case QGis::Line: { if ( mSnapper.snapToCurrentLayer( point, mRecentSnappingResults, QgsSnapper::SnapToVertexAndSegment ) == 0 ) { if ( mRecentSnappingResults.length() > 0 ) { QgsSnappingResult sr = mRecentSnappingResults.first(); int snapVertex = sr.snappedVertexNr; if ( snapVertex == -1 ) snapVertex = sr.beforeVertexNr; vlayer->getFeatures( QgsFeatureRequest().setFilterFid( sr.snappedAtGeometry ) ).nextFeature( f ); QgsGeometry* g = f.geometry(); if ( !g->isMultipart() ) return geomPart; if ( g->wkbType() == QGis::WKBMultiPoint || g->wkbType() == QGis::WKBMultiPoint25D ) { fid = sr.snappedAtGeometry; partNum = snapVertex; return QgsGeometry::fromPoint( sr.snappedVertex ); } if ( g->wkbType() == QGis::WKBMultiLineString || g->wkbType() == QGis::WKBMultiLineString25D ) { QgsMultiPolyline mline = g->asMultiPolyline(); for ( int part = 0; part < mline.count(); part++ ) { if ( snapVertex < mline[part].count() ) { fid = sr.snappedAtGeometry; partNum = part; return QgsGeometry::fromPolyline( mline[part] ); } snapVertex -= mline[part].count(); } } } } break; } case QGis::Polygon: { QgsPoint layerCoords = toLayerCoordinates( vlayer, point ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ) ); fit.nextFeature( f ); QgsGeometry* g = f.geometry(); if ( !g ) return geomPart; if ( !g->isMultipart() ) return geomPart; QgsMultiPolygon mpolygon = g->asMultiPolygon(); for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons { const QgsPolygon& polygon = mpolygon[part]; QgsGeometry* partGeo = QgsGeometry::fromPolygon( polygon ); if ( partGeo->contains( &layerCoords ) ) { fid = f.id(); partNum = part; return partGeo; } } break; } default: { break; } } return geomPart; }
QgsGeometry* QgsTransectSample::clipBufferLine( const QgsGeometry& stratumGeom, QgsGeometry* clippedBaseline, double tolerance ) { if ( !stratumGeom || !clippedBaseline || clippedBaseline->wkbType() == QgsWkbTypes::Unknown ) { return nullptr; } QgsGeometry usedBaseline = *clippedBaseline; if ( mBaselineSimplificationTolerance >= 0 ) { //int verticesBefore = usedBaseline->asMultiPolyline().count(); usedBaseline = clippedBaseline->simplify( mBaselineSimplificationTolerance ); if ( usedBaseline.isEmpty() ) { return nullptr; } //int verticesAfter = usedBaseline->asMultiPolyline().count(); //debug: write to file /*QgsVectorFileWriter debugWriter( "/tmp/debug.shp", "utf-8", QgsFields(), QgsWkbTypes::LineString, &( mStrataLayer->crs() ) ); QgsFeature debugFeature; debugFeature.setGeometry( usedBaseline ); debugWriter.addFeature( debugFeature );*/ } double currentBufferDist = tolerance; int maxLoops = 10; for ( int i = 0; i < maxLoops; ++i ) { //loop with tolerance: create buffer, convert buffer to line, clip line by stratum, test if result is (single) line QgsGeometry clipBaselineBuffer = usedBaseline.buffer( currentBufferDist, 8 ); if ( clipBaselineBuffer.isEmpty() ) { continue; } //it is also possible that clipBaselineBuffer is a multipolygon QgsGeometry bufferLine; //buffer line or multiline QgsGeometry bufferLineClipped; QgsMultiPolyline mpl; if ( clipBaselineBuffer.isMultipart() ) { QgsMultiPolygon bufferMultiPolygon = clipBaselineBuffer.asMultiPolygon(); if ( bufferMultiPolygon.size() < 1 ) { continue; } for ( int j = 0; j < bufferMultiPolygon.size(); ++j ) { int size = bufferMultiPolygon.at( j ).size(); for ( int k = 0; k < size; ++k ) { mpl.append( bufferMultiPolygon.at( j ).at( k ) ); } } bufferLine = QgsGeometry::fromMultiPolyline( mpl ); } else { QgsPolygon bufferPolygon = clipBaselineBuffer.asPolygon(); if ( bufferPolygon.size() < 1 ) { continue; } int size = bufferPolygon.size(); mpl.reserve( size ); for ( int j = 0; j < size; ++j ) { mpl.append( bufferPolygon[j] ); } bufferLine = QgsGeometry::fromMultiPolyline( mpl ); } bufferLineClipped = bufferLine.intersection( stratumGeom ); if ( bufferLineClipped.isEmpty() && bufferLineClipped.type() == QgsWkbTypes::LineGeometry ) { //if stratumGeom is a multipolygon, bufferLineClipped must intersect each part bool bufferLineClippedIntersectsStratum = true; if ( stratumGeom.wkbType() == QgsWkbTypes::MultiPolygon || stratumGeom.wkbType() == QgsWkbTypes::MultiPolygon25D ) { QVector<QgsPolygon> multiPoly = stratumGeom.asMultiPolygon(); QVector<QgsPolygon>::const_iterator multiIt = multiPoly.constBegin(); for ( ; multiIt != multiPoly.constEnd(); ++multiIt ) { QgsGeometry poly = QgsGeometry::fromPolygon( *multiIt ); if ( !poly.intersects( bufferLineClipped ) ) { bufferLineClippedIntersectsStratum = false; break; } } } if ( bufferLineClippedIntersectsStratum ) { return new QgsGeometry( bufferLineClipped ); } } currentBufferDist /= 2; } return nullptr; //no solution found even with reduced tolerances }
int QgsVectorLayerEditUtils::addTopologicalPoints( QgsGeometry* geom ) { if ( !L->hasGeometryType() ) return 1; if ( !geom ) { return 1; } int returnVal = 0; QGis::WkbType wkbType = geom->wkbType(); switch ( wkbType ) { //line case QGis::WKBLineString25D: case QGis::WKBLineString: { QgsPolyline theLine = geom->asPolyline(); QgsPolyline::const_iterator line_it = theLine.constBegin(); for ( ; line_it != theLine.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } break; } //multiline case QGis::WKBMultiLineString25D: case QGis::WKBMultiLineString: { QgsMultiPolyline theMultiLine = geom->asMultiPolyline(); QgsPolyline currentPolyline; for ( int i = 0; i < theMultiLine.size(); ++i ) { QgsPolyline::const_iterator line_it = currentPolyline.constBegin(); for ( ; line_it != currentPolyline.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } break; } //polygon case QGis::WKBPolygon25D: case QGis::WKBPolygon: { QgsPolygon thePolygon = geom->asPolygon(); QgsPolyline currentRing; for ( int i = 0; i < thePolygon.size(); ++i ) { currentRing = thePolygon.at( i ); QgsPolyline::const_iterator line_it = currentRing.constBegin(); for ( ; line_it != currentRing.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } break; } //multipolygon case QGis::WKBMultiPolygon25D: case QGis::WKBMultiPolygon: { QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon(); QgsPolygon currentPolygon; QgsPolyline currentRing; for ( int i = 0; i < theMultiPolygon.size(); ++i ) { currentPolygon = theMultiPolygon.at( i ); for ( int j = 0; j < currentPolygon.size(); ++j ) { currentRing = currentPolygon.at( j ); QgsPolyline::const_iterator line_it = currentRing.constBegin(); for ( ; line_it != currentRing.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } } break; } default: break; } return returnVal; }
void QgsGeometryValidator::run() { mErrorCount = 0; #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ ( (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=3) || GEOS_VERSION_MAJOR>3) QSettings settings; if ( settings.value( "/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; } #endif QgsDebugMsg( "validation thread started." ); switch ( mG.wkbType() ) { case QGis::WKBPoint: case QGis::WKBPoint25D: case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: break; case QGis::WKBLineString: case QGis::WKBLineString25D: validatePolyline( 0, mG.asPolyline() ); break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: { QgsMultiPolyline mp = mG.asMultiPolyline(); for ( int i = 0; !mStop && i < mp.size(); i++ ) validatePolyline( i, mp[i] ); } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: { validatePolygon( 0, mG.asPolygon() ); } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: { 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] ); } } } } break; case QGis::WKBNoGeometry: case QGis::WKBUnknown: QgsDebugMsg( QObject::tr( "Unknown geometry type" ) ); emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mG.wkbType() ) ) ); mErrorCount++; break; } 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 QgsDxfExport::addFeature( const QgsSymbolV2RenderContext& ctx, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ) { const QgsFeature* fet = ctx.feature(); if ( !fet ) { return; } QgsGeometry* geom = fet->geometry(); if ( geom ) { int c = 0; if ( mSymbologyExport != NoSymbology ) { c = colorFromSymbolLayer( symbolLayer, ctx ); } double width = -1; if ( mSymbologyExport != NoSymbology && symbolLayer ) { width = symbolLayer->dxfWidth( *this, ctx ); } QString lineStyleName = "CONTINUOUS"; if ( mSymbologyExport != NoSymbology ) { lineStyleName = lineStyleFromSymbolLayer( symbolLayer ); } QGis::WkbType geometryType = geom->wkbType(); //single point if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D ) { writePoint( geom->asPoint(), layer, c, fet, symbolLayer, symbol ); } //multipoint if ( geometryType == QGis::WKBMultiPoint || geometryType == QGis::WKBMultiPoint25D ) { QgsMultiPoint multiPoint = geom->asMultiPoint(); QgsMultiPoint::const_iterator it = multiPoint.constBegin(); for ( ; it != multiPoint.constEnd(); ++it ) { writePoint( *it, layer, c, fet, symbolLayer, symbol ); } } //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { writePolyline( geom->asPolyline(), layer, lineStyleName, c, width, false ); } //multiline if ( geometryType == QGis::WKBMultiLineString || geometryType == QGis::WKBMultiLineString25D ) { QgsMultiPolyline multiLine = geom->asMultiPolyline(); QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); for ( ; lIt != multiLine.constEnd(); ++lIt ) { writePolyline( *lIt, layer, lineStyleName, c, width, false ); } } //polygon if ( geometryType == QGis::WKBPolygon || geometryType == QGis::WKBPolygon25D ) { QgsPolygon polygon = geom->asPolygon(); QgsPolygon::const_iterator polyIt = polygon.constBegin(); for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings { writePolyline( *polyIt, layer, lineStyleName, c, width, true ); } } //multipolygon or polygon if ( geometryType == QGis::WKBMultiPolygon || geometryType == QGis::WKBMultiPolygon25D ) { QgsMultiPolygon mp = geom->asMultiPolygon(); QgsMultiPolygon::const_iterator mpIt = mp.constBegin(); for ( ; mpIt != mp.constEnd(); ++mpIt ) { QgsPolygon::const_iterator polyIt = mpIt->constBegin(); for ( ; polyIt != mpIt->constEnd(); ++polyIt ) { writePolyline( *polyIt, layer, lineStyleName, c, width, true ); } } } } }
QgsGeometry* QgsTransectSample::clipBufferLine( QgsGeometry* stratumGeom, QgsGeometry* clippedBaseline, double tolerance ) { if ( !stratumGeom || !clippedBaseline || clippedBaseline->wkbType() == QGis::WKBUnknown ) { return 0; } double currentBufferDist = tolerance; int maxLoops = 10; for ( int i = 0; i < maxLoops; ++i ) { //loop with tolerance: create buffer, convert buffer to line, clip line by stratum, test if result is (single) line QgsGeometry* clipBaselineBuffer = clippedBaseline->buffer( currentBufferDist, 8 ); if ( !clipBaselineBuffer ) { delete clipBaselineBuffer; continue; } //it is also possible that clipBaselineBuffer is a multipolygon QgsGeometry* bufferLine = 0; //buffer line or multiline QgsGeometry* bufferLineClipped = 0; QgsMultiPolyline mpl; if ( clipBaselineBuffer->isMultipart() ) { QgsMultiPolygon bufferMultiPolygon = clipBaselineBuffer->asMultiPolygon(); if ( bufferMultiPolygon.size() < 1 ) { delete clipBaselineBuffer; continue; } for ( int j = 0; j < bufferMultiPolygon.size(); ++j ) { int size = bufferMultiPolygon.at( j ).size(); for ( int k = 0; k < size; ++k ) { mpl.append( bufferMultiPolygon.at( j ).at( k ) ); } } bufferLine = QgsGeometry::fromMultiPolyline( mpl ); } else { QgsPolygon bufferPolygon = clipBaselineBuffer->asPolygon(); if ( bufferPolygon.size() < 1 ) { delete clipBaselineBuffer; continue; } int size = bufferPolygon.size(); for ( int j = 0; j < size; ++j ) { mpl.append( bufferPolygon[j] ); } bufferLine = QgsGeometry::fromMultiPolyline( mpl ); } bufferLineClipped = bufferLine->intersection( stratumGeom ); if ( bufferLineClipped && bufferLineClipped->type() == QGis::Line ) { //if stratumGeom is a multipolygon, bufferLineClipped must intersect each part bool bufferLineClippedIntersectsStratum = true; if ( stratumGeom->wkbType() == QGis::WKBMultiPolygon || stratumGeom->wkbType() == QGis::WKBMultiPolygon25D ) { QVector<QgsPolygon> multiPoly = stratumGeom->asMultiPolygon(); QVector<QgsPolygon>::const_iterator multiIt = multiPoly.constBegin(); for ( ; multiIt != multiPoly.constEnd(); ++multiIt ) { QgsGeometry* poly = QgsGeometry::fromPolygon( *multiIt ); if ( !poly->intersects( bufferLineClipped ) ) { bufferLineClippedIntersectsStratum = false; delete poly; break; } delete poly; } } if ( bufferLineClippedIntersectsStratum ) { return bufferLineClipped; } } delete bufferLineClipped; delete clipBaselineBuffer; delete bufferLine; currentBufferDist /= 2; } return 0; //no solution found even with reduced tolerances }
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; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); QgsPolygon pol; QgsMultiPolygon mpol; QgsPolyline segm; QgsPolyline ls; QgsMultiPolyline mls; QList<FeatureLayer> fls; TopolErrorShort* err; double distance; for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) { emit progress( i ); } if ( testCancelled() ) { break; } QgsGeometry* g1 = it->feature.geometry(); // switching by type here, because layer can contain both single and multi version geometries switch ( g1->wkbType() ) { case QGis::WKBLineString: case QGis::WKBLineString25D: ls = g1->asPolyline(); for ( int i = 1; i < ls.size(); ++i ) { distance = 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::fromPolyline( 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 QGis::WKBPolygon: case QGis::WKBPolygon25D: pol = g1->asPolygon(); for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = 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::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: mls = g1->asMultiPolyline(); for ( int k = 0; k < mls.size(); ++k ) { QgsPolyline& ls = mls[k]; for ( int i = 1; i < ls.size(); ++i ) { distance = 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::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: mpol = g1->asMultiPolygon(); for ( int k = 0; k < mpol.size(); ++k ) { QgsPolygon& 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::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } } break; default: continue; } } 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; }
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: { QgsDebugMsg( "validation thread started." ); 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 ) { QgsMultiPolyline 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 ) { QgsMultiPolygon 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++; } 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 break; } } }
void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const { QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ]; QgsFeature feature; if ( !featurePool->getFeature( error->featureId(), feature ) ) { error->setObsolete(); return; } QgsGeometry featureGeom = feature.geometry(); QgsAbstractGeometry *geom = featureGeom.get(); QgsVertexId vidx = error->vidx(); // Check if ring still exists if ( !vidx.isValid( geom ) ) { error->setObsolete(); return; } const QgsGeometryUtils::SelfIntersection &inter = static_cast<QgsGeometrySelfIntersectionCheckError *>( error )->intersection(); // Check if error still applies bool ringIsClosed = false; int nVerts = QgsGeometryCheckerUtils::polyLineSize( geom, vidx.part, vidx.ring, &ringIsClosed ); if ( nVerts == 0 || inter.segment1 >= nVerts || inter.segment2 >= nVerts ) { error->setObsolete(); return; } QgsPoint p1 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, inter.segment1 ) ); QgsPoint q1 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, inter.segment2 ) ); QgsPoint p2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment1 + 1 ) % nVerts ) ); QgsPoint q2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment2 + 1 ) % nVerts ) ); QgsPoint s; bool intersection = false; if ( !QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, s, intersection, mContext->tolerance ) ) { error->setObsolete(); return; } // Fix with selected method if ( method == NoChange ) { error->setFixed( method ); } else if ( method == ToMultiObject || method == ToSingleObjects ) { // Extract rings QgsPointSequence ring1, ring2; bool ring1EndsWithS = false; bool ring2EndsWithS = false; for ( int i = 0; i < nVerts; ++i ) { if ( i <= inter.segment1 || i >= inter.segment2 + 1 ) { ring1.append( geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, i ) ) ); ring1EndsWithS = false; if ( i == inter.segment2 + 1 ) { ring2.append( s ); ring2EndsWithS = true; } } else { ring2.append( geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, i ) ) ); ring2EndsWithS = true; if ( i == inter.segment1 + 1 ) { ring1.append( s ); ring1EndsWithS = false; } } } if ( nVerts == inter.segment2 + 1 ) { ring2.append( s ); ring2EndsWithS = true; } if ( ringIsClosed || ring1EndsWithS ) ring1.append( ring1.front() ); // Ensure ring is closed if ( ringIsClosed || ring2EndsWithS ) ring2.append( ring2.front() ); // Ensure ring is closed if ( ring1.size() < 3 + ( ringIsClosed || ring1EndsWithS ) || ring2.size() < 3 + ( ringIsClosed || ring2EndsWithS ) ) { error->setFixFailed( tr( "Resulting geometry is degenerate" ) ); return; } QgsLineString *ringGeom1 = new QgsLineString(); ringGeom1->setPoints( ring1 ); QgsLineString *ringGeom2 = new QgsLineString(); ringGeom2->setPoints( ring2 ); QgsAbstractGeometry *part = QgsGeometryCheckerUtils::getGeomPart( geom, vidx.part ); // If is a polygon... if ( dynamic_cast<QgsCurvePolygon *>( part ) ) { QgsCurvePolygon *poly = static_cast<QgsCurvePolygon *>( part ); // If self-intersecting ring is an interior ring, create separate holes if ( vidx.ring > 0 ) { poly->removeInteriorRing( vidx.ring ); poly->addInteriorRing( ringGeom1 ); poly->addInteriorRing( ringGeom2 ); changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeRemoved, vidx ) ); changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeAdded, QgsVertexId( vidx.part, poly->ringCount() - 2 ) ) ); changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeAdded, QgsVertexId( vidx.part, poly->ringCount() - 1 ) ) ); feature.setGeometry( featureGeom ); featurePool->updateFeature( feature ); } else { // If ring is exterior, build two polygons, and reassign interiors as necessary poly->setExteriorRing( ringGeom1 ); // If original feature was a linear polygon, also create the new part as a linear polygon QgsCurvePolygon *poly2 = dynamic_cast<QgsPolygon *>( part ) ? new QgsPolygon() : new QgsCurvePolygon(); poly2->setExteriorRing( ringGeom2 ); // Reassing interiors as necessary std::unique_ptr< QgsGeometryEngine > geomEnginePoly1 = QgsGeometryCheckerUtils::createGeomEngine( poly, mContext->tolerance ); std::unique_ptr< QgsGeometryEngine > geomEnginePoly2 = QgsGeometryCheckerUtils::createGeomEngine( poly2, mContext->tolerance ); for ( int n = poly->numInteriorRings(), i = n - 1; i >= 0; --i ) { if ( !geomEnginePoly1->contains( poly->interiorRing( i ) ) ) { if ( geomEnginePoly2->contains( poly->interiorRing( i ) ) ) { poly2->addInteriorRing( static_cast<QgsCurve *>( poly->interiorRing( i )->clone() ) ); // No point in adding ChangeAdded changes, since the entire poly2 is added anyways later on } poly->removeInteriorRing( i ); changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeRemoved, QgsVertexId( vidx.part, 1 + i ) ) ); } } if ( method == ToMultiObject ) { // If is already a geometry collection, just add the new polygon. if ( dynamic_cast<QgsGeometryCollection *>( geom ) ) { static_cast<QgsGeometryCollection *>( geom )->addGeometry( poly2 ); changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeChanged, QgsVertexId( vidx.part, vidx.ring ) ) ); changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geom->partCount() - 1 ) ) ); feature.setGeometry( featureGeom ); featurePool->updateFeature( feature ); } // Otherwise, create multipolygon else { QgsMultiPolygon *multiPoly = new QgsMultiPolygon(); multiPoly->addGeometry( poly->clone() ); multiPoly->addGeometry( poly2 ); feature.setGeometry( QgsGeometry( multiPoly ) ); featurePool->updateFeature( feature ); changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } } else // if ( method == ToSingleObjects ) { QgsFeature newFeature; newFeature.setAttributes( feature.attributes() ); newFeature.setGeometry( QgsGeometry( poly2 ) ); feature.setGeometry( featureGeom ); featurePool->updateFeature( feature ); featurePool->addFeature( newFeature ); changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeChanged, QgsVertexId( vidx.part, vidx.ring ) ) ); changes[error->layerId()][newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) ); } } } else if ( dynamic_cast<QgsCurve *>( part ) ) { if ( method == ToMultiObject ) { if ( dynamic_cast<QgsGeometryCollection *>( geom ) ) { QgsGeometryCollection *geomCollection = static_cast<QgsGeometryCollection *>( geom ); geomCollection->removeGeometry( vidx.part ); geomCollection->addGeometry( ringGeom1 ); geomCollection->addGeometry( ringGeom2 ); feature.setGeometry( featureGeom ); featurePool->updateFeature( feature ); changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( vidx.part ) ) ); changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 2 ) ) ); changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) ); } else { QgsMultiCurve *geomCollection = new QgsMultiLineString(); geomCollection->addGeometry( ringGeom1 ); geomCollection->addGeometry( ringGeom2 ); feature.setGeometry( QgsGeometry( geomCollection ) ); featurePool->updateFeature( feature ); changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) ); } } else // if(method == ToSingleObjects) { if ( dynamic_cast<QgsGeometryCollection *>( geom ) ) { QgsGeometryCollection *geomCollection = static_cast<QgsGeometryCollection *>( geom ); geomCollection->removeGeometry( vidx.part ); geomCollection->addGeometry( ringGeom1 ); feature.setGeometry( featureGeom ); featurePool->updateFeature( feature ); changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( vidx.part ) ) ); changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) ); } else { feature.setGeometry( QgsGeometry( ringGeom1 ) ); featurePool->updateFeature( feature ); changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged, QgsVertexId( vidx.part ) ) ); } QgsFeature newFeature; newFeature.setAttributes( feature.attributes() ); newFeature.setGeometry( QgsGeometry( ringGeom2 ) ); featurePool->addFeature( newFeature ); changes[error->layerId()][newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) ); } } else { delete ringGeom1; delete ringGeom2; } error->setFixed( method ); } else { error->setFixFailed( tr( "Unknown method" ) ); } }
void QgsRubberBand::addGeometry( QgsGeometry* geom, QgsVectorLayer* layer ) { if ( !geom ) { return; } //maprender object of canvas QgsMapRenderer* mr = mMapCanvas->mapRenderer(); if ( !mr ) { return; } int idx = mPoints.size(); switch ( geom->wkbType() ) { case QGis::WKBPoint: case QGis::WKBPoint25D: { double d = mMapCanvas->extent().width() * 0.005; QgsPoint pt; if ( layer ) { pt = mr->layerToMapCoordinates( layer, geom->asPoint() ); } else { pt = geom->asPoint(); } addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx ); addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx ); addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx ); addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx ); } break; case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: { double d = mMapCanvas->extent().width() * 0.005; QgsMultiPoint mpt = geom->asMultiPoint(); for ( int i = 0; i < mpt.size(); ++i, ++idx ) { QgsPoint pt = mpt[i]; if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() - d ) ), false, idx ); addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() - d ) ), false, idx ); addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() + d ) ), false, idx ); addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() + d ) ), false, idx ); } else { addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx ); addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx ); addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx ); addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx ); } } } break; case QGis::WKBLineString: case QGis::WKBLineString25D: { QgsPolyline line = geom->asPolyline(); for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: { mPoints.clear(); QgsMultiPolyline mline = geom->asMultiPolyline(); for ( int i = 0; i < mline.size(); ++i, ++idx ) { QgsPolyline line = mline[i]; if ( line.size() == 0 ) { --idx; } for ( int j = 0; j < line.size(); ++j ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: { QgsPolygon poly = geom->asPolygon(); QgsPolyline line = poly[0]; for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: { mPoints.clear(); QgsMultiPolygon multipoly = geom->asMultiPolygon(); for ( int i = 0; i < multipoly.size(); ++i, ++idx ) { QgsPolygon poly = multipoly[i]; QgsPolyline line = poly[0]; for ( int j = 0; j < line.count(); ++j ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QGis::WKBUnknown: default: return; } updateRect(); update(); }