Skip to content

Commit

Permalink
Fix #10605 (round corners when using simple line with offset)
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Jun 17, 2014
1 parent fb5cca2 commit ed1d08d
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 10 deletions.
16 changes: 15 additions & 1 deletion python/core/qgsgeometry.sip
Expand Up @@ -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 */
Expand Down
24 changes: 23 additions & 1 deletion src/core/qgsgeometry.cpp
Expand Up @@ -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();

Expand All @@ -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 )
{
Expand Down
22 changes: 15 additions & 7 deletions src/core/qgsgeometry.h
Expand Up @@ -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 );
Expand Down
8 changes: 7 additions & 1 deletion src/core/symbology-ng/qgssymbollayerv2utils.cpp
Expand Up @@ -708,7 +708,13 @@ QList<QPolygonF> 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 )
{
Expand Down

0 comments on commit ed1d08d

Please sign in to comment.