Skip to content

Commit

Permalink
[needs-docs] geometry smooth algorithm now also retains and smooths z…
Browse files Browse the repository at this point in the history
…/m values

...instead of just discarding them

Applies to processing algorithm and expression function (and
QgsGeometry::smooth method)
  • Loading branch information
nyalldawson committed Mar 29, 2018
1 parent bf252d6 commit f02602b
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 5 deletions.
3 changes: 3 additions & 0 deletions python/core/geometry/qgsgeometry.sip.in
Expand Up @@ -1668,6 +1668,9 @@ tolerance
Smooths a geometry by rounding off corners using the Chaikin algorithm. This operation
roughly doubles the number of vertices in a geometry.

If input geometries contain Z or M values, these will also be smoothed and the output
geometry will retain the same dimensionality as the input geometry.

:param iterations: number of smoothing iterations to run. More iterations results
in a smoother geometry
:param offset: fraction of line to create new vertices along, between 0 and 1.0,
Expand Down
2 changes: 1 addition & 1 deletion resources/function_help/json/smooth
@@ -1,7 +1,7 @@
{
"name": "smooth",
"type": "function",
"description":"Smooths a geometry by adding extra nodes which round off corners in the geometry.",
"description":"Smooths a geometry by adding extra nodes which round off corners in the geometry. If input geometries contain Z or M values, these will also be smoothed and the output geometry will retain the same dimensionality as the input geometry.",
"arguments": [ {"arg":"geometry","description":"a geometry"},
{"arg":"iterations", "optional":true,"description":"number of smoothing iterations to apply. Larger numbers result in smoother but more complex geometries."},
{"arg":"offset", "optional":true,"description":"value between 0 and 0.5 which controls how tightly the smoothed geometry follow the original geometry. Smaller values result in a tighter smoothing, larger values result in looser smoothing."},
Expand Down
4 changes: 3 additions & 1 deletion src/analysis/processing/qgsalgorithmsmooth.cpp
Expand Up @@ -67,7 +67,9 @@ QString QgsSmoothAlgorithm::shortHelpString() const
"The maximum angle parameter can be used to prevent smoothing of "
"nodes with large angles. Any node where the angle of the segments to either "
"side is larger than this will not be smoothed. For example, setting the maximum "
"angle to 90 degrees or lower would preserve right angles in the geometry." );
"angle to 90 degrees or lower would preserve right angles in the geometry.\n\n"
"If input geometries contain Z or M values, these will also be smoothed and the output "
"geometry will retain the same dimensionality as the input geometry." );
}

