Skip to content

Commit

Permalink
Port conversion of geometry to provider type to 2.14 branch
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Sep 2, 2016
1 parent a528eb9 commit b14255c
Show file tree
Hide file tree
Showing 19 changed files with 203 additions and 2 deletions.
6 changes: 6 additions & 0 deletions python/core/geometry/qgsabstractgeometryv2.sip
Expand Up @@ -306,6 +306,12 @@ class QgsAbstractGeometryV2
*/
virtual QgsAbstractGeometryV2* segmentize() const /Factory/;

/** Returns the geometry converted to the more generic curve type.
E.g. QgsLineString -> QgsCompoundCurve, QgsPolygonV2 -> QgsCurvePolygon,
QgsMultiLineString -> QgsMultiCurve, QgsMultiPolygonV2 -> QgsMultiSurface
@return the converted geometry. Caller takes ownership*/
virtual QgsAbstractGeometry* toCurveType() const /Factory/;

/** Returns approximate angle at a vertex. This is usually the average angle between adjacent
* segments, and can be pictured as the orientation of a line following the curvature of the
* geometry at the specified vertex.
Expand Down
4 changes: 4 additions & 0 deletions python/core/geometry/qgslinestringv2.sip
Expand Up @@ -102,6 +102,10 @@ class QgsLineStringV2: public QgsCurveV2
/** Closes the line string by appending the first point to the end of the line, if it is not already closed.*/
void close();

/** Returns the geometry converted to the more generic curve type QgsCompoundCurve
@return the converted geometry. Caller takes ownership*/
QgsAbstractGeometry* toCurveType() const /Factory/;

/** Returns a QPolygonF representing the line string.
*/
QPolygonF asQPolygonF() const;
Expand Down
4 changes: 4 additions & 0 deletions python/core/geometry/qgsmultilinestringv2.sip
Expand Up @@ -20,6 +20,10 @@ class QgsMultiLineStringV2: public QgsMultiCurveV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );

/** Returns the geometry converted to the more generic curve type QgsMultiCurve
@return the converted geometry. Caller takes ownership*/
QgsAbstractGeometry* toCurveType() const /Factory/;

protected:

virtual bool wktOmitChildType() const;
Expand Down
4 changes: 4 additions & 0 deletions python/core/geometry/qgsmultipolygonv2.sip
Expand Up @@ -20,6 +20,10 @@ class QgsMultiPolygonV2: public QgsMultiSurfaceV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g );

/** Returns the geometry converted to the more generic curve type QgsMultiSurface
@return the converted geometry. Caller takes ownership*/
QgsAbstractGeometry* toCurveType() const /Factory/;

protected:

virtual bool wktOmitChildType() const;
Expand Down
4 changes: 4 additions & 0 deletions python/core/geometry/qgspolygonv2.sip
Expand Up @@ -26,6 +26,10 @@ class QgsPolygonV2: public QgsCurvePolygonV2

QgsPolygonV2* surfaceToPolygon() const;

/** Returns the geometry converted to the more generic curve type QgsCurvePolygon
@return the converted geometry. Caller takes ownership*/
QgsAbstractGeometry* toCurveType() const /Factory/;

void addInteriorRing( QgsCurveV2* ring /Transfer/ );
//overridden to handle LineString25D rings
virtual void setExteriorRing( QgsCurveV2* ring /Transfer/ );
Expand Down
4 changes: 4 additions & 0 deletions python/core/qgsvectordataprovider.sip
Expand Up @@ -361,4 +361,8 @@ class QgsVectorDataProvider : QgsDataProvider
void fillMinMaxCache();

void pushError( const QString& msg );

/** Converts the geometry to the provider type if possible / necessary
@return the converted geometry or nullptr if no conversion was necessary or possible*/
QgsGeometry* convertToProviderType( const QgsGeometry& geom ) const /Factory/;
};
6 changes: 6 additions & 0 deletions src/core/geometry/qgsabstractgeometryv2.h
Expand Up @@ -292,6 +292,12 @@ class CORE_EXPORT QgsAbstractGeometryV2
*/
virtual QgsAbstractGeometryV2* segmentize() const { return clone(); }

