Skip to content

Commit

Permalink
Move conversion of added/changed geometry to vector data provider
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed May 6, 2016
1 parent bd6d22d commit 11b7a27
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 82 deletions.
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 0 if no conversion was necessary or possible*/
QgsGeometry* convertToProviderType( const QgsGeometry* geom ) const /Factory/;
};
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 @@ -572,4 +577,103 @@ QSet<QString> QgsVectorDataProvider::layerDependencies() const
return QSet<QString>();
}

QgsGeometry* QgsVectorDataProvider::convertToProviderType( const QgsGeometry* geom ) const
{
if ( !geom )
{
return 0;
}

QgsAbstractGeometryV2* geometry = geom->geometry();
if ( !geometry )
{
return 0;
}

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

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

QgsAbstractGeometryV2* outputGeom = 0;

//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 = 0;
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 0;
}

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 0 if no conversion was necessary or possible*/
QgsGeometry* convertToProviderType( const QgsGeometry* geom ) const;

private:
/** Old notation **/
QMap<QString, QVariant::Type> mOldTypeList;
Expand Down
77 changes: 0 additions & 77 deletions src/core/qgsvectorlayereditbuffer.cpp
Expand Up @@ -276,23 +276,6 @@ bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
int cap = provider->capabilities();
bool success = true;

//convert added features to a type accepted by the backend
QgsFeatureMap::iterator addedIt = mAddedFeatures.begin();
for ( ; addedIt != mAddedFeatures.end(); ++addedIt )
{
QgsGeometry* geom = addedIt.value().geometry();
if ( geom )
{
geom->setGeometry( outputGeometry( geom->geometry() ) );
}
}

QgsGeometryMap::iterator changedIt = mChangedGeometries.begin();
for ( ; changedIt != mChangedGeometries.end(); ++changedIt )
{
changedIt.value().setGeometry( outputGeometry( changedIt.value().geometry() ) );
}

// geometry updates attribute updates
// yes no => changeGeometryValues
// no yes => changeAttributeValues
Expand Down Expand Up @@ -689,63 +672,3 @@ void QgsVectorLayerEditBuffer::updateLayerFields()
{
L->updateFields();
}

QgsAbstractGeometryV2* QgsVectorLayerEditBuffer::outputGeometry( QgsAbstractGeometryV2* geom ) const
{
if ( !geom || !L )
{
delete geom;
return nullptr;
}

QgsWKBTypes::Type providerGeomType = QGis::fromOldWkbType( L->dataProvider()->geometryType() );

if ( geom->wkbType() == providerGeomType )
{
return geom;
}

QgsAbstractGeometryV2* outputGeom = geom;

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

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

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

//set z/m types
if ( QgsWKBTypes::hasZ( providerGeomType ) )
{
outputGeom->addZValue();
}
if ( QgsWKBTypes::hasM( providerGeomType ) )
{
outputGeom->addMValue();
}
return outputGeom;
}
3 changes: 0 additions & 3 deletions src/core/qgsvectorlayereditbuffer.h
Expand Up @@ -188,9 +188,6 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject

/** Changed geometries which are not commited. */
QgsGeometryMap mChangedGeometries;

private:
QgsAbstractGeometryV2* outputGeometry( QgsAbstractGeometryV2* geom ) const;
};

#endif // QGSVECTORLAYEREDITBUFFER_H
9 changes: 7 additions & 2 deletions src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -2371,14 +2371,19 @@ void QgsPostgresProvider::appendGeomParam( const QgsGeometry *geom, QStringList
}

QString param;
const unsigned char *buf = geom->asWkb();
for ( int i = 0; i < geom->wkbSize(); ++i )

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' ) );
else
param += QString( "\\%1" ).arg(( int ) buf[i], 3, 8, QChar( '0' ) );
}
delete convertedGeom;
params << param;
}

Expand Down

0 comments on commit 11b7a27

Please sign in to comment.