QgsSmoothAlgorithm *QgsSmoothAlgorithm::createInstance() const
Expand Down
9 changes: 6 additions & 3 deletions src/core/geometry/qgsgeometry.cpp
Expand Up @@ -2711,9 +2711,12 @@ QgsGeometry QgsGeometry::smooth( const unsigned int iterations, const double off

inline QgsPoint interpolatePointOnLine( const QgsPoint &p1, const QgsPoint &p2, const double offset )
{
double deltaX = p2.x() - p1.x();
double deltaY = p2.y() - p1.y();
return QgsPoint( p1.x() + deltaX * offset, p1.y() + deltaY * offset );
const double _offset = 1 - offset;
return QgsPoint( p1.wkbType(),
p1.x() * _offset + p2.x() * offset,
p1.y() * _offset + p2.y() * offset,
p1.is3D() ? p1.z() * _offset + p2.z() * offset : std::numeric_limits<double>::quiet_NaN(),
p1.isMeasure() ? p1.m() * _offset + p2.m() * offset : std::numeric_limits<double>::quiet_NaN() );
}

std::unique_ptr< QgsLineString > smoothCurve( const QgsLineString &line, const unsigned int iterations,
Expand Down
4 changes: 4 additions & 0 deletions src/core/geometry/qgsgeometry.h
Expand Up @@ -1675,6 +1675,10 @@ class CORE_EXPORT QgsGeometry
/**
* Smooths a geometry by rounding off corners using the Chaikin algorithm. This operation
* roughly doubles the number of vertices in a geometry.
*
* If input geometries contain Z or M values, these will also be smoothed and the output
* geometry will retain the same dimensionality as the input geometry.
*
* \param iterations number of smoothing iterations to run. More iterations results
* in a smoother geometry
* \param offset fraction of line to create new vertices along, between 0 and 1.0,
Expand Down
36 changes: 36 additions & 0 deletions tests/src/core/testqgsgeometry.cpp
Expand Up @@ -15606,6 +15606,24 @@ void TestQgsGeometry::smoothCheck()
<< QgsPointXY( 10.0, 7.5 ) << QgsPointXY( 12.5, 10.0 ) << QgsPointXY( 20.0, 10.0 );
QVERIFY( QgsGeometry::compare( line, expectedLine ) );

//linestringM
wkt = QStringLiteral( "LineStringM(0 0 1, 10 0 2, 10 10 6, 20 10 4)" );
geom = QgsGeometry::fromWkt( wkt );
result = geom.smooth( 1, 0.25 );
QCOMPARE( result.asWkt(), QStringLiteral( "LineStringM (0 0 1, 7.5 0 1.75, 10 2.5 3, 10 7.5 5, 12.5 10 5.5, 20 10 4)" ) );

//linestringZ
wkt = QStringLiteral( "LineStringZ(0 0 1, 10 0 2, 10 10 6, 20 10 4)" );
geom = QgsGeometry::fromWkt( wkt );
result = geom.smooth( 1, 0.25 );
QCOMPARE( result.asWkt(), QStringLiteral( "LineStringZ (0 0 1, 7.5 0 1.75, 10 2.5 3, 10 7.5 5, 12.5 10 5.5, 20 10 4)" ) );

//linestringZM
wkt = QStringLiteral( "LineStringZM(0 0 1 4, 10 0 2 8, 10 10 6 2, 20 10 4 0)" );
geom = QgsGeometry::fromWkt( wkt );
result = geom.smooth( 1, 0.25 );
QCOMPARE( result.asWkt(), QStringLiteral( "LineStringZM (0 0 1 4, 7.5 0 1.75 7, 10 2.5 3 6.5, 10 7.5 5 3.5, 12.5 10 5.5 1.5, 20 10 4 0)" ) );

//linestring, with min distance
wkt = QStringLiteral( "LineString(0 0, 10 0, 10 10, 15 10, 15 20)" );
geom = QgsGeometry::fromWkt( wkt );
Expand Down Expand Up @@ -15670,6 +15688,24 @@ void TestQgsGeometry::smoothCheck()
<< QgsPointXY( 2.0, 3.5 ) << QgsPointXY( 2.0, 2.5 ) << QgsPointXY( 2.5, 2.0 ) );
QVERIFY( QgsGeometry::compare( poly, expectedPolygon ) );

//polygonM
wkt = QStringLiteral( "PolygonM ((0 0 1, 10 0 4, 10 10 6, 0 10 8, 0 0 1 ),(2 2 3, 4 2 5, 4 4 7, 2 4 9, 2 2 3))" );
geom = QgsGeometry::fromWkt( wkt );
result = geom.smooth( 1, 0.25 );
QCOMPARE( result.asWkt(), QStringLiteral( "PolygonM ((2.5 0 1.75, 7.5 0 3.25, 10 2.5 4.5, 10 7.5 5.5, 7.5 10 6.5, 2.5 10 7.5, 0 7.5 6.25, 0 2.5 2.75, 2.5 0 1.75),(2.5 2 3.5, 3.5 2 4.5, 4 2.5 5.5, 4 3.5 6.5, 3.5 4 7.5, 2.5 4 8.5, 2 3.5 7.5, 2 2.5 4.5, 2.5 2 3.5))" ) );

//polygonZ
wkt = QStringLiteral( "PolygonZ ((0 0 1, 10 0 4, 10 10 6, 0 10 8, 0 0 1 ),(2 2 3, 4 2 5, 4 4 7, 2 4 9, 2 2 3))" );
geom = QgsGeometry::fromWkt( wkt );
result = geom.smooth( 1, 0.25 );
QCOMPARE( result.asWkt(), QStringLiteral( "PolygonZ ((2.5 0 1.75, 7.5 0 3.25, 10 2.5 4.5, 10 7.5 5.5, 7.5 10 6.5, 2.5 10 7.5, 0 7.5 6.25, 0 2.5 2.75, 2.5 0 1.75),(2.5 2 3.5, 3.5 2 4.5, 4 2.5 5.5, 4 3.5 6.5, 3.5 4 7.5, 2.5 4 8.5, 2 3.5 7.5, 2 2.5 4.5, 2.5 2 3.5))" ) );

//polygonZM
wkt = QStringLiteral( "PolygonZ ((0 0 1 6, 10 0 4 2, 10 10 6 0, 0 10 8 4, 0 0 1 6 ))" );
geom = QgsGeometry::fromWkt( wkt );
result = geom.smooth( 1, 0.25 );
QCOMPARE( result.asWkt(), QStringLiteral( "PolygonZM ((2.5 0 1.75 5, 7.5 0 3.25 3, 10 2.5 4.5 1.5, 10 7.5 5.5 0.5, 7.5 10 6.5 1, 2.5 10 7.5 3, 0 7.5 6.25 4.5, 0 2.5 2.75 5.5, 2.5 0 1.75 5))" ) );

//polygon with max angle - should be unchanged
wkt = QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" );
geom = QgsGeometry::fromWkt( wkt );
Expand Down

0 comments on commit f02602b

Please sign in to comment.