Skip to content

Commit 878230a

Browse files
committed
Add methods to QgsGeometry to convert to/from QPointF and QPolygonF
1 parent b5c9df0 commit 878230a

File tree

4 files changed

+241
-3
lines changed

4 files changed

+241
-3
lines changed

python/core/qgsgeometry.sip

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ class QgsGeometry
5555
static QgsGeometry* fromMultiPolygon( const QgsMultiPolygon& multipoly ) /Factory/;
5656
/** construct geometry from a rectangle */
5757
static QgsGeometry* fromRect( const QgsRectangle& rect ) /Factory/;
58+
/**Construct geometry from a QPointF
59+
* @param point source QPointF
60+
* @note added in QGIS 2.7
61+
*/
62+
static QgsGeometry* fromQPointF( const QPointF& point ) /Factory/;
63+
64+
/**Construct geometry from a QPolygonF. If the polygon is closed than
65+
* the resultant geometry will be a polygon, if it is open than the
66+
* geometry will be a polyline.
67+
* @param polygon source QPolygonF
68+
* @note added in QGIS 2.7
69+
*/
70+
static QgsGeometry* fromQPolygonF( const QPolygonF& polygon ) /Factory/;
71+
5872
/**
5973
Set the geometry, feeding in a geometry in GEOS format.
6074
This class will take ownership of the buffer.
@@ -416,6 +430,19 @@ class QgsGeometry
416430
@note added in version 1.1 */
417431
QList<QgsGeometry*> asGeometryCollection() const /Factory/;
418432