/** Returns the geometry converted to the more generic curve type.
* E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,
* QgsMultiLineStringV2 -> QgsMultiCurveV2, QgsMultiPolygonV2 -> QgsMultiSurfaceV2
*/
virtual QgsAbstractGeometryV2* toCurveType() const { return 0; }

/** Returns approximate angle at a vertex. This is usually the average angle between adjacent
* segments, and can be pictured as the orientation of a line following the curvature of the
* geometry at the specified vertex.
Expand Down
5 changes: 5 additions & 0 deletions src/core/geometry/qgsgeometry.cpp
Expand Up @@ -132,6 +132,11 @@ QgsAbstractGeometryV2* QgsGeometry::geometry() const

void QgsGeometry::setGeometry( QgsAbstractGeometryV2* geometry )
{
if ( d->geometry == geometry )
{
return;
}

detach( false );
if ( d->geometry )
{
Expand Down
8 changes: 8 additions & 0 deletions src/core/geometry/qgslinestringv2.cpp
Expand Up @@ -17,6 +17,7 @@

#include "qgslinestringv2.h"
#include "qgsapplication.h"
#include "qgscompoundcurvev2.h"
#include "qgscoordinatetransform.h"
#include "qgsgeometryutils.h"
#include "qgsmaptopixel.h"
Expand Down Expand Up @@ -583,6 +584,13 @@ QPolygonF QgsLineStringV2::asQPolygonF() const
return points;
}

QgsAbstractGeometryV2* QgsLineStringV2::toCurveType() const
{
QgsCompoundCurveV2* compoundCurve = new QgsCompoundCurveV2();
compoundCurve->addCurve( clone() );
return compoundCurve;
}

/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests.
Expand Down
3 changes: 3 additions & 0 deletions src/core/geometry/qgslinestringv2.h
Expand Up @@ -132,6 +132,9 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
*/
QPolygonF asQPolygonF() const;

/** Returns the geometry converted to QgsCompoundCurveV2*/
QgsAbstractGeometryV2* toCurveType() const override;

//reimplemented methods

virtual QString geometryType() const override { return "LineString"; }
Expand Down
11 changes: 11 additions & 0 deletions src/core/geometry/qgsmultilinestringv2.cpp
Expand Up @@ -20,6 +20,7 @@ email : marco.hugentobler at sourcepole dot com
#include "qgscompoundcurvev2.h"
#include "qgsgeometryutils.h"
#include "qgslinestringv2.h"
#include "qgsmulticurvev2.h"

QgsMultiLineStringV2* QgsMultiLineStringV2::clone() const
{
Expand Down Expand Up @@ -101,3 +102,13 @@ bool QgsMultiLineStringV2::addGeometry( QgsAbstractGeometryV2* g )
setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiLineString );
return QgsGeometryCollectionV2::addGeometry( g );
}

QgsAbstractGeometryV2* QgsMultiLineStringV2::toCurveType() const
{
QgsMultiCurveV2* multiCurve = new QgsMultiCurveV2();
for ( int i = 0; i < mGeometries.size(); ++i )
{
multiCurve->addGeometry( mGeometries.at( i )->clone() );
}
return multiCurve;
}
3 changes: 3 additions & 0 deletions src/core/geometry/qgsmultilinestringv2.h
Expand Up @@ -42,6 +42,9 @@ class CORE_EXPORT QgsMultiLineStringV2: public QgsMultiCurveV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;

/** Returns the geometry converted to QgsMultiCurveV2*/
QgsAbstractGeometryV2* toCurveType() const override;

protected:

