Skip to content

Commit

Permalink
Add convenience constructors to create QgsCircularStrings
Browse files Browse the repository at this point in the history
Add constructors to create a circular string with a single arc:
- from 3 points on arc
- from 2 points and a center
  • Loading branch information
nyalldawson committed Apr 23, 2018
1 parent 3f3b951 commit 732d6bb
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 0 deletions.
24 changes: 24 additions & 0 deletions python/core/geometry/qgscircularstring.sip.in
Expand Up @@ -23,7 +23,31 @@ class QgsCircularString: QgsCurve
#include "qgscircularstring.h"
%End
public:

QgsCircularString();
%Docstring
Constructs an empty circular string.
%End

QgsCircularString( const QgsPoint &p1,
const QgsPoint &p2,
const QgsPoint &p3 );
%Docstring
Constructs a circular string with a single
arc passing through ``p1``, ``p2`` and ``p3``.

.. versionadded:: 3.2
%End

static QgsCircularString fromTwoPointsAndCenter( const QgsPoint &p1,
const QgsPoint &p2,
const QgsPoint &center );
%Docstring
Creates a circular string with a single arc representing
the curve from ``p1`` to ``p2`` with the specified ``center``.

.. versionadded:: 3.2
%End

virtual bool equals( const QgsCurve &other ) const;

Expand Down
39 changes: 39 additions & 0 deletions src/core/geometry/qgscircularstring.cpp
Expand Up @@ -33,6 +33,45 @@ QgsCircularString::QgsCircularString()
mWkbType = QgsWkbTypes::CircularString;
}

QgsCircularString::QgsCircularString( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3 )
{
//get wkb type from first point
bool hasZ = p1.is3D();
bool hasM = p1.isMeasure();
mWkbType = QgsWkbTypes::CircularString;

mX.resize( 3 );
mX[ 0 ] = p1.x();
mX[ 1 ] = p2.x();
mX[ 2 ] = p3.x();
mY.resize( 3 );
mY[ 0 ] = p1.y();
mY[ 1 ] = p2.y();
mY[ 2 ] = p3.y();
if ( hasZ )
{
mWkbType = QgsWkbTypes::addZ( mWkbType );
mZ.resize( 3 );
mZ[ 0 ] = p1.z();
mZ[ 1 ] = p2.z();
mZ[ 2 ] = p3.z();
}
if ( hasM )
{
mWkbType = QgsWkbTypes::addM( mWkbType );
mM.resize( 3 );
mM[ 0 ] = p1.m();
mM[ 1 ] = p2.m();
mM[ 2 ] = p3.m();
}
}

QgsCircularString QgsCircularString::fromTwoPointsAndCenter( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &center )
{
const QgsPoint midPoint = QgsGeometryUtils::segmentMidPointFromCenter( p1, p2, center );
return QgsCircularString( p1, midPoint, p2 );
}

bool QgsCircularString::equals( const QgsCurve &other ) const
{
const QgsCircularString *otherLine = dynamic_cast< const QgsCircularString * >( &other );
Expand Down
24 changes: 24 additions & 0 deletions src/core/geometry/qgscircularstring.h
Expand Up @@ -34,8 +34,32 @@
class CORE_EXPORT QgsCircularString: public QgsCurve
{
public:

/**
* Constructs an empty circular string.
*/
QgsCircularString();

/**
* Constructs a circular string with a single
* arc passing through \a p1, \a p2 and \a p3.
*
* \since QGIS 3.2
*/
QgsCircularString( const QgsPoint &p1,
const QgsPoint &p2,
const QgsPoint &p3 );

/**
* Creates a circular string with a single arc representing
* the curve from \a p1 to \a p2 with the specified \a center.
*
* \since QGIS 3.2
*/
static QgsCircularString fromTwoPointsAndCenter( const QgsPoint &p1,
const QgsPoint &p2,
const QgsPoint &center );

bool equals( const QgsCurve &other ) const override;

QString geometryType() const override;
Expand Down
106 changes: 106 additions & 0 deletions tests/src/core/testqgsgeometry.cpp
Expand Up @@ -1158,6 +1158,112 @@ void TestQgsGeometry::circularString()
l1.points( pts );
QVERIFY( pts.empty() );

// from 3 points
QgsCircularString from3Pts( QgsPoint( 1, 2 ), QgsPoint( 21, 22 ), QgsPoint( 31, 2 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 21, 22, 23 ),
QgsPoint( QgsWkbTypes::PointZ, 31, 2, 33 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZ );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 23 ),
QgsPoint( QgsWkbTypes::PointM, 31, 2, 0, 33 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringM );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.pointN( 0 ).m(), 3.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.pointN( 1 ).m(), 23.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
QCOMPARE( from3Pts.pointN( 2 ).m(), 33.0 );
from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ),
QgsPoint( QgsWkbTypes::PointZM, 31, 2, 33, 34 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZM );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
QCOMPARE( from3Pts.pointN( 0 ).m(), 4.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
QCOMPARE( from3Pts.pointN( 1 ).m(), 24.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
QCOMPARE( from3Pts.pointN( 2 ).m(), 34.0 );

// from 2 points and center
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( 1, 2 ), QgsPoint( 31, 2 ), QgsPoint( 21, 2 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 32, 2, 33 ),
QgsPoint( QgsWkbTypes::PointZ, 21, 2, 23 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZ );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
QCOMPARE( from3Pts.xAt( 2 ), 32.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 31, 2, 0, 33 ),
QgsPoint( QgsWkbTypes::PointM, 21, 2, 0, 23 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringM );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.pointN( 0 ).m(), 3.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.pointN( 1 ).m(), 23.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
QCOMPARE( from3Pts.pointN( 2 ).m(), 33.0 );
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 31, 2, 33, 34 ),
QgsPoint( QgsWkbTypes::PointZM, 21, 2, 23, 24 ) );
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZM );
QCOMPARE( from3Pts.numPoints(), 3 );
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
QCOMPARE( from3Pts.pointN( 0 ).m(), 4.0 );
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
QCOMPARE( from3Pts.pointN( 1 ).m(), 24.0 );
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
QCOMPARE( from3Pts.pointN( 2 ).m(), 34.0 );

//setPoints
QgsCircularString l2;
l2.setPoints( QgsPointSequence() << QgsPoint( 1.0, 2.0 ) );
Expand Down

0 comments on commit 732d6bb

Please sign in to comment.