Skip to content
Permalink
Browse files

[virtual layers] support curved geometries (segmentized)

  • Loading branch information
olivierdalang authored and nyalldawson committed Aug 30, 2020
1 parent 71d0948 commit 1cb067b4c7cbbcd075b34c8e665b364ea142680c
@@ -67,7 +67,9 @@ void qgsGeometryToSpatialiteBlob( const QgsGeometry &geom, int32_t srid, char *&
{
const int header_len = SpatialiteBlobHeader::LENGTH;

QByteArray wkb( geom.asWkb() );
// we segment the geometry as spatialite doesn't support curves
std::unique_ptr < QgsAbstractGeometry > segmentized( geom.constGet()->segmentize() );
QByteArray wkb( segmentized->asWkb() );

const int wkb_size = wkb.length();
size = header_len + wkb_size;
@@ -219,13 +219,17 @@ struct VTable
}

QgsVectorDataProvider *provider = mLayer ? mLayer->dataProvider() : mProvider;
if ( provider->wkbType() != QgsWkbTypes::NoGeometry )

// spatialite doesn't support curved geometries, it will be converted to linear in qgsGeometryToSpatialiteBlob
QgsWkbTypes::Type layerType = QgsWkbTypes::linearType( provider->wkbType() );

if ( layerType != QgsWkbTypes::NoGeometry )
{
// we have here a convenient hack
// the type of a column can be declared with two numeric arguments, usually for setting numeric precision
// we are using them to set the geometry type and srid
// these will be reused by the provider when it will introspect the query to detect types
sqlFields << QStringLiteral( "geometry geometry(%1,%2)" ).arg( provider->wkbType() ).arg( provider->crs().postgisSrid() );
sqlFields << QStringLiteral( "geometry geometry(%1,%2)" ).arg( layerType ).arg( provider->crs().postgisSrid() );

// add a hidden field for rtree filtering
sqlFields << QStringLiteral( "_search_frame_ HIDDEN BLOB" );
@@ -357,7 +357,11 @@ def test_geometryTypes(self):
(3, "POLYGON", "((0 0,1 0,1 1,0 0))"),
(4, "MULTIPOINT", "((1 1))"),
(5, "MULTILINESTRING", "((0 0,1 0),(0 1,1 1))"),
(6, "MULTIPOLYGON", "(((0 0,1 0,1 1,0 0)),((2 2,3 0,3 3,2 2)))")]
(6, "MULTIPOLYGON", "(((0 0,1 0,1 1,0 0)),((2 2,3 0,3 3,2 2)))"),
(9, "COMPOUNDCURVE", "(CIRCULARSTRING(0 0, 1 0, 1 1))"),
(10, "CURVEPOLYGON", "(COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 0, 1 1)))"),
(11, "MULTICURVE", "(COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 0, 1 1)),COMPOUNDCURVE(CIRCULARSTRING(2 2, 3 2, 3 3)))"),
(12, "MULTISURFACE", "(CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 0, 1 1))),CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(2 2, 3 2, 3 3))))")]
for wkb_type, wkt_type, wkt in geo:
l = QgsVectorLayer("%s?crs=epsg:4326" % wkt_type, "m1", "memory", QgsVectorLayer.LayerOptions(False))
self.assertEqual(l.isValid(), True)
@@ -372,7 +376,13 @@ def test_geometryTypes(self):
l2 = QgsVectorLayer("?layer_ref=%s" % l.id(), "vtab", "virtual", QgsVectorLayer.LayerOptions(False))
self.assertEqual(l2.isValid(), True)
self.assertEqual(l2.dataProvider().featureCount(), 1)
self.assertEqual(l2.dataProvider().wkbType(), wkb_type)
# we ensure the geom type matches the original (semgentized) type
self.assertEqual(l2.dataProvider().wkbType(), QgsWkbTypes.linearType(wkb_type))

# we ensure the geometry still matches the original (segmentized) geometry
f2 = QgsFeature()
l2.getFeatures().nextFeature(f2)
self.assertEqual(f2.geometry().asWkt(), f1.geometry().constGet().segmentize().asWkt())

QgsProject.instance().removeMapLayer(l.id())

0 comments on commit 1cb067b

Please sign in to comment.
You can’t perform that action at this time.