Skip to content

Commit

Permalink
[FEATURE] Support for Oracle circular string and compound curve edition
Browse files Browse the repository at this point in the history
  • Loading branch information
troopa81 authored and nyalldawson committed Jan 13, 2020
1 parent 0d4d825 commit ac7d365
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/providers/oracle/qgsoracleconn.cpp
Expand Up @@ -647,8 +647,10 @@ QString QgsOracleConn::databaseTypeFilter( const QString &alias, QString geomCol
return QStringLiteral( "mod(%1.sdo_gtype,100) IN (1,5)" ).arg( geomCol );
case QgsWkbTypes::LineString:
case QgsWkbTypes::LineString25D:
case QgsWkbTypes::LineStringZ:
case QgsWkbTypes::MultiLineString:
case QgsWkbTypes::MultiLineString25D:
case QgsWkbTypes::MultiLineStringZ:
return QStringLiteral( "mod(%1.sdo_gtype,100) IN (2,6)" ).arg( geomCol );
case QgsWkbTypes::Polygon:
case QgsWkbTypes::Polygon25D:
Expand Down
66 changes: 58 additions & 8 deletions src/providers/oracle/qgsoracleprovider.cpp
Expand Up @@ -1910,7 +1910,7 @@ void QgsOracleProvider::appendGeomParam( const QgsGeometry &geom, QSqlQuery &qry
{
g.gtype = SDO_GTYPE( dim, GtLine );
int nLines = 1;
if ( type == QgsWkbTypes::MultiLineString25D || type == QgsWkbTypes::MultiLineString )
if ( type == QgsWkbTypes::MultiLineString25D || type == QgsWkbTypes::MultiLineString || type == QgsWkbTypes::MultiLineStringZ )
{
g.gtype = SDO_GTYPE( dim, GtMultiLine );
nLines = *ptr.iPtr++;
Expand Down Expand Up @@ -2006,15 +2006,61 @@ void QgsOracleProvider::appendGeomParam( const QgsGeometry &geom, QSqlQuery &qry
}
break;

// currently unsupported curved types
case QgsWkbTypes::CircularString:
case QgsWkbTypes::CircularStringZ:
case QgsWkbTypes::CircularStringM:
case QgsWkbTypes::CircularStringZM:
case QgsWkbTypes::CompoundCurve:
case QgsWkbTypes::CompoundCurveZ:
case QgsWkbTypes::CompoundCurveM:
case QgsWkbTypes::CompoundCurveZM:
dim = 3;
FALLTHROUGH

case QgsWkbTypes::CircularString:
case QgsWkbTypes::CompoundCurve:
{
g.gtype = SDO_GTYPE( dim, GtLine );
int nLines = 1;
QgsWkbTypes::Type lineType = type;
if ( type == QgsWkbTypes::CompoundCurve || type == QgsWkbTypes::CompoundCurveZ )
{
g.gtype = SDO_GTYPE( dim, GtMultiLine );
nLines = *ptr.iPtr++;

g.eleminfo << iOrdinate << 4 << nLines;

ptr.ucPtr++; // Skip endianness of first linestring
lineType = ( QgsWkbTypes::Type ) * ptr.iPtr++; // type of first linestring
}

for ( int iLine = 0; iLine < nLines; iLine++ )
{
bool circularString = lineType == QgsWkbTypes::CircularString || lineType == QgsWkbTypes::CircularStringZ;

g.eleminfo << iOrdinate << 2 << ( circularString ? 2 : 1 );

for ( int i = 0, n = *ptr.iPtr++; i < n; i++ )
{
// Inside a compound curve, two consecutives lines share start/end points
// We don't repeat this point in ordinates, so we skip the last point (except for last line)
if ( ( type == QgsWkbTypes::CompoundCurve || type == QgsWkbTypes::CompoundCurveZ )
&& i == n - 1 && iLine < nLines - 1 )
{
ptr.dPtr += dim;
continue;
}

g.ordinates << *ptr.dPtr++;
g.ordinates << *ptr.dPtr++;
if ( dim == 3 )
g.ordinates << *ptr.dPtr++;

iOrdinate += dim;
}

ptr.ucPtr++; // Skip endianness of next linestring
lineType = ( QgsWkbTypes::Type ) * ptr.iPtr++; // type of next linestring
}
}
break;



case QgsWkbTypes::CurvePolygon:
case QgsWkbTypes::CurvePolygonZ:
case QgsWkbTypes::CurvePolygonM:
Expand All @@ -2041,6 +2087,10 @@ void QgsOracleProvider::appendGeomParam( const QgsGeometry &geom, QSqlQuery &qry
case QgsWkbTypes::MultiLineStringZM:
case QgsWkbTypes::MultiPolygonM:
case QgsWkbTypes::MultiPolygonZM:
case QgsWkbTypes::CircularStringM:
case QgsWkbTypes::CircularStringZM:
case QgsWkbTypes::CompoundCurveM:
case QgsWkbTypes::CompoundCurveZM:

// other unsupported or missing geometry types
case QgsWkbTypes::GeometryCollection:
Expand Down
55 changes: 54 additions & 1 deletion tests/src/python/test_provider_oracle.py
Expand Up @@ -21,7 +21,8 @@
NULL,
QgsProject,
QgsTransactionGroup,
QgsFeature
QgsFeature,
QgsGeometry
)

from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant
Expand Down Expand Up @@ -257,6 +258,58 @@ def testCurves(self):
self.assertTrue(
compareWkt(features[8].geometry().asWkt(), 'MultiCurve (CompoundCurve ((-1 -5, 1 2),CircularString (1 2, 5 4, 7 2.2, 10 0.1, 13 4),(13 4, 17 -6)),CompoundCurve (CircularString (1 2, 5 4, 7 2.2, 10 0.1, 13 4)),CompoundCurve ((-11 -3, 5 7, 10 -1)))', 0.00001), features[8].geometry().asWkt())

def testEditCurves(self):

def test_geom(layer, pk, wkt):
# insert geom in layer
self.assertTrue(layer.startEditing())
feature = QgsFeature(layer.fields())
geom = QgsGeometry.fromWkt(wkt)
feature.setAttributes([pk])
feature.setGeometry(geom)
self.assertTrue(layer.addFeature(feature))
self.assertTrue(layer.commitChanges())

res_wkt = layer.getFeature(pk).geometry().asWkt()
self.assertTrue(compareWkt(res_wkt, wkt, 0.00001), "\nactual = {}\nexpected = {}".format(res_wkt, wkt))

self.execSQLCommand('DROP TABLE "QGIS"."EDIT_CURVE_DATA"', ignore_errors=True)
self.execSQLCommand("""CREATE TABLE QGIS.EDIT_CURVE_DATA ("pk" INTEGER PRIMARY KEY, GEOM SDO_GEOMETRY)""")

lines = QgsVectorLayer(
self.dbconn + ' sslmode=disable key=\'pk\' srid=3857 type=LineString table="QGIS"."EDIT_CURVE_DATA" (GEOM) sql=',
'test_lines', 'oracle')
self.assertTrue(lines.isValid())

test_geom(lines, 1, 'LineString (1 2, 3 4, 5 6)')
test_geom(lines, 2, 'CircularString (1 2, 5 4, 7 2.2, 10 0.1, 13 4)')
test_geom(lines, 3, 'CompoundCurve ((-1 -5, 1 2),CircularString (1 2, 5 4, 7 2.20, 10 0.1, 13 4),(13 4, 17 -6))')

lines_z = QgsVectorLayer(
self.dbconn + ' sslmode=disable key=\'pk\' srid=3857 type=LineStringZ table="QGIS"."EDIT_CURVE_DATA" (GEOM) sql=',
'test_lines', 'oracle')
self.assertTrue(lines_z.isValid())

test_geom(lines_z, 4, 'LineStringZ (1 2 3, 4 5 6, 7 8 9)')
test_geom(lines_z, 5, 'CircularStringZ (1 2 1, 5 4 2, 7 2.2 3, 10 0.1 4, 13 4 5)')
test_geom(lines_z, 6, 'CompoundCurveZ ((-1 -5 1, 1 2 2),CircularStringZ (1 2 2, 5 4 3, 7 2.20 4, 10 0.1 5, 13 4 6),(13 4 6, 17 -6 7))')

multi_lines = QgsVectorLayer(
self.dbconn + ' sslmode=disable key=\'pk\' srid=3857 type=MultiLineString table="QGIS"."EDIT_CURVE_DATA" (GEOM) sql=',
'test_multilines', 'oracle')
self.assertTrue(multi_lines.isValid())

test_geom(multi_lines, 7, 'MultiLineString ((1 2, 3 4),(5 6, 7 8, 9 10), (11 12, 13 14))')
test_geom(multi_lines, 8, 'MultiLineString ((1 2, 3 4),(5 6, 7 8, 9 10))')

multi_lines_z = QgsVectorLayer(
self.dbconn + ' sslmode=disable key=\'pk\' srid=3857 type=MultiLineStringZ table="QGIS"."EDIT_CURVE_DATA" (GEOM) sql=',
'test_multilines', 'oracle')
self.assertTrue(multi_lines_z.isValid())

test_geom(multi_lines_z, 9, 'MultiLineStringZ ((1 2 11, 3 4 -11),(5 6 9, 7 8 1, 9 10 -3))')
test_geom(multi_lines_z, 10, 'MultiLineStringZ ((1 2 1, 3 4 2),(5 6 3, 7 8 4, 9 10 5), (11 12 6, 13 14 7))')

def testSurfaces(self):
vl = QgsVectorLayer('%s table="QGIS"."POLY_DATA" (GEOM) srid=4326 type=POLYGON sql=' %
(self.dbconn), "testpoly", "oracle")
Expand Down

0 comments on commit ac7d365

Please sign in to comment.