Skip to content

Commit 8fae816

Browse files
authored
Merge pull request #3446 from mhugent/convert_geometry_provider
Port conversion of geometry to provider type to 2.14 branch
2 parents a528eb9 + b14255c commit 8fae816

19 files changed

+203
-2
lines changed

python/core/geometry/qgsabstractgeometryv2.sip

+6
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. QgsLineString -> QgsCompoundCurve, QgsPolygonV2 -> QgsCurvePolygon,
311+
QgsMultiLineString -> QgsMultiCurve, QgsMultiPolygonV2 -> QgsMultiSurface
312+
@return the converted geometry. Caller takes ownership*/
313+
virtual QgsAbstractGeometry* 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

+4
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class QgsLineStringV2: public QgsCurveV2
102102
/** Closes the line string by appending the first point to the end of the line, if it is not already closed.*/
103103
void close();
104104

105+
/** Returns the geometry converted to the more generic curve type QgsCompoundCurve
106+
@return the converted geometry. Caller takes ownership*/
107+
QgsAbstractGeometry* toCurveType() const /Factory/;
108+
105109
/** Returns a QPolygonF representing the line string.
106110
*/
107111
QPolygonF asQPolygonF() const;

python/core/geometry/qgsmultilinestringv2.sip

+4
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 QgsMultiCurve
24+
@return the converted geometry. Caller takes ownership*/
25+
QgsAbstractGeometry* toCurveType() const /Factory/;
26+
2327
protected:
2428

2529
virtual bool wktOmitChildType() const;

python/core/geometry/qgsmultipolygonv2.sip

+4
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 QgsMultiSurface
24+
@return the converted geometry. Caller takes ownership*/
25+
QgsAbstractGeometry* toCurveType() const /Factory/;
26+
2327
protected:
2428

2529
virtual bool wktOmitChildType() const;

python/core/geometry/qgspolygonv2.sip

+4
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 QgsCurvePolygon
30+
@return the converted geometry. Caller takes ownership*/
31+
QgsAbstractGeometry* 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

+4
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 nullptr if no conversion was necessary or possible*/
367+
QgsGeometry* convertToProviderType( const QgsGeometry& geom ) const /Factory/;
364368
};

src/core/geometry/qgsabstractgeometryv2.h

+6
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,12 @@ class CORE_EXPORT QgsAbstractGeometryV2
292292
*/
293293
virtual QgsAbstractGeometryV2* segmentize() const { return clone(); }
294294

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

src/core/geometry/qgsgeometry.cpp

+5
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

+8
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
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

+3
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
132132
*/
133133
QPolygonF asQPolygonF() const;
134134

135+
/** Returns the geometry converted to QgsCompoundCurveV2*/
136+
QgsAbstractGeometryV2* toCurveType() const override;
137+
135138
//reimplemented methods
136139

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

src/core/geometry/qgsmultilinestringv2.cpp

+11
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

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ 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 QgsMultiCurveV2*/
46+
QgsAbstractGeometryV2* toCurveType() const override;
47+
4548
protected:
4649

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

src/core/geometry/qgsmultipolygonv2.cpp

+10
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

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ 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 QgsMultiSurfaceV2*/
47+
QgsAbstractGeometryV2* toCurveType() const override;
48+
4649
protected:
4750

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

src/core/geometry/qgspolygonv2.cpp

+12
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

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class CORE_EXPORT QgsPolygonV2: public QgsCurvePolygonV2
5050

5151
QgsPolygonV2* surfaceToPolygon() const override;
5252

53+
/** Returns the geometry converted to QgsCurvePolygonV2*/
54+
QgsAbstractGeometryV2* toCurveType() const override;
55+
5356
void addInteriorRing( QgsCurveV2* ring ) override;
5457
//overridden to handle LineString25D rings
5558
virtual void setExteriorRing( QgsCurveV2* ring ) override;

src/core/qgsvectordataprovider.cpp

+104
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

@@ -582,4 +587,103 @@ QSet<QString> QgsVectorDataProvider::layerDependencies() const
582587
return QSet<QString>();
583588
}
584589

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

src/core/qgsvectordataprovider.h

+4
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,10 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
429429
/** Old-style mapping of index to name for QgsPalLabeling fix */
430430
QgsAttrPalIndexNameHash mAttrPalIndexName;
431431

432+
/** Converts the geometry to the provider type if possible / necessary
433+
@return the converted geometry or nullptr if no conversion was necessary or possible*/
434+
QgsGeometry* convertToProviderType( const QgsGeometry& geom ) const;
435+
432436
private:
433437
/** Old notation **/
434438
QMap<QString, QVariant::Type> mOldTypeList;

src/providers/postgres/qgspostgresprovider.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -2306,8 +2306,11 @@ void QgsPostgresProvider::appendGeomParam( const QgsGeometry *geom, QStringList
23062306
}
23072307

23082308
QString param;
2309-
const unsigned char *buf = geom->asWkb();
2310-
for ( int i = 0; i < geom->wkbSize(); ++i )
2309+
QScopedPointer<QgsGeometry> convertedGeom( convertToProviderType( *geom ) );
2310+
const unsigned char *buf = convertedGeom ? convertedGeom->asWkb() : geom->asWkb();
2311+
size_t wkbSize = convertedGeom ? convertedGeom->wkbSize() : geom->wkbSize();
2312+
2313+
for ( int i = 0; i < wkbSize; ++i )
23112314
{
23122315
if ( connectionRO()->useWkbHex() )
23132316
param += QString( "%1" ).arg(( int ) buf[i], 2, 16, QChar( '0' ) );

0 commit comments

Comments
 (0)