diff --git a/python/core/qgsgeometry.sip b/python/core/qgsgeometry.sip index 04c24605f68..8a9893de051 100644 --- a/python/core/qgsgeometry.sip +++ b/python/core/qgsgeometry.sip @@ -314,7 +314,21 @@ class QgsGeometry of segments used to approximate curves */ QgsGeometry* buffer( double distance, int segments ) /Factory/; - /** Returns an offset line at a given distance and side from an input line. */ + /** Returns a buffer region around the geometry, with additional style options. + * @param segments For round joins, number of segments to approximate quarter-circle + * @param endCapStyle Round (1) / Flat (2) / Square (3) end cap style + * @param joinStyle Round (1) / Mitre (2) / Bevel (3) join style + * @param mitreLimit Limit on the mitre ratio used for very sharp corners + * @note added in 2.4 + * @note needs GEOS >= 3.3 - otherwise always returns 0 + */ + QgsGeometry* buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) /Factory/; + + /** Returns an offset line at a given distance and side from an input line. + * See buffer() method for details on parameters. + * @note added in 2.4 + * @note needs GEOS >= 3.3 - otherwise always returns 0 + */ QgsGeometry* offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) /Factory/; /** Returns a simplified version of this geometry using a specified tolerance value */ diff --git a/src/core/qgsgeometry.cpp b/src/core/qgsgeometry.cpp index 65a1c944226..20e75aa5450 100644 --- a/src/core/qgsgeometry.cpp +++ b/src/core/qgsgeometry.cpp @@ -5594,10 +5594,30 @@ QgsGeometry* QgsGeometry::buffer( double distance, int segments ) CATCH_GEOS( 0 ) } +QgsGeometry*QgsGeometry::buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ) +{ #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) + if ( mDirtyGeos ) + exportWkbToGeos(); + + if ( !mGeos ) + return 0; + + try + { + return fromGeosGeom( GEOSBufferWithStyle( mGeos, distance, segments, endCapStyle, joinStyle, mitreLimit ) ); + } + CATCH_GEOS( 0 ) +#else + return 0; +#endif +} + QgsGeometry* QgsGeometry::offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ) { +#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ + ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) if ( mDirtyGeos ) exportWkbToGeos(); @@ -5609,8 +5629,10 @@ QgsGeometry* QgsGeometry::offsetCurve( double distance, int segments, int joinSt return fromGeosGeom( GEOSOffsetCurve( mGeos, distance, segments, joinStyle, mitreLimit ) ); } CATCH_GEOS( 0 ) -} +#else + return 0; #endif +} QgsGeometry* QgsGeometry::simplify( double tolerance ) { diff --git a/src/core/qgsgeometry.h b/src/core/qgsgeometry.h index cba1202cef7..bf522a7e458 100644 --- a/src/core/qgsgeometry.h +++ b/src/core/qgsgeometry.h @@ -355,14 +355,22 @@ class CORE_EXPORT QgsGeometry of segments used to approximate curves */ QgsGeometry* buffer( double distance, int segments ); -#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ - ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3))) - /** Returns an offset line at a given distance and side from an input line (uses GEOS) - @note added in 2.3 - @note only available with GEOS >= 3.3 - */ + /** Returns a buffer region around the geometry, with additional style options. + * @param segments For round joins, number of segments to approximate quarter-circle + * @param endCapStyle Round (1) / Flat (2) / Square (3) end cap style + * @param joinStyle Round (1) / Mitre (2) / Bevel (3) join style + * @param mitreLimit Limit on the mitre ratio used for very sharp corners + * @note added in 2.4 + * @note needs GEOS >= 3.3 - otherwise always returns 0 + */ + QgsGeometry* buffer( double distance, int segments, int endCapStyle, int joinStyle, double mitreLimit ); + + /** Returns an offset line at a given distance and side from an input line. + * See buffer() method for details on parameters. + * @note added in 2.4 + * @note needs GEOS >= 3.3 - otherwise always returns 0 + */ QgsGeometry* offsetCurve( double distance, int segments, int joinStyle, double mitreLimit ); -#endif /** Returns a simplified version of this geometry using a specified tolerance value */ QgsGeometry* simplify( double tolerance ); diff --git a/src/core/symbology-ng/qgssymbollayerv2utils.cpp b/src/core/symbology-ng/qgssymbollayerv2utils.cpp index 677992a2287..ab028d34b5b 100644 --- a/src/core/symbology-ng/qgssymbollayerv2utils.cpp +++ b/src/core/symbology-ng/qgssymbollayerv2utils.cpp @@ -708,7 +708,13 @@ QList offsetLine( QPolygonF polyline, double dist, QGis::GeometryType QgsGeometry* tempGeometry = ( geometryType == QGis::Polygon ) ? QgsGeometry::fromPolygon( QgsPolygon() << tempPolyline ) : QgsGeometry::fromPolyline( tempPolyline ); if ( tempGeometry ) { - QgsGeometry* offsetGeom = ( geometryType == QGis::Polygon ) ? tempGeometry->buffer( -dist, 8 /*quadSegments*/ ) : tempGeometry->offsetCurve( dist, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ); + int quadSegments = 0; // we want mitre joins, not round joins + double mitreLimit = 2.0; // the default value in GEOS (5.0) allows for fairly sharp endings + QgsGeometry* offsetGeom = 0; + if ( geometryType == QGis::Polygon ) + offsetGeom = tempGeometry->buffer( -dist, quadSegments, GEOSBUF_CAP_FLAT, GEOSBUF_JOIN_MITRE, mitreLimit ); + else + offsetGeom = tempGeometry->offsetCurve( dist, quadSegments, GEOSBUF_JOIN_MITRE, mitreLimit ); if ( offsetGeom ) {