Skip to content

Commit 59db4d0

Browse files
committedMay 9, 2016
Merge pull request #3045 from mhugent/convert_geometry_2
Convert geometry 2
2 parents a65d9c5 + 0b4961c commit 59db4d0

22 files changed

+224
-3
lines changed
 

‎python/core/geometry/qgsabstractgeometryv2.sip

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,12 @@ class QgsAbstractGeometryV2
306306
*/
307307
virtual QgsAbstractGeometryV2* segmentize() const /Factory/;
308308

309+
/** Returns the geometry converted to the more generic curve type.
310+
E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,
311+
QgsMultiLineStringV2 -> QgsMultiCurveV2, QgsMultiPolygonV2 -> QgsMultiSurfaceV2
312+
@return the converted geometry. Caller takes ownership*/
313+
virtual QgsAbstractGeometryV2* toCurveType() const /Factory/;
314+
309315
/** Returns approximate angle at a vertex. This is usually the average angle between adjacent
310316
* segments, and can be pictured as the orientation of a line following the curvature of the
311317
* geometry at the specified vertex.

‎python/core/geometry/qgslinestringv2.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class QgsLineStringV2: public QgsCurveV2
106106
*/
107107
QPolygonF asQPolygonF() const;
108108

109+
/** Returns the geometry converted to the more generic curve type QgsCompoundCurveV2
110+
@return the converted geometry. Caller takes ownership*/
111+
QgsAbstractGeometryV2* toCurveType() const /Factory/;
112+
109113
//reimplemented methods
110114

111115
virtual QString geometryType() const;

‎python/core/geometry/qgsmultilinestringv2.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class QgsMultiLineStringV2: public QgsMultiCurveV2
2020
/** Adds a geometry and takes ownership. Returns true in case of success*/
2121
virtual bool addGeometry( QgsAbstractGeometryV2* g );
2222

23+
/** Returns the geometry converted to the more generic curve type QgsMultiCurveV2
24+
@return the converted geometry. Caller takes ownership*/
25+
QgsAbstractGeometryV2* toCurveType() const /Factory/;
26+
2327
protected:
2428

2529
virtual bool wktOmitChildType() const;

‎python/core/geometry/qgsmultipolygonv2.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class QgsMultiPolygonV2: public QgsMultiSurfaceV2
2020
/** Adds a geometry and takes ownership. Returns true in case of success*/
2121
virtual bool addGeometry( QgsAbstractGeometryV2* g );
2222

23+
/** Returns the geometry converted to the more generic curve type QgsMultiSurfaceV2
24+
@return the converted geometry. Caller takes ownership*/
25+
QgsAbstractGeometryV2* toCurveType() const /Factory/;
26+
2327
protected:
2428

2529
virtual bool wktOmitChildType() const;

‎python/core/geometry/qgspolygonv2.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class QgsPolygonV2: public QgsCurvePolygonV2
2626

2727
QgsPolygonV2* surfaceToPolygon() const;
2828

29+
/** Returns the geometry converted to the more generic curve type QgsCurvePolygonV2
30+
@return the converted geometry. Caller takes ownership*/
31+
QgsAbstractGeometryV2* toCurveType() const /Factory/;
32+
2933
void addInteriorRing( QgsCurveV2* ring /Transfer/ );
3034
//overridden to handle LineString25D rings
3135
virtual void setExteriorRing( QgsCurveV2* ring /Transfer/ );

‎python/core/qgsvectordataprovider.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,4 +361,8 @@ class QgsVectorDataProvider : QgsDataProvider
361361
void fillMinMaxCache();
362362

363363
void pushError( const QString& msg );
364+
365+
/** Converts the geometry to the provider type if possible / necessary
366+
@return the converted geometry or 0 if no conversion was necessary or possible*/
367+
QgsGeometry* convertToProviderType( const QgsGeometry* geom ) const /Factory/;
364368
};

‎src/core/geometry/qgsabstractgeometryv2.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,12 @@ class CORE_EXPORT QgsAbstractGeometryV2
291291
*/
292292
virtual QgsAbstractGeometryV2* segmentize() const { return clone(); }
293293