433+
/**Return contents of the geometry as a QPointF if wkbType is WKBPoint,
434+
* otherwise returns a null QPointF.
435+
* @note added in QGIS 2.7
436+
*/
437+
QPointF asQPointF() const;
438+
439+
/**Return contents of the geometry as a QPolygonF. If geometry is a linestring,
440+
* then the result will be an open QPolygonF. If the geometry is a polygon,
441+
* then the result will be a closed QPolygonF of the geometry's exterior ring.
442+
* @note added in QGIS 2.7
443+
*/
444+
QPolygonF asQPolygonF() const;
445+
419446
/** delete a ring in polygon or multipolygon.
420447
Ring 0 is outer ring and can't be deleted.
421448
@return true on success

src/core/qgsgeometry.cpp

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,19 @@ static unsigned int getNumGeosPoints( const GEOSGeometry *geom )
190190
return n;
191191
}
192192

193-
static GEOSGeometry *createGeosPoint( const QgsPoint &point )
193+
static GEOSGeometry *createGeosPoint( const double x, const double y )
194194
{
195195
GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosinit.ctxt, 1, 2 );
196-
GEOSCoordSeq_setX_r( geosinit.ctxt, coord, 0, point.x() );
197-
GEOSCoordSeq_setY_r( geosinit.ctxt, coord, 0, point.y() );
196+
GEOSCoordSeq_setX_r( geosinit.ctxt, coord, 0, x );
197+
GEOSCoordSeq_setY_r( geosinit.ctxt, coord, 0, y );
198198
return GEOSGeom_createPoint_r( geosinit.ctxt, coord );
199199
}
200200

201+
static GEOSGeometry *createGeosPoint( const QgsPoint &point )
202+
{
203+
return createGeosPoint( point.x(), point.y() );
204+
}
205+
201206
static GEOSCoordSequence *createGeosCoordSequence( const QgsPolyline& points )
202207
{
203208
GEOSCoordSequence *coord = 0;
@@ -509,6 +514,40 @@ QgsGeometry* QgsGeometry::fromRect( const QgsRectangle& rect )
509514
return fromPolygon( polygon );
510515
}
511516

517+
QgsGeometry *QgsGeometry::fromQPointF( const QPointF &point )
518+
{
519+
return fromGeosGeom( createGeosPoint( point.x(), point.y() ) );
520+
}
521+
522+
QgsGeometry *QgsGeometry::fromQPolygonF( const QPolygonF &polygon )
523+
{
524+
if ( polygon.isClosed() )
525+
{
526+
return QgsGeometry::fromPolygon( createPolygonFromQPolygonF( polygon ) );
527+
}
528+
else
529+
{
530+
return QgsGeometry::fromPolyline( createPolylineFromQPolygonF( polygon ) );
531+
}
532+
}
533+
534+
QgsPolygon QgsGeometry::createPolygonFromQPolygonF( const QPolygonF &polygon )
535+
{
536+
QgsPolygon result;
537+
result << createPolylineFromQPolygonF( polygon );
538+
return result;
539+
}
540+
541+
QgsPolyline QgsGeometry::createPolylineFromQPolygonF( const QPolygonF &polygon )
542+
{
543+
QgsPolyline result;
544+
QPolygonF::const_iterator it = polygon.constBegin();
545+
for ( ; it != polygon.constEnd(); ++it )
546+
{
547+
result.append( QgsPoint( *it ) );
548+
}
549+
return result;
550+
}
512551

513552
QgsGeometry & QgsGeometry::operator=( QgsGeometry const & rhs )
514553
{
@@ -5901,6 +5940,41 @@ QList<QgsGeometry*> QgsGeometry::asGeometryCollection() const
59015940
return geomCollection;
59025941
}
59035942

5943+
QPointF QgsGeometry::asQPointF() const
5944+
{
5945+
QgsPoint point = asPoint();
5946+
return point.toQPointF();
5947+
}
5948+
5949+
QPolygonF QgsGeometry::asQPolygonF() const
5950+
{
5951+
QPolygonF result;
5952+
QgsPolyline polyline;
5953+
QGis::WkbType type = wkbType();
5954+
if ( type == QGis::WKBLineString || type == QGis::WKBLineString25D )
5955+
{
5956+
polyline = asPolyline();
5957+
}
5958+
else if ( type == QGis::WKBPolygon || type == QGis::WKBPolygon25D )
5959+
{
5960+
QgsPolygon polygon = asPolygon();
5961+
if ( polygon.size() < 1 )
5962+
return result;
5963+
polyline = polygon.at( 0 );
5964+
}
5965+
else
5966+
{
5967+
return result;
5968+
}
5969+
5970+
QgsPolyline::const_iterator lineIt = polyline.constBegin();
5971+
for ( ; lineIt != polyline.constEnd(); ++lineIt )
5972+
{
5973+
result << lineIt->toQPointF();
5974+
}
5975+
return result;
5976+
}
5977+
59045978
bool QgsGeometry::deleteRing( int ringNum, int partNum )
59055979
{
59065980
if ( ringNum <= 0 || partNum < 0 )

src/core/qgsgeometry.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ class CORE_EXPORT QgsGeometry
106106
static QgsGeometry* fromMultiPolygon( const QgsMultiPolygon& multipoly );
107107
/** construct geometry from a rectangle */
108108
static QgsGeometry* fromRect( const QgsRectangle& rect );
109+
/**Construct geometry from a QPointF
110+
* @param point source QPointF
111+
* @note added in QGIS 2.7
112+
*/
113+
static QgsGeometry* fromQPointF( const QPointF& point );
114+
115+
/**Construct geometry from a QPolygonF. If the polygon is closed than
116+
* the resultant geometry will be a polygon, if it is open than the
117+
* geometry will be a polyline.
118+
* @param polygon source QPolygonF
119+
* @note added in QGIS 2.7
120+
*/
121+
static QgsGeometry* fromQPolygonF( const QPolygonF& polygon );
122+
109123
/**
110124
Set the geometry, feeding in a geometry in GEOS format.
111125
This class will take ownership of the buffer.
@@ -436,6 +450,19 @@ class CORE_EXPORT QgsGeometry
436450
/** return contents of the geometry as a list of geometries */
437451
QList<QgsGeometry*> asGeometryCollection() const;
438452

