Skip to content

Commit

Permalink
Merge pull request #2605 from nyalldawson/delimited
Browse files Browse the repository at this point in the history
Add support for curved geometries and M/Z values to delimited text provider
  • Loading branch information
ccrook committed Dec 22, 2015
2 parents 5838819 + 809c925 commit 9d81938
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 45 deletions.
Expand Up @@ -377,7 +377,7 @@ QgsGeometry* QgsDelimitedTextFeatureIterator::loadGeometryWkt( const QStringList
}

isNull = false;
geom = QgsDelimitedTextProvider::geomFromWkt( sWkt, mSource->mWktHasPrefix, mSource->mWktHasZM );
geom = QgsDelimitedTextProvider::geomFromWkt( sWkt, mSource->mWktHasPrefix );

if ( geom && geom->type() != mSource->mGeometryType )
{
Expand Down Expand Up @@ -482,7 +482,6 @@ QgsDelimitedTextFeatureSource::QgsDelimitedTextFeatureSource( const QgsDelimited
, mXFieldIndex( p->mXFieldIndex )
, mYFieldIndex( p->mYFieldIndex )
, mWktFieldIndex( p->mWktFieldIndex )
, mWktHasZM( p->mWktHasZM )
, mWktHasPrefix( p->mWktHasPrefix )
, mGeometryType( p->mGeometryType )
, mDecimalPoint( p->mDecimalPoint )
Expand Down
Expand Up @@ -45,7 +45,6 @@ class QgsDelimitedTextFeatureSource : public QgsAbstractFeatureSource
int mXFieldIndex;
int mYFieldIndex;
int mWktFieldIndex;
bool mWktHasZM;
bool mWktHasPrefix;
QGis::GeometryType mGeometryType;
QString mDecimalPoint;
Expand Down
15 changes: 3 additions & 12 deletions src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
Expand Up @@ -53,8 +53,6 @@ static const QString TEXT_PROVIDER_DESCRIPTION = "Delimited text data provider";
static const int SUBSET_ID_THRESHOLD_FACTOR = 10;

QRegExp QgsDelimitedTextProvider::WktPrefixRegexp( "^\\s*(?:\\d+\\s+|SRID\\=\\d+\\;)", Qt::CaseInsensitive );
QRegExp QgsDelimitedTextProvider::WktZMRegexp( "\\s*(?:z|m|zm)(?=\\s*\\()", Qt::CaseInsensitive );
QRegExp QgsDelimitedTextProvider::WktCrdRegexp( "(\\-?\\d+(?:\\.\\d*)?\\s+\\-?\\d+(?:\\.\\d*)?)\\s[\\s\\d\\.\\-]+" );
QRegExp QgsDelimitedTextProvider::CrdDmsRegexp( "^\\s*(?:([-+nsew])\\s*)?(\\d{1,3})(?:[^0-9.]+([0-5]?\\d))?[^0-9.]+([0-5]?\\d(?:\\.\\d+)?)[^0-9.]*([-+nsew])?\\s*$", Qt::CaseInsensitive );

QgsDelimitedTextProvider::QgsDelimitedTextProvider( const QString& uri )
Expand All @@ -67,7 +65,6 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( const QString& uri )
, mXFieldIndex( -1 )
, mYFieldIndex( -1 )
, mWktFieldIndex( -1 )
, mWktHasZM( false )
, mWktHasPrefix( false )
, mXyDms( false )
, mSubsetString( "" )
Expand Down Expand Up @@ -447,9 +444,7 @@ void QgsDelimitedTextProvider::scanFile( bool buildIndexes )
QgsGeometry *geom = nullptr;
if ( !mWktHasPrefix && sWkt.indexOf( WktPrefixRegexp ) >= 0 )
mWktHasPrefix = true;
if ( !mWktHasZM && sWkt.indexOf( WktZMRegexp ) >= 0 )
mWktHasZM = true;
geom = geomFromWkt( sWkt, mWktHasPrefix, mWktHasZM );
geom = geomFromWkt( sWkt, mWktHasPrefix );

if ( geom )
{
Expand Down Expand Up @@ -812,7 +807,7 @@ void QgsDelimitedTextProvider::rescanFile()
mUseSpatialIndex = buildSpatialIndex;
}

QgsGeometry *QgsDelimitedTextProvider::geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp, bool wktHasZM )
QgsGeometry *QgsDelimitedTextProvider::geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp )
{
QgsGeometry *geom = nullptr;
try
Expand All @@ -822,10 +817,6 @@ QgsGeometry *QgsDelimitedTextProvider::geomFromWkt( QString &sWkt, bool wktHasPr
sWkt.remove( WktPrefixRegexp );
}

if ( wktHasZM )
{
sWkt.remove( WktZMRegexp ).replace( WktCrdRegexp, "\\1" );
}
geom = QgsGeometry::fromWkt( sWkt );
}
catch ( ... )
Expand Down Expand Up @@ -1148,7 +1139,7 @@ bool QgsDelimitedTextProvider::isValid()

int QgsDelimitedTextProvider::capabilities() const
{
return SelectAtId | CreateSpatialIndex;
return SelectAtId | CreateSpatialIndex | CircularGeometries;
}


Expand Down
21 changes: 2 additions & 19 deletions src/providers/delimitedtext/qgsdelimitedtextprovider.h
Expand Up @@ -217,9 +217,6 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider

private:

static QRegExp WktZMRegexp;
static QRegExp WktCrdRegexp;

void scanFile( bool buildIndexes );
void rescanFile();
void resetCachedSubset();
Expand All @@ -231,7 +228,7 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
void setUriParameter( const QString& parameter, const QString& value );