294+
/** Returns the geometry converted to the more generic curve type.
295+
E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,
296+
QgsMultiLineStringV2 -> QgsMultiCurveV2, QgsMultiPolygonV2 -> QgsMultiSurfaceV2
297+
@return the converted geometry. Caller takes ownership*/
298+
virtual QgsAbstractGeometryV2* toCurveType() const { return 0; }
299+
294300
/** Returns approximate angle at a vertex. This is usually the average angle between adjacent
295301
* segments, and can be pictured as the orientation of a line following the curvature of the
296302
* geometry at the specified vertex.

‎src/core/geometry/qgscompoundcurvev2.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,15 @@ void QgsCompoundCurveV2::addCurve( QgsCurveV2* c )
390390
{
391391
setZMTypeFromSubGeometry( c, QgsWKBTypes::CompoundCurve );
392392
}
393+
394+
if ( QgsWKBTypes::hasZ( mWkbType ) && !QgsWKBTypes::hasZ( c->wkbType() ) )
395+
{
396+
c->addZValue();
397+
}
398+
if ( QgsWKBTypes::hasM( mWkbType ) && !QgsWKBTypes::hasM( c->wkbType() ) )
399+
{
400+
c->addMValue();
401+
}
393402
clearCache();
394403
}
395404
}

‎src/core/geometry/qgsgeometry.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ QgsAbstractGeometryV2* QgsGeometry::geometry() const
132132

133133
void QgsGeometry::setGeometry( QgsAbstractGeometryV2* geometry )
134134
{
135+
if ( d->geometry == geometry )
136+
{
137+
return;
138+
}
139+
135140
detach( false );
136141
if ( d->geometry )
137142
{

‎src/core/geometry/qgslinestringv2.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "qgslinestringv2.h"
1919
#include "qgsapplication.h"
20+
#include "qgscompoundcurvev2.h"
2021
#include "qgscoordinatetransform.h"
2122
#include "qgsgeometryutils.h"
2223
#include "qgsmaptopixel.h"
@@ -583,6 +584,13 @@ QPolygonF QgsLineStringV2::asQPolygonF() const
583584
return points;
584585
}
585586

587+
QgsAbstractGeometryV2* QgsLineStringV2::toCurveType() const
Code has comments. Press enter to view.
588+
{
589+
QgsCompoundCurveV2* compoundCurve = new QgsCompoundCurveV2();
590+
compoundCurve->addCurve( clone() );
591+
return compoundCurve;
592+
}
593+
586594
/***************************************************************************
587595
* This class is considered CRITICAL and any change MUST be accompanied with
588596
* full unit tests.

‎src/core/geometry/qgslinestringv2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
132132
*/
133133
QPolygonF asQPolygonF() const;
134134

135+
/** Returns the geometry converted to the more generic curve type QgsCompoundCurveV2
136+
@return the converted geometry. Caller takes ownership*/
137+
QgsAbstractGeometryV2* toCurveType() const override;
138+
135139
//reimplemented methods
136140

137141
virtual QString geometryType() const override { return "LineString"; }

‎src/core/geometry/qgsmultilinestringv2.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ email : marco.hugentobler at sourcepole dot com
2020
#include "qgscompoundcurvev2.h"
2121
#include "qgsgeometryutils.h"
2222
#include "qgslinestringv2.h"
23+
#include "qgsmulticurvev2.h"
2324

2425
QgsMultiLineStringV2* QgsMultiLineStringV2::clone() const
2526
{
@@ -101,3 +102,13 @@ bool QgsMultiLineStringV2::addGeometry( QgsAbstractGeometryV2* g )
101102
setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiLineString );
102103
return QgsGeometryCollectionV2::addGeometry( g );
103104
}
105+
106+
QgsAbstractGeometryV2* QgsMultiLineStringV2::toCurveType() const
107+
{
108+
QgsMultiCurveV2* multiCurve = new QgsMultiCurveV2();
109+
for ( int i = 0; i < mGeometries.size(); ++i )
110+
{
111+
multiCurve->addGeometry( mGeometries.at( i )->clone() );
112+
}
113+
return multiCurve;
114+
}

‎src/core/geometry/qgsmultilinestringv2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class CORE_EXPORT QgsMultiLineStringV2: public QgsMultiCurveV2
4242
/** Adds a geometry and takes ownership. Returns true in case of success*/
4343
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;
4444

45+
/** Returns the geometry converted to the more generic curve type QgsMultiCurveV2
46+
@return the converted geometry. Caller takes ownership*/
47+
QgsAbstractGeometryV2* toCurveType() const override;
48+
4549
protected:
4650

4751
virtual bool wktOmitChildType() const override { return true; }

‎src/core/geometry/qgsmultipolygonv2.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,13 @@ bool QgsMultiPolygonV2::addGeometry( QgsAbstractGeometryV2* g )
117117
setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiPolygon );
118118
return QgsGeometryCollectionV2::addGeometry( g );
119119
}
120+
121+
QgsAbstractGeometryV2* QgsMultiPolygonV2::toCurveType() const
122+
{
123+
QgsMultiSurfaceV2* multiSurface = new QgsMultiSurfaceV2();
124+
for ( int i = 0; i < mGeometries.size(); ++i )
125+
{
126+
multiSurface->addGeometry( mGeometries.at( i )->clone() );
127+
}
128+
return multiSurface;
129+
}

