Skip to content

Commit 732d6bb

Browse files
committed
Add convenience constructors to create QgsCircularStrings
Add constructors to create a circular string with a single arc: - from 3 points on arc - from 2 points and a center
1 parent 3f3b951 commit 732d6bb

File tree

4 files changed

+193
-0
lines changed

4 files changed

+193
-0
lines changed

python/core/geometry/qgscircularstring.sip.in

+24
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,31 @@ class QgsCircularString: QgsCurve
2323
#include "qgscircularstring.h"
2424
%End
2525
public:
26+
2627
QgsCircularString();
28+
%Docstring
29+
Constructs an empty circular string.
30+
%End
31+
32+
QgsCircularString( const QgsPoint &p1,
33+
const QgsPoint &p2,
34+
const QgsPoint &p3 );
35+
%Docstring
36+
Constructs a circular string with a single
37+
arc passing through ``p1``, ``p2`` and ``p3``.
38+
39+
.. versionadded:: 3.2
40+
%End
41+
42+
static QgsCircularString fromTwoPointsAndCenter( const QgsPoint &p1,
43+
const QgsPoint &p2,
44+
const QgsPoint &center );
45+
%Docstring
46+
Creates a circular string with a single arc representing
47+
the curve from ``p1`` to ``p2`` with the specified ``center``.
48+
49+
.. versionadded:: 3.2
50+
%End
2751

2852
virtual bool equals( const QgsCurve &other ) const;
2953

src/core/geometry/qgscircularstring.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,45 @@ QgsCircularString::QgsCircularString()
3333
mWkbType = QgsWkbTypes::CircularString;
3434
}
3535