453+
/**Return contents of the geometry as a QPointF if wkbType is WKBPoint,
454+
* otherwise returns a null QPointF.
455+
* @note added in QGIS 2.7
456+
*/
457+
QPointF asQPointF() const;
458+
459+
/**Return contents of the geometry as a QPolygonF. If geometry is a linestring,
460+
* then the result will be an open QPolygonF. If the geometry is a polygon,
461+
* then the result will be a closed QPolygonF of the geometry's exterior ring.
462+
* @note added in QGIS 2.7
463+
*/
464+
QPolygonF asQPolygonF() const;
465+
439466
/** delete a ring in polygon or multipolygon.
440467
Ring 0 is outer ring and can't be deleted.
441468
@return true on success
@@ -632,6 +659,9 @@ class CORE_EXPORT QgsGeometry
632659
QgsGeometry* convertToLine( bool destMultipart );
633660
/** try to convert the geometry to a polygon */
634661
QgsGeometry* convertToPolygon( bool destMultipart );
662+
663+
static QgsPolyline createPolylineFromQPolygonF( const QPolygonF &polygon );
664+
static QgsPolygon createPolygonFromQPolygonF( const QPolygonF &polygon );
635665
}; // class QgsGeometry
636666

637667
Q_DECLARE_METATYPE( QgsGeometry );

tests/src/core/testqgsgeometry.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ class TestQgsGeometry: public QObject
4747
void init();// will be called before each testfunction is executed.
4848
void cleanup();// will be called after every testfunction.
4949

50+
void fromQgsPoint();
51+
void fromQPoint();
52+
void fromQPolygonF();
53+
void asQPointF();
54+
void asQPolygonF();
55+
5056
void simplifyCheck1();
5157
void intersectionCheck1();
5258
void intersectionCheck2();
@@ -178,6 +184,107 @@ void TestQgsGeometry::cleanup()
178184
delete mpPainter;
179185
}
180186