virtual bool wktOmitChildType() const override { return true; }
Expand Down
10 changes: 10 additions & 0 deletions src/core/geometry/qgsmultipolygonv2.cpp
Expand Up @@ -117,3 +117,13 @@ bool QgsMultiPolygonV2::addGeometry( QgsAbstractGeometryV2* g )
setZMTypeFromSubGeometry( g, QgsWKBTypes::MultiPolygon );
return QgsGeometryCollectionV2::addGeometry( g );
}

QgsAbstractGeometryV2* QgsMultiPolygonV2::toCurveType() const
{
QgsMultiSurfaceV2* multiSurface = new QgsMultiSurfaceV2();
for ( int i = 0; i < mGeometries.size(); ++i )
{
multiSurface->addGeometry( mGeometries.at( i )->clone() );
}
return multiSurface;
}
3 changes: 3 additions & 0 deletions src/core/geometry/qgsmultipolygonv2.h
Expand Up @@ -43,6 +43,9 @@ class CORE_EXPORT QgsMultiPolygonV2: public QgsMultiSurfaceV2
/** Adds a geometry and takes ownership. Returns true in case of success*/
virtual bool addGeometry( QgsAbstractGeometryV2* g ) override;

/** Returns the geometry converted to QgsMultiSurfaceV2*/
QgsAbstractGeometryV2* toCurveType() const override;

protected:

virtual bool wktOmitChildType() const override { return true; }
Expand Down
12 changes: 12 additions & 0 deletions src/core/geometry/qgspolygonv2.cpp
Expand Up @@ -240,3 +240,15 @@ QgsPolygonV2* QgsPolygonV2::surfaceToPolygon() const
{
return clone();
}

QgsAbstractGeometryV2* QgsPolygonV2::toCurveType() const
{
QgsCurvePolygonV2* curvePolygon = new QgsCurvePolygonV2();
curvePolygon->setExteriorRing( mExteriorRing->clone() );
int nInteriorRings = mInteriorRings.size();
for ( int i = 0; i < nInteriorRings; ++i )
{
curvePolygon->addInteriorRing( mInteriorRings.at( i )->clone() );
}
return curvePolygon;
}
3 changes: 3 additions & 0 deletions src/core/geometry/qgspolygonv2.h
Expand Up @@ -50,6 +50,9 @@ class CORE_EXPORT QgsPolygonV2: public QgsCurvePolygonV2

QgsPolygonV2* surfaceToPolygon() const override;

/** Returns the geometry converted to QgsCurvePolygonV2*/
QgsAbstractGeometryV2* toCurveType() const override;

void addInteriorRing( QgsCurveV2* ring ) override;
//overridden to handle LineString25D rings
virtual void setExteriorRing( QgsCurveV2* ring ) override;
Expand Down
104 changes: 104 additions & 0 deletions src/core/qgsvectordataprovider.cpp
Expand Up @@ -21,10 +21,15 @@
#include <limits>

#include "qgsvectordataprovider.h"
#include "qgscircularstringv2.h"
#include "qgscompoundcurvev2.h"
#include "qgsfeature.h"
#include "qgsfeatureiterator.h"
#include "qgsfeaturerequest.h"
#include "qgsfield.h"
#include "qgsgeometry.h"
#include "qgsgeometrycollectionv2.h"
#include "qgsgeometryfactory.h"
#include "qgslogger.h"
#include "qgsmessagelog.h"

Expand Down Expand Up @@ -582,4 +587,103 @@ QSet<QString> QgsVectorDataProvider::layerDependencies() const
return QSet<QString>();
}