36+
QgsCircularString::QgsCircularString( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3 )
37+
{
38+
//get wkb type from first point
39+
bool hasZ = p1.is3D();
40+
bool hasM = p1.isMeasure();
41+
mWkbType = QgsWkbTypes::CircularString;
42+
43+
mX.resize( 3 );
44+
mX[ 0 ] = p1.x();
45+
mX[ 1 ] = p2.x();
46+
mX[ 2 ] = p3.x();
47+
mY.resize( 3 );
48+
mY[ 0 ] = p1.y();
49+
mY[ 1 ] = p2.y();
50+
mY[ 2 ] = p3.y();
51+
if ( hasZ )
52+
{
53+
mWkbType = QgsWkbTypes::addZ( mWkbType );
54+
mZ.resize( 3 );
55+
mZ[ 0 ] = p1.z();
56+
mZ[ 1 ] = p2.z();
57+
mZ[ 2 ] = p3.z();
58+
}
59+
if ( hasM )
60+
{
61+
mWkbType = QgsWkbTypes::addM( mWkbType );
62+
mM.resize( 3 );
63+
mM[ 0 ] = p1.m();
64+
mM[ 1 ] = p2.m();
65+
mM[ 2 ] = p3.m();
66+
}
67+
}
68+
69+
QgsCircularString QgsCircularString::fromTwoPointsAndCenter( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &center )
70+
{
71+
const QgsPoint midPoint = QgsGeometryUtils::segmentMidPointFromCenter( p1, p2, center );
72+
return QgsCircularString( p1, midPoint, p2 );
73+
}
74+
3675
bool QgsCircularString::equals( const QgsCurve &other ) const
3776
{
3877
const QgsCircularString *otherLine = dynamic_cast< const QgsCircularString * >( &other );

src/core/geometry/qgscircularstring.h

+24
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,32 @@
3434
class CORE_EXPORT QgsCircularString: public QgsCurve
3535
{
3636
public:
37+
38+
/**
39+
* Constructs an empty circular string.
40+
*/
3741
QgsCircularString();
3842

43+
/**
44+
* Constructs a circular string with a single
45+
* arc passing through \a p1, \a p2 and \a p3.
46+
*
47+
* \since QGIS 3.2
48+
*/
49+
QgsCircularString( const QgsPoint &p1,
50+
const QgsPoint &p2,
51+
const QgsPoint &p3 );
52+
53+
/**
54+
* Creates a circular string with a single arc representing
55+
* the curve from \a p1 to \a p2 with the specified \a center.
56+
*
57+
* \since QGIS 3.2
58+
*/
59+
static QgsCircularString fromTwoPointsAndCenter( const QgsPoint &p1,
60+
const QgsPoint &p2,
61+
const QgsPoint &center );
62+
3963
bool equals( const QgsCurve &other ) const override;
4064

4165
QString geometryType() const override;

tests/src/core/testqgsgeometry.cpp

+106
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,112 @@ void TestQgsGeometry::circularString()
11581158
l1.points( pts );
11591159
QVERIFY( pts.empty() );
11601160

1161+
// from 3 points
1162+
QgsCircularString from3Pts( QgsPoint( 1, 2 ), QgsPoint( 21, 22 ), QgsPoint( 31, 2 ) );
1163+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
1164+
QCOMPARE( from3Pts.numPoints(), 3 );
1165+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1166+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1167+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1168+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1169+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1170+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1171+
from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 21, 22, 23 ),
1172+
QgsPoint( QgsWkbTypes::PointZ, 31, 2, 33 ) );
1173+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZ );
1174+
QCOMPARE( from3Pts.numPoints(), 3 );
1175+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1176+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1177+
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1178+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1179+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1180+
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1181+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1182+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1183+
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1184+
from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 23 ),
1185+
QgsPoint( QgsWkbTypes::PointM, 31, 2, 0, 33 ) );
1186+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringM );
1187+
QCOMPARE( from3Pts.numPoints(), 3 );
1188+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1189+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1190+
QCOMPARE( from3Pts.pointN( 0 ).m(), 3.0 );
1191+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1192+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1193+
QCOMPARE( from3Pts.pointN( 1 ).m(), 23.0 );
1194+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1195+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1196+
QCOMPARE( from3Pts.pointN( 2 ).m(), 33.0 );
1197+
from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ),
1198+
QgsPoint( QgsWkbTypes::PointZM, 31, 2, 33, 34 ) );
1199+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZM );
1200+
QCOMPARE( from3Pts.numPoints(), 3 );
1201+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1202+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1203+
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1204+
QCOMPARE( from3Pts.pointN( 0 ).m(), 4.0 );
1205+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1206+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1207+
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1208+
QCOMPARE( from3Pts.pointN( 1 ).m(), 24.0 );
1209+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1210+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1211+
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1212+
QCOMPARE( from3Pts.pointN( 2 ).m(), 34.0 );
1213+
1214+
// from 2 points and center
1215+
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( 1, 2 ), QgsPoint( 31, 2 ), QgsPoint( 21, 2 ) );
1216+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
1217+
QCOMPARE( from3Pts.numPoints(), 3 );
1218+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1219+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1220+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1221+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1222+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1223+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1224+
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 32, 2, 33 ),
1225+
QgsPoint( QgsWkbTypes::PointZ, 21, 2, 23 ) );
1226+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZ );
1227+
QCOMPARE( from3Pts.numPoints(), 3 );
1228+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1229+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1230+
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1231+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1232+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1233+
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1234+
QCOMPARE( from3Pts.xAt( 2 ), 32.0 );
1235+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1236+
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1237+
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 31, 2, 0, 33 ),
1238+
QgsPoint( QgsWkbTypes::PointM, 21, 2, 0, 23 ) );
1239+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringM );
1240+
QCOMPARE( from3Pts.numPoints(), 3 );
1241+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1242+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1243+
QCOMPARE( from3Pts.pointN( 0 ).m(), 3.0 );
1244+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1245+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1246+
QCOMPARE( from3Pts.pointN( 1 ).m(), 23.0 );
1247+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1248+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1249+
QCOMPARE( from3Pts.pointN( 2 ).m(), 33.0 );
1250+
from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 31, 2, 33, 34 ),
1251+
QgsPoint( QgsWkbTypes::PointZM, 21, 2, 23, 24 ) );
1252+
QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZM );
1253+
QCOMPARE( from3Pts.numPoints(), 3 );
1254+
QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1255+
QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1256+
QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1257+
QCOMPARE( from3Pts.pointN( 0 ).m(), 4.0 );
1258+
QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1259+
QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1260+
QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1261+
QCOMPARE( from3Pts.pointN( 1 ).m(), 24.0 );
1262+
QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1263+
QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1264+
QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1265+
QCOMPARE( from3Pts.pointN( 2 ).m(), 34.0 );
1266+
11611267
//setPoints
11621268
QgsCircularString l2;
11631269
l2.setPoints( QgsPointSequence() << QgsPoint( 1.0, 2.0 ) );

0 commit comments

Comments
 (0)