‎src/core/geometry/qgsmultipolygonv2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ class CORE_EXPORT QgsMultiPolygonV2: public QgsMultiSurfaceV2
4343
/** Adds a geometry and takes ownership. Returns true in case of success*/
4444
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;
4545

46+
/** Returns the geometry converted to the more generic curve type QgsMultiSurfaceV2
47+
@return the converted geometry. Caller takes ownership*/
48+
QgsAbstractGeometryV2* toCurveType() const override;
49+
4650
protected:
4751

4852
virtual bool wktOmitChildType() const override { return true; }

‎src/core/geometry/qgspolygonv2.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,15 @@ QgsPolygonV2* QgsPolygonV2::surfaceToPolygon() const
240240
{
241241
return clone();
242242
}
243+
244+
QgsAbstractGeometryV2* QgsPolygonV2::toCurveType() const
245+
{
246+
QgsCurvePolygonV2* curvePolygon = new QgsCurvePolygonV2();
247+
curvePolygon->setExteriorRing( mExteriorRing->clone() );
248+
int nInteriorRings = mInteriorRings.size();
249+
for ( int i = 0; i < nInteriorRings; ++i )
250+
{
251+
curvePolygon->addInteriorRing( mInteriorRings.at( i )->clone() );
252+
}
253+
return curvePolygon;
254+
}

‎src/core/geometry/qgspolygonv2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class CORE_EXPORT QgsPolygonV2: public QgsCurvePolygonV2
5050

5151
QgsPolygonV2* surfaceToPolygon() const override;
5252

53+
/** Returns the geometry converted to the more generic curve type QgsCurvePolygonV2
54+
@return the converted geometry. Caller takes ownership*/
55+
QgsAbstractGeometryV2* toCurveType() const override;
56+
5357
void addInteriorRing( QgsCurveV2* ring ) override;
5458
//overridden to handle LineString25D rings
5559
virtual void setExteriorRing( QgsCurveV2* ring ) override;

‎src/core/qgsvectordataprovider.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@
2121
#include <limits>
2222

2323
#include "qgsvectordataprovider.h"
24+
#include "qgscircularstringv2.h"
25+
#include "qgscompoundcurvev2.h"
2426
#include "qgsfeature.h"
2527
#include "qgsfeatureiterator.h"
2628
#include "qgsfeaturerequest.h"
2729
#include "qgsfield.h"
30+
#include "qgsgeometry.h"
31+
#include "qgsgeometrycollectionv2.h"
32+
#include "qgsgeometryfactory.h"
2833
#include "qgslogger.h"
2934
#include "qgsmessagelog.h"
3035

@@ -572,4 +577,103 @@ QSet<QString> QgsVectorDataProvider::layerDependencies() const
572577
return QSet<QString>();
573578
}
574579

