Skip to content
Permalink
Browse files
Add api to condense compound curves by merging adjacent parts of the
same type to single parts
  • Loading branch information
nyalldawson committed Apr 28, 2021
1 parent b65e37a commit 417d44442901794f9670b02e9b0f6bb26078e388
@@ -117,6 +117,14 @@ Removes a curve from the geometry.
void addVertex( const QgsPoint &pt );
%Docstring
Adds a vertex to the end of the geometry.
%End

void condenseCurves();
%Docstring
Condenses the curves in this geometry by combining adjacent linestrings a to a single continuous linestring,
and combining adjacent circularstrings to a single continuous circularstring.

.. versionadded:: 3.20
%End

virtual void draw( QPainter &p ) const;
@@ -638,6 +638,35 @@ void QgsCompoundCurve::addVertex( const QgsPoint &pt )
clearCache();
}

void QgsCompoundCurve::condenseCurves()
{
QgsCurve *lastCurve = nullptr;
QVector< QgsCurve * > newCurves;
newCurves.reserve( mCurves.size() );
for ( QgsCurve *curve : std::as_const( mCurves ) )
{
if ( lastCurve && lastCurve->wkbType() == curve->wkbType() )
{
if ( QgsLineString *ls = qgsgeometry_cast< QgsLineString * >( lastCurve ) )
{
ls->append( qgsgeometry_cast< QgsLineString * >( curve ) );
delete curve;
}
else if ( QgsCircularString *cs = qgsgeometry_cast< QgsCircularString * >( lastCurve ) )
{
cs->append( qgsgeometry_cast< QgsCircularString * >( curve ) );
delete curve;
}
}
else
{
lastCurve = curve;
newCurves << curve;
}
}
mCurves = newCurves;
}

void QgsCompoundCurve::draw( QPainter &p ) const
{
for ( const QgsCurve *curve : mCurves )
@@ -107,6 +107,14 @@ class CORE_EXPORT QgsCompoundCurve: public QgsCurve
*/
void addVertex( const QgsPoint &pt );

/**
* Condenses the curves in this geometry by combining adjacent linestrings a to a single continuous linestring,
* and combining adjacent circularstrings to a single continuous circularstring.
*
* \since QGIS 3.20
*/
void condenseCurves();

void draw( QPainter &p ) const override;
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
@@ -134,7 +134,11 @@ class TestQgsGeometry : public QObject
void ellipse();
void quadrilateral();
void regularPolygon();
void compoundCurve(); //test QgsCompoundCurve

void compoundCurve();
void compoundCurveCondense_data();
void compoundCurveCondense();

void multiPoint();
void multiLineString();
void multiCurve();
QCOMPARE( orientation.orientation(), QgsCurve::CounterClockwise );
}

void TestQgsGeometry::compoundCurveCondense_data()
{
QTest::addColumn<QString>( "curve" );
QTest::addColumn<QString>( "expected" );

QTest::newRow( "compound curve empty" ) << QStringLiteral( "COMPOUNDCURVE()" ) << QStringLiteral( "CompoundCurve EMPTY" );
QTest::newRow( "compound curve one line" ) << QStringLiteral( "COMPOUNDCURVE((1 1, 1 2))" ) << QStringLiteral( "CompoundCurve ((1 1, 1 2))" );
QTest::newRow( "compound curve one circular string" ) << QStringLiteral( "COMPOUNDCURVE(CIRCULARSTRING(1 1, 1 2, 2 2))" ) << QStringLiteral( "CompoundCurve (CircularString (1 1, 1 2, 2 2))" );
QTest::newRow( "compound curve can't condense" ) << QStringLiteral( "COMPOUNDCURVE((1 5, 1 4, 1 1),CIRCULARSTRING(1 1, 1 2, 2 2),(2 2, 2 3),CIRCULARSTRING(2 3, 2 0, 2 1))" ) << QStringLiteral( "CompoundCurve ((1 5, 1 4, 1 1),CircularString (1 1, 1 2, 2 2),(2 2, 2 3),CircularString (2 3, 2 0, 2 1))" );
QTest::newRow( "compound curve two lines" ) << QStringLiteral( "COMPOUNDCURVE((1 5, 1 4, 1 1),(1 1, 1 0, 3 0))" ) << QStringLiteral( "CompoundCurve ((1 5, 1 4, 1 1, 1 0, 3 0))" );
QTest::newRow( "compound curve three lines" ) << QStringLiteral( "COMPOUNDCURVE((1 5, 1 4, 1 1),(1 1, 1 0, 3 0),(3 0, 4 0, 5 0))" ) << QStringLiteral( "CompoundCurve ((1 5, 1 4, 1 1, 1 0, 3 0, 4 0, 5 0))" );
QTest::newRow( "compound curve two lines and cs" ) << QStringLiteral( "COMPOUNDCURVE((1 5, 1 4, 1 1),(1 1, 1 0, 3 0),CIRCULARSTRING(3 0, 4 0, 5 0))" ) << QStringLiteral( "CompoundCurve ((1 5, 1 4, 1 1, 1 0, 3 0),CircularString (3 0, 4 0, 5 0))" );
QTest::newRow( "compound curve two cs" ) << QStringLiteral( "COMPOUNDCURVE(CIRCULARSTRING(1 5, 1 4, 1 1),CIRCULARSTRING(1 1, 1 0, 3 0))" ) << QStringLiteral( "CompoundCurve (CircularString (1 5, 1 4, 1 1, 1 0, 3 0))" );
QTest::newRow( "compound curve complex" ) << QStringLiteral( "COMPOUNDCURVE((1 5, 1 4, 1 1),(1 1, 1 0, 3 0),CIRCULARSTRING(3 0, 4 0, 5 0),(5 0, 6 0),(6 0, 7 0),CIRCULARSTRING(7 0, 8 0, 9 0),CIRCULARSTRING(9 0, 10 1, 10 0),(10 0, 10 -1))" ) << QStringLiteral( "CompoundCurve ((1 5, 1 4, 1 1, 1 0, 3 0),CircularString (3 0, 4 0, 5 0),(5 0, 6 0, 7 0),CircularString (7 0, 8 0, 9 0, 10 1, 10 0),(10 0, 10 -1))" );
}

void TestQgsGeometry::compoundCurveCondense()
{
QFETCH( QString, curve );
QFETCH( QString, expected );

QgsGeometry g = QgsGeometry::fromWkt( curve );
qgsgeometry_cast< QgsCompoundCurve * >( g.get() )->condenseCurves();

QCOMPARE( g.asWkt(), expected );
}

void TestQgsGeometry::multiPoint()
{
//test constructor

0 comments on commit 417d444

Please sign in to comment.