std::unique_ptr<QgsMultiLineString> QgsGeometryFactory::fromMultiPolyline( const QgsMultiPolyline &multiline ) { std::unique_ptr< QgsMultiLineString > mLine( new QgsMultiLineString() ); for ( int i = 0; i < multiline.size(); ++i ) { mLine->addGeometry( fromPolyline( multiline.at( i ) ).release() ); } return mLine; }
QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, QgsGeometry* lineGeom ) { if ( !lineGeom ) { return 0; } QgsMultiPolyline resultGeom; //need to go with WKB and z coordinate until QgsGeometry supports M values unsigned char* lineWkb = lineGeom->asWkb(); unsigned char* ptr = lineWkb + 1; QGis::WkbType wkbType; memcpy( &wkbType, ptr, sizeof( wkbType ) ); ptr += sizeof( wkbType ); if ( wkbType != QGis::WKBLineString25D && wkbType != QGis::WKBMultiLineString25D ) { return 0; } if ( wkbType == QGis::WKBLineString25D ) { locateBetweenWkbString( ptr, resultGeom, fromMeasure, toMeasure ); } else if ( wkbType == QGis::WKBMultiLineString25D ) { int* nLines = ( int* )ptr; ptr += sizeof( int ); for ( int i = 0; i < *nLines; ++i ) { ptr += ( 1 + sizeof( wkbType ) ); ptr = locateBetweenWkbString( ptr, resultGeom, fromMeasure, toMeasure ); } } if ( resultGeom.size() < 1 ) { return 0; } return QgsGeometry::fromMultiPolyline( resultGeom ); }
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 QgsRubberBand::addGeometry( const QgsGeometry& geom, QgsVectorLayer* layer ) { if ( geom.isEmpty() ) { return; } //maprender object of canvas const QgsMapSettings& ms = mMapCanvas->mapSettings(); int idx = mPoints.size(); switch ( geom.wkbType() ) { case QgsWkbTypes::Point: case QgsWkbTypes::Point25D: { QgsPoint pt; if ( layer ) { pt = ms.layerToMapCoordinates( layer, geom.asPoint() ); } else { pt = geom.asPoint(); } addPoint( pt, false, idx ); removeLastPoint( idx, false ); } break; case QgsWkbTypes::MultiPoint: case QgsWkbTypes::MultiPoint25D: { 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 QgsWkbTypes::LineString: case QgsWkbTypes::LineString25D: { 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 QgsWkbTypes::MultiLineString: case QgsWkbTypes::MultiLineString25D: { QgsMultiPolyline mline = geom.asMultiPolyline(); for ( int i = 0; i < mline.size(); ++i, ++idx ) { QgsPolyline line = mline[i]; if ( line.isEmpty() ) { --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 QgsWkbTypes::Polygon: case QgsWkbTypes::Polygon25D: { 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 QgsWkbTypes::MultiPolygon: case QgsWkbTypes::MultiPolygon25D: { 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 QgsWkbTypes::Unknown: default: return; } setVisible( true ); updateRect(); update(); }
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: { QgsPoint pt; if ( layer ) { pt = mr->layerToMapCoordinates( layer, geom->asPoint() ); } else { pt = geom->asPoint(); } addPoint( pt, false, idx ); } 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( mr->layerToMapCoordinates( layer, pt ), false, idx ); } else { addPoint( pt, 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(); }
/*! 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; } }
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; }
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; }