187+
void TestQgsGeometry::fromQgsPoint()
188+
{
189+
QgsPoint point( 1.0, 2.0 );
190+
QgsGeometry* result = QgsGeometry::fromPoint( point );
191+
QCOMPARE( result->wkbType(), QGis::WKBPoint );
192+
QgsPoint resultPoint = result->asPoint();
193+
QCOMPARE( resultPoint, point );
194+
delete result;
195+
}
196+
197+
void TestQgsGeometry::fromQPoint()
198+
{
199+
QPointF point( 1.0, 2.0 );
200+
QgsGeometry* result = QgsGeometry::fromQPointF( point );
201+
QCOMPARE( result->wkbType(), QGis::WKBPoint );
202+
QgsPoint resultPoint = result->asPoint();
203+
QCOMPARE( resultPoint.x(), 1.0 );
204+
QCOMPARE( resultPoint.y(), 2.0 );
205+
delete result;
206+
}
207+
208+
void TestQgsGeometry::fromQPolygonF()
209+
{
210+
//test with a polyline
211+
QPolygonF polyline;
212+
polyline << QPointF( 1.0, 2.0 ) << QPointF( 4.0, 6.0 ) << QPointF( 4.0, 3.0 ) << QPointF( 2.0, 2.0 );
213+
QgsGeometry* result = QgsGeometry::fromQPolygonF( polyline );
214+
QCOMPARE( result->wkbType(), QGis::WKBLineString );
215+
QgsPolyline resultLine = result->asPolyline();
216+
QCOMPARE( resultLine.size(), 4 );
217+
QCOMPARE( resultLine.at( 0 ), QgsPoint( 1.0, 2.0 ) );
218+
QCOMPARE( resultLine.at( 1 ), QgsPoint( 4.0, 6.0 ) );
219+
QCOMPARE( resultLine.at( 2 ), QgsPoint( 4.0, 3.0 ) );
220+
QCOMPARE( resultLine.at( 3 ), QgsPoint( 2.0, 2.0 ) );
221+
delete result;
222+
223+
//test with a closed polygon
224+
QPolygonF polygon;
225+
polygon << QPointF( 1.0, 2.0 ) << QPointF( 4.0, 6.0 ) << QPointF( 4.0, 3.0 ) << QPointF( 2.0, 2.0 ) << QPointF( 1.0, 2.0 );
226+
QgsGeometry* result2 = QgsGeometry::fromQPolygonF( polygon );
227+
QCOMPARE( result2->wkbType(), QGis::WKBPolygon );
228+
QgsPolygon resultPolygon = result2->asPolygon();
229+
QCOMPARE( resultPolygon.size(), 1 );
230+
QCOMPARE( resultPolygon.at( 0 ).at( 0 ), QgsPoint( 1.0, 2.0 ) );
231+
QCOMPARE( resultPolygon.at( 0 ).at( 1 ), QgsPoint( 4.0, 6.0 ) );
232+
QCOMPARE( resultPolygon.at( 0 ).at( 2 ), QgsPoint( 4.0, 3.0 ) );
233+
QCOMPARE( resultPolygon.at( 0 ).at( 3 ), QgsPoint( 2.0, 2.0 ) );
234+
QCOMPARE( resultPolygon.at( 0 ).at( 4 ), QgsPoint( 1.0, 2.0 ) );
235+
delete result2;
236+
}
237+
238+
void TestQgsGeometry::asQPointF()
239+
{
240+
QPointF point( 1.0, 2.0 );
241+
QgsGeometry* geom = QgsGeometry::fromQPointF( point );
242+
QPointF resultPoint = geom->asQPointF();
243+
QCOMPARE( resultPoint, point );
244+
delete geom;
245+
246+
//non point geom
247+
QPointF badPoint = mpPolygonGeometryA->asQPointF();
248+
QVERIFY( badPoint.isNull() );
249+
}
250+
251+
void TestQgsGeometry::asQPolygonF()
252+
{
253+
//test polygon
254+
QPolygonF fromPoly = mpPolygonGeometryA->asQPolygonF();
255+
QVERIFY( fromPoly.isClosed() );
256+
QCOMPARE( fromPoly.size(), 5 );
257+
QCOMPARE( fromPoly.at( 0 ).x(), mPoint1.x() );
258+
QCOMPARE( fromPoly.at( 0 ).y(), mPoint1.y() );
259+
QCOMPARE( fromPoly.at( 1 ).x(), mPoint2.x() );
260+
QCOMPARE( fromPoly.at( 1 ).y(), mPoint2.y() );
261+
QCOMPARE( fromPoly.at( 2 ).x(), mPoint3.x() );
262+
QCOMPARE( fromPoly.at( 2 ).y(), mPoint3.y() );
263+
QCOMPARE( fromPoly.at( 3 ).x(), mPoint4.x() );
264+
QCOMPARE( fromPoly.at( 3 ).y(), mPoint4.y() );
265+
QCOMPARE( fromPoly.at( 4 ).x(), mPoint1.x() );
266+
QCOMPARE( fromPoly.at( 4 ).y(), mPoint1.y() );
267+
//test polyline
268+
QgsPolyline testline;
269+
testline << mPoint1 << mPoint2 << mPoint3;
270+
QgsGeometry* lineGeom = QgsGeometry::fromPolyline( testline );
271+
QPolygonF fromLine = lineGeom->asQPolygonF();
272+
QVERIFY( !fromLine.isClosed() );
273+
QCOMPARE( fromLine.size(), 3 );
274+
QCOMPARE( fromLine.at( 0 ).x(), mPoint1.x() );
275+
QCOMPARE( fromLine.at( 0 ).y(), mPoint1.y() );
276+
QCOMPARE( fromLine.at( 1 ).x(), mPoint2.x() );
277+
QCOMPARE( fromLine.at( 1 ).y(), mPoint2.y() );
278+
QCOMPARE( fromLine.at( 2 ).x(), mPoint3.x() );
279+
QCOMPARE( fromLine.at( 2 ).y(), mPoint3.y() );
280+
delete lineGeom;
281+
//test a bad geometry
282+
QgsGeometry* badGeom = QgsGeometry::fromPoint( mPoint1 );
283+
QPolygonF fromBad = badGeom->asQPolygonF();
284+
QVERIFY( fromBad.isEmpty() );
285+
delete badGeom;
286+
}
287+
181288
void TestQgsGeometry::initTestCase()
182289
{
183290
//

0 commit comments

Comments
 (0)