580+
QgsGeometry* QgsVectorDataProvider::convertToProviderType( const QgsGeometry* geom ) const
581+
{
582+
if ( !geom )
583+
{
584+
return 0;
585+
}
586+
587+
QgsAbstractGeometryV2* geometry = geom->geometry();
588+
if ( !geometry )
589+
{
590+
return 0;
591+
}
592+
593+
QgsWKBTypes::Type providerGeomType = QgsWKBTypes::Type( geometryType() );
594+
595+
//geom is already in the provider geometry type
596+
if ( geometry->wkbType() == providerGeomType )
597+
{
598+
return 0;
599+
}
600+
601+
QgsAbstractGeometryV2* outputGeom = 0;
602+
603+
//convert compoundcurve to circularstring (possible if compoundcurve consists of one circular string)
604+
if ( QgsWKBTypes::flatType( providerGeomType ) == QgsWKBTypes::CircularString && QgsWKBTypes::flatType( geometry->wkbType() ) == QgsWKBTypes::CompoundCurve )
605+
{
606+
QgsCompoundCurveV2* compoundCurve = static_cast<QgsCompoundCurveV2*>( geometry );
607+
if ( compoundCurve )
608+
{
609+
if ( compoundCurve->nCurves() == 1 )
610+
{
611+
const QgsCircularStringV2* circularString = dynamic_cast<const QgsCircularStringV2*>( compoundCurve->curveAt( 0 ) );
612+
if ( circularString )
613+
{
614+
outputGeom = circularString->clone();
615+
}
616+
}
617+
}
618+
}
619+
620+
//convert to multitype if necessary
621+
if ( QgsWKBTypes::isMultiType( providerGeomType ) && !QgsWKBTypes::isMultiType( geometry->wkbType() ) )
622+
{
623+
outputGeom = QgsGeometryFactory::geomFromWkbType( providerGeomType );
624+
QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( outputGeom );
625+
if ( geomCollection )
626+
{
627+
geomCollection->addGeometry( geometry->clone() );
628+
}
629+
}
630+
631+
//convert to curved type if necessary
632+
if ( !QgsWKBTypes::isCurvedType( geometry->wkbType() ) && QgsWKBTypes::isCurvedType( providerGeomType ) )
633+
{
634+
QgsAbstractGeometryV2* curveGeom = outputGeom ? outputGeom->toCurveType() : geometry->toCurveType();
635+
if ( curveGeom )
636+
{
637+
delete outputGeom;
638+
outputGeom = curveGeom;
639+
}
640+
}
641+
642+
//convert to linear type from curved type
643+
if ( QgsWKBTypes::isCurvedType( geometry->wkbType() ) && !QgsWKBTypes::isCurvedType( providerGeomType ) )
644+
{
645+
QgsAbstractGeometryV2* segmentizedGeom = 0;
646+
segmentizedGeom = outputGeom ? outputGeom->segmentize() : geometry->segmentize();
647+
if ( segmentizedGeom )
648+
{
649+
delete outputGeom;
650+
outputGeom = segmentizedGeom;
651+
}
652+
}
653+
654+
//set z/m types
655+
if ( QgsWKBTypes::hasZ( providerGeomType ) )
656+
{
657+
if ( !outputGeom )
658+
{
659+
outputGeom = geometry->clone();
660+
}
661+
outputGeom->addZValue();
662+
}
663+
if ( QgsWKBTypes::hasM( providerGeomType ) )
664+
{
665+
if ( !outputGeom )
666+
{
667+
outputGeom = geometry->clone();
668+
}
669+
outputGeom->addMValue();
670+
}
671+
672+
if ( outputGeom )
673+
{
674+
return new QgsGeometry( outputGeom );
675+
}
676+
return 0;
677+
}
678+
575679
QStringList QgsVectorDataProvider::smEncodings;

‎src/core/qgsvectordataprovider.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
436436
/** Old-style mapping of index to name for QgsPalLabeling fix */
437437
QgsAttrPalIndexNameHash mAttrPalIndexName;
438438

439+
/** Converts the geometry to the provider type if possible / necessary
440+
@return the converted geometry or 0 if no conversion was necessary or possible*/
441+
QgsGeometry* convertToProviderType( const QgsGeometry* geom ) const;
442+
439443
private:
440444
/** Old notation **/
441445
QMap<QString, QVariant::Type> mOldTypeList;

‎src/core/qgsvectorlayereditbuffer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
#include "qgsvectorlayereditbuffer.h"
1616

1717
#include "qgsgeometry.h"
18+
#include "qgscurvepolygonv2.h"
19+
#include "qgscurvev2.h"
20+
#include "qgsgeometrycollectionv2.h"
21+
#include "qgsgeometryfactory.h"
22+
#include "qgsgeometryutils.h"
1823
#include "qgslogger.h"
24+
#include "qgspolygonv2.h"
1925
#include "qgsvectorlayerundocommand.h"
2026
#include "qgsvectordataprovider.h"
2127
#include "qgsvectorlayer.h"

‎src/core/qgsvectorlayereditbuffer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
188188

189189
/** Changed geometries which are not commited. */
190190
QgsGeometryMap mChangedGeometries;
191-
192191
};
193192

194193
#endif // QGSVECTORLAYEREDITBUFFER_H

‎src/providers/postgres/qgspostgresprovider.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,14 +2371,19 @@ void QgsPostgresProvider::appendGeomParam( const QgsGeometry *geom, QStringList
23712371
}
23722372

23732373
QString param;
2374-
const unsigned char *buf = geom->asWkb();
2375-
for ( int i = 0; i < geom->wkbSize(); ++i )
2374+
2375+
QgsGeometry* convertedGeom = convertToProviderType( geom );
2376+
const unsigned char *buf = convertedGeom ? convertedGeom->asWkb() : geom->asWkb();
2377+
size_t wkbSize = convertedGeom ? convertedGeom->wkbSize() : geom->wkbSize();
2378+
2379+
for ( size_t i = 0; i < wkbSize; ++i )
23762380
{
23772381
if ( connectionRO()->useWkbHex() )
23782382
param += QString( "%1" ).arg(( int ) buf[i], 2, 16, QChar( '0' ) );
23792383
else
23802384
param += QString( "\\%1" ).arg(( int ) buf[i], 3, 8, QChar( '0' ) );
23812385
}
2386+
delete convertedGeom;
23822387
params << param;
23832388
}
23842389

0 commit comments

Comments
 (0)
Please sign in to comment.