static QgsGeometry *geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp, bool wktHasZM );
static QgsGeometry *geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp );
static bool pointFromXY( QString &sX, QString &sY, QgsPoint &point, const QString& decimalPoint, bool xyDms );
static double dmsStringToDouble( const QString &sX, bool *xOk );

Expand All @@ -258,13 +255,8 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
int mYFieldIndex;
int mWktFieldIndex;

// Handling of WKT types with .. Z, .. M, and .. ZM geometries (ie
// Z values and/or measures). mWktZMRegexp is used to test for and
// remove the Z or M fields, and mWktCrdRegexp is used to remove the
// extra coordinate values. mWktPrefix regexp is used to clean up
// mWktPrefix regexp is used to clean up
// prefixes sometimes used for WKT (postgis EWKT, informix SRID)

bool mWktHasZM;
bool mWktHasPrefix;

//! Layer extent
Expand Down Expand Up @@ -295,15 +287,6 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
//! Record file updates, flags rescan required
bool mRescanRequired;

struct wkbPoint
{
unsigned char byteOrder;
quint32 wkbType;
double x;
double y;
};
wkbPoint mWKBpt;

// Coordinate reference sytem
QgsCoordinateReferenceSystem mCrs;

Expand Down
36 changes: 27 additions & 9 deletions tests/src/python/test_qgsdelimitedtextprovider_wanted.py
Expand Up @@ -460,13 +460,13 @@ def test_011_read_wkt():
'id': u'10',
'description': u'Measure in point',
'#fid': 11,
'#geometry': 'Point (10 20)',
'#geometry': 'PointM (10 20 30)',
},
}
wanted['log'] = [
u'Errors in file testwkt.csv',
u'1 records discarded due to invalid geometry definitions',
u'7 records discarded due to incompatible geometry types',
u'10 records discarded due to incompatible geometry types',
u'The following lines were not loaded into QGIS due to errors:',
u'Invalid WKT at line 8',
]
Expand Down Expand Up @@ -507,13 +507,13 @@ def test_012_read_wkt_point():
'id': u'10',
'description': u'Measure in point',
'#fid': 11,
'#geometry': 'Point (10 20)',
'#geometry': 'PointM (10 20 30)',
},
}
wanted['log'] = [
u'Errors in file testwkt.csv',
u'1 records discarded due to invalid geometry definitions',
u'7 records discarded due to incompatible geometry types',
u'10 records discarded due to incompatible geometry types',
u'The following lines were not loaded into QGIS due to errors:',
u'Invalid WKT at line 8',
]
Expand Down Expand Up @@ -542,25 +542,37 @@ def test_013_read_wkt_line():
'id': u'11',
'description': u'Measure in line',
'#fid': 12,
'#geometry': 'LineString (10 20, 11 21)',
'#geometry': 'LineStringM (10 20 30, 11 21 31)',
},
13: {
'id': u'12',
'description': u'Z in line',
'#fid': 13,
'#geometry': 'LineString (10 20, 11 21)',
'#geometry': 'LineStringZ (10 20 30, 11 21 31)',
},
14: {
'id': u'13',
'description': u'Measure and Z in line',
'#fid': 14,
'#geometry': 'LineString (10 20, 11 21)',
'#geometry': 'LineStringZM (10 20 30 40, 11 21 31 41)',
},
15: {
'id': u'14',
'description': u'CircularString',
'#fid': 15,
'#geometry': 'CircularString (268 415, 227 505, 227 406)',
},
17: {
'id': u'16',
'description': u'CompoundCurve',
'#fid': 17,
'#geometry': 'CompoundCurve ((5 3, 5 13), CircularString(5 13, 7 15, 9 13), (9 13, 9 3), CircularString(9 3, 7 1, 5 3))',
},
}
wanted['log'] = [
u'Errors in file testwkt.csv',
u'1 records discarded due to invalid geometry definitions',
u'7 records discarded due to incompatible geometry types',
u'8 records discarded due to incompatible geometry types',
u'The following lines were not loaded into QGIS due to errors:',
u'Invalid WKT at line 8',
]
Expand All @@ -585,11 +597,17 @@ def test_014_read_wkt_polygon():
'#fid': 7,
'#geometry': 'MultiPolygon (((10 10,10 20,20 20,20 10,10 10),(14 14,14 16,16 16,14 14)),((30 30,30 35,35 35,30 30)))',
},
16: {
'id': u'15',
'description': u'CurvePolygon',
'#fid': 16,
'#geometry': 'CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3))',
},
}
wanted['log'] = [
u'Errors in file testwkt.csv',
u'1 records discarded due to invalid geometry definitions',
u'10 records discarded due to incompatible geometry types',
u'12 records discarded due to incompatible geometry types',
u'The following lines were not loaded into QGIS due to errors:',
u'Invalid WKT at line 8',
]
Expand Down
6 changes: 4 additions & 2 deletions tests/testdata/delimitedtext/testwkt.csv
Expand Up @@ -9,7 +9,9 @@ id|description|geom_wkt
8|EWKT prefix|SRID=1234;POINT(10 10)
9|Informix prefix|1 POINT(10 10)
10|Measure in point|POINTM(10 20 30)
11|Measure in line|LINESTRING(10.0 20.0 30.0, 11.0 21.0 31.0)
11|Measure in line|LINESTRINGM(10.0 20.0 30.0, 11.0 21.0 31.0)
12|Z in line|LINESTRING Z(10.0 20.0 30.0, 11.0 21.0 31.0)
13|Measure and Z in line|LINESTRING ZM(10.0 20.0 30.0 40.0, 11.0 21.0 31.0 41.0)

14|CircularString|CIRCULARSTRING(268 415,227 505,227 406)
15|CurvePolygon|CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))
16|CompoundCurve|COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))

0 comments on commit 9d81938

Please sign in to comment.