QgsGeometry* QgsVectorDataProvider::convertToProviderType( const QgsGeometry& geom ) const
{
if ( geom.isEmpty() )
{
return nullptr;
}

QgsAbstractGeometryV2* geometry = geom.geometry();
if ( !geometry )
{
return nullptr;
}

QgsWKBTypes::Type providerGeomType = QgsWKBTypes::Type( geometryType() );

//geom is already in the provider geometry type
if ( geometry->wkbType() == providerGeomType )
{
return nullptr;
}

QgsAbstractGeometryV2* outputGeom = nullptr;

//convert compoundcurve to circularstring (possible if compoundcurve consists of one circular string)
if ( QgsWKBTypes::flatType( providerGeomType ) == QgsWKBTypes::CircularString && QgsWKBTypes::flatType( geometry->wkbType() ) == QgsWKBTypes::CompoundCurve )
{
QgsCompoundCurveV2* compoundCurve = static_cast<QgsCompoundCurveV2*>( geometry );
if ( compoundCurve )
{
if ( compoundCurve->nCurves() == 1 )
{
const QgsCircularStringV2* circularString = dynamic_cast<const QgsCircularStringV2*>( compoundCurve->curveAt( 0 ) );
if ( circularString )
{
outputGeom = circularString->clone();
}
}
}
}

//convert to multitype if necessary
if ( QgsWKBTypes::isMultiType( providerGeomType ) && !QgsWKBTypes::isMultiType( geometry->wkbType() ) )
{
outputGeom = QgsGeometryFactory::geomFromWkbType( providerGeomType );
QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( outputGeom );
if ( geomCollection )
{
geomCollection->addGeometry( geometry->clone() );
}
}

//convert to curved type if necessary
if ( !QgsWKBTypes::isCurvedType( geometry->wkbType() ) && QgsWKBTypes::isCurvedType( providerGeomType ) )
{
QgsAbstractGeometryV2* curveGeom = outputGeom ? outputGeom->toCurveType() : geometry->toCurveType();
if ( curveGeom )
{
delete outputGeom;
outputGeom = curveGeom;
}
}

//convert to linear type from curved type
if ( QgsWKBTypes::isCurvedType( geometry->wkbType() ) && !QgsWKBTypes::isCurvedType( providerGeomType ) )
{
QgsAbstractGeometryV2* segmentizedGeom = nullptr;
segmentizedGeom = outputGeom ? outputGeom->segmentize() : geometry->segmentize();
if ( segmentizedGeom )
{
delete outputGeom;
outputGeom = segmentizedGeom;
}
}

//set z/m types
if ( QgsWKBTypes::hasZ( providerGeomType ) )
{
if ( !outputGeom )
{
outputGeom = geometry->clone();
}
outputGeom->addZValue();
}
if ( QgsWKBTypes::hasM( providerGeomType ) )
{
if ( !outputGeom )
{
outputGeom = geometry->clone();
}
outputGeom->addMValue();
}

if ( outputGeom )
{
return new QgsGeometry( outputGeom );
}
return nullptr;
}

QStringList QgsVectorDataProvider::smEncodings;
4 changes: 4 additions & 0 deletions src/core/qgsvectordataprovider.h
Expand Up @@ -429,6 +429,10 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** Old-style mapping of index to name for QgsPalLabeling fix */
QgsAttrPalIndexNameHash mAttrPalIndexName;

/** Converts the geometry to the provider type if possible / necessary
@return the converted geometry or nullptr if no conversion was necessary or possible*/
QgsGeometry* convertToProviderType( const QgsGeometry& geom ) const;

private:
/** Old notation **/
QMap<QString, QVariant::Type> mOldTypeList;
Expand Down
7 changes: 5 additions & 2 deletions src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -2306,8 +2306,11 @@ void QgsPostgresProvider::appendGeomParam( const QgsGeometry *geom, QStringList
}

QString param;
const unsigned char *buf = geom->asWkb();
for ( int i = 0; i < geom->wkbSize(); ++i )
QScopedPointer<QgsGeometry> convertedGeom( convertToProviderType( *geom ) );
const unsigned char *buf = convertedGeom ? convertedGeom->asWkb() : geom->asWkb();
size_t wkbSize = convertedGeom ? convertedGeom->wkbSize() : geom->wkbSize();

for ( int i = 0; i < wkbSize; ++i )
{
if ( connectionRO()->useWkbHex() )
param += QString( "%1" ).arg(( int ) buf[i], 2, 16, QChar( '0' ) );
Expand Down

0 comments on commit b14255c

Please sign in to comment.