QgsGeometry QgsGeometryAnalyzer::createOffsetGeometry( const QgsGeometry& geom, const QgsGeometry& lineGeom, double offset ) { if ( !geom || lineGeom.isEmpty() ) { return QgsGeometry(); } QList<QgsGeometry> inputGeomList; if ( geom.isMultipart() ) { inputGeomList = geom.asGeometryCollection(); } else { inputGeomList.push_back( geom ); } QList<GEOSGeometry*> outputGeomList; QList<QgsGeometry>::const_iterator inputGeomIt = inputGeomList.constBegin(); GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt ) { if ( geom.type() == QgsWkbTypes::LineGeometry ) { GEOSGeometry* inputGeomItGeos = inputGeomIt->exportToGeos(); GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, inputGeomItGeos, -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); GEOSGeom_destroy_r( geosctxt, inputGeomItGeos ); if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) ) { return QgsGeometry(); } if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 ) { GEOSGeom_destroy_r( geosctxt, offsetGeom ); return QgsGeometry(); } outputGeomList.push_back( offsetGeom ); } else if ( geom.type() == QgsWkbTypes::PointGeometry ) { QgsPoint p = ( *inputGeomIt ).asPoint(); p = createPointOffset( p.x(), p.y(), offset, lineGeom ); GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() ); GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() ); GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq ); outputGeomList.push_back( geosPt ); } } QgsGeometry outGeometry; if ( !geom.isMultipart() ) { GEOSGeometry* outputGeom = outputGeomList.at( 0 ); if ( outputGeom ) { outGeometry.fromGeos( outputGeom ); } } else { GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()]; for ( int i = 0; i < outputGeomList.size(); ++i ) { geomArray[i] = outputGeomList.at( i ); } GEOSGeometry* collection = nullptr; if ( geom.type() == QgsWkbTypes::PointGeometry ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() ); } else if ( geom.type() == QgsWkbTypes::LineGeometry ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() ); } outGeometry.fromGeos( collection ); delete[] geomArray; } return outGeometry; }
bool QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset ) { if ( !geom || !lineGeom ) { return false; } QList<QgsGeometry*> inputGeomList; if ( geom->isMultipart() ) { inputGeomList = geom->asGeometryCollection(); } else { inputGeomList.push_back( geom ); } QList<GEOSGeometry*> outputGeomList; QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin(); GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler(); for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt ) { if ( geom->type() == QGis::Line ) { //geos 3.3 needed for line offsets #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, ( *inputGeomIt )->asGeos(), -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) ) { return false; } if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 ) { GEOSGeom_destroy_r( geosctxt, offsetGeom ); return false; } outputGeomList.push_back( offsetGeom ); #else outputGeomList.push_back( GEOSGeom_clone_r( geosctxt, ( *inputGeomIt )->asGeos() ) ); #endif } else if ( geom->type() == QGis::Point ) { QgsPoint p = ( *inputGeomIt )->asPoint(); p = createPointOffset( p.x(), p.y(), offset, lineGeom ); GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 ); GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() ); GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() ); GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq ); outputGeomList.push_back( geosPt ); } } if ( !geom->isMultipart() ) { GEOSGeometry* outputGeom = outputGeomList.at( 0 ); if ( outputGeom ) { geom->fromGeos( outputGeom ); } } else { GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()]; for ( int i = 0; i < outputGeomList.size(); ++i ) { geomArray[i] = outputGeomList.at( i ); } GEOSGeometry* collection = 0; if ( geom->type() == QGis::Point ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() ); } else if ( geom->type() == QGis::Line ) { collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() ); } geom->fromGeos( collection ); delete[] geomArray; } return true; }