@@ -114,7 +114,8 @@ class GEOSGeomScopedPtr
114114 GEOSGeometry* mGeom ;
115115};
116116
117- QgsGeos::QgsGeos ( const QgsAbstractGeometryV2* geometry, int precision ) : QgsGeometryEngine( geometry ), mGeos( 0 ), mGeosPrepared( 0 )
117+ QgsGeos::QgsGeos ( const QgsAbstractGeometryV2* geometry, double precision )
118+ : QgsGeometryEngine( geometry ), mGeos( 0 ), mGeosPrepared( 0 ), mPrecision( precision )
118119{
119120 cacheGeos ();
120121}
@@ -149,7 +150,7 @@ void QgsGeos::cacheGeos() const
149150 return ;
150151 }
151152
152- mGeos = asGeos ( mGeometry );
153+ mGeos = asGeos ( mGeometry , mPrecision );
153154}
154155
155156QgsAbstractGeometryV2* QgsGeos::intersection ( const QgsAbstractGeometryV2& geom, QString* errorMsg ) const
@@ -174,7 +175,7 @@ QgsAbstractGeometryV2* QgsGeos::combine( const QList< const QgsAbstractGeometryV
174175 geosGeometries.resize ( geomList.size () );
175176 for ( int i = 0 ; i < geomList.size (); ++i )
176177 {
177- geosGeometries[i] = asGeos ( geomList.at ( i ) );
178+ geosGeometries[i] = asGeos ( geomList.at ( i ), mPrecision );
178179 }
179180
180181 GEOSGeometry* geomUnion = 0 ;
@@ -204,7 +205,7 @@ double QgsGeos::distance( const QgsAbstractGeometryV2& geom, QString* errorMsg )
204205 return distance;
205206 }
206207
207- GEOSGeometry* otherGeosGeom = asGeos ( &geom );
208+ GEOSGeometry* otherGeosGeom = asGeos ( &geom, mPrecision );
208209 if ( !otherGeosGeom )
209210 {
210211 return distance;
@@ -321,12 +322,12 @@ int QgsGeos::splitGeometry( const QgsLineStringV2& splitLine,
321322 {
322323 if ( splitLine.numPoints () > 1 )
323324 {
324- splitLineGeos = createGeosLinestring ( &splitLine );
325+ splitLineGeos = createGeosLinestring ( &splitLine, mPrecision );
325326 }
326327 else if ( splitLine.numPoints () == 1 )
327328 {
328329 QgsPointV2 pt = splitLine.pointN ( 0 );
329- splitLineGeos = createGeosPoint ( &pt, 2 );
330+ splitLineGeos = createGeosPoint ( &pt, 2 , mPrecision );
330331 }
331332 else
332333 {
@@ -490,7 +491,7 @@ GEOSGeometry* QgsGeos::linePointDifference( GEOSGeometry* GEOSsplitPoint ) const
490491
491492 delete splitGeom;
492493 delete multiCurve;
493- return asGeos ( &lines );
494+ return asGeos ( &lines, mPrecision );
494495}
495496
496497int QgsGeos::splitLinearGeometry ( GEOSGeometry* splitLine, QList<QgsAbstractGeometryV2*>& newGeometries ) const
@@ -958,7 +959,7 @@ QgsPointV2 QgsGeos::coordSeqPoint( const GEOSCoordSequence* cs, int i, bool hasZ
958959 return QgsPointV2 ( t, x, y, z, m );
959960}
960961
961- GEOSGeometry* QgsGeos::asGeos ( const QgsAbstractGeometryV2* geom )
962+ GEOSGeometry* QgsGeos::asGeos ( const QgsAbstractGeometryV2* geom, double precision )
962963{
963964 int coordDims = 2 ;
964965 if ( geom->is3D () )
@@ -976,16 +977,16 @@ GEOSGeometry* QgsGeos::asGeos( const QgsAbstractGeometryV2* geom )
976977 if ( curve )
977978 {
978979 QScopedPointer< QgsLineStringV2> lineString ( curve->curveToLine () );
979- return createGeosLinestring ( lineString.data () );
980+ return createGeosLinestring ( lineString.data (), precision );
980981 }
981982 else if ( curvePolygon )
982983 {
983984 QScopedPointer<QgsPolygonV2> polygon ( curvePolygon->toPolygon () );
984- return createGeosPolygon ( polygon.data () );
985+ return createGeosPolygon ( polygon.data (), precision );
985986 }
986987 else if ( geom->geometryType () == " Point" )
987988 {
988- return createGeosPoint ( geom, coordDims );
989+ return createGeosPoint ( geom, coordDims, precision );
989990 }
990991 else if ( QgsWKBTypes::isMultiType ( geom->wkbType () ) )
991992 {
@@ -1016,7 +1017,7 @@ GEOSGeometry* QgsGeos::asGeos( const QgsAbstractGeometryV2* geom )
10161017 QVector< GEOSGeometry* > geomVector ( c->numGeometries () );
10171018 for ( int i = 0 ; i < c->numGeometries (); ++i )
10181019 {
1019- geomVector[i] = asGeos ( c->geometryN ( i ) );
1020+ geomVector[i] = asGeos ( c->geometryN ( i ), precision );
10201021 }
10211022 return createGeosCollection ( geosType, geomVector );
10221023 }
@@ -1031,7 +1032,7 @@ QgsAbstractGeometryV2* QgsGeos::overlay( const QgsAbstractGeometryV2& geom, Over
10311032 return 0 ;
10321033 }
10331034
1034- GEOSGeomScopedPtr geosGeom ( asGeos ( &geom ) );
1035+ GEOSGeomScopedPtr geosGeom ( asGeos ( &geom, mPrecision ) );
10351036 if ( !geosGeom )
10361037 {
10371038 return 0 ;
@@ -1091,7 +1092,7 @@ bool QgsGeos::relation( const QgsAbstractGeometryV2& geom, Relation r, QString*
10911092 return false ;
10921093 }
10931094
1094- GEOSGeomScopedPtr geosGeom ( asGeos ( &geom ) );
1095+ GEOSGeomScopedPtr geosGeom ( asGeos ( &geom, mPrecision ) );
10951096 if ( !geosGeom )
10961097 {
10971098 return false ;
@@ -1348,7 +1349,7 @@ bool QgsGeos::isEqual( const QgsAbstractGeometryV2& geom, QString* errorMsg ) co
13481349
13491350 try
13501351 {
1351- GEOSGeomScopedPtr geosGeom ( asGeos ( &geom ) );
1352+ GEOSGeomScopedPtr geosGeom ( asGeos ( &geom, mPrecision ) );
13521353 if ( !geosGeom )
13531354 {
13541355 return false ;
@@ -1373,7 +1374,7 @@ bool QgsGeos::isEmpty( QString* errorMsg ) const
13731374 CATCH_GEOS_WITH_ERRMSG ( false );
13741375}
13751376
1376- GEOSCoordSequence* QgsGeos::createCoordinateSequence ( const QgsCurveV2* curve )
1377+ GEOSCoordSequence* QgsGeos::createCoordinateSequence ( const QgsCurveV2* curve, double precision )
13771378{
13781379 bool segmentize = false ;
13791380 const QgsLineStringV2* line = dynamic_cast <const QgsLineStringV2*>( curve );
@@ -1406,18 +1407,38 @@ GEOSCoordSequence* QgsGeos::createCoordinateSequence( const QgsCurveV2* curve )
14061407 try
14071408 {
14081409 coordSeq = GEOSCoordSeq_create_r ( geosinit.ctxt , numPoints, coordDims );
1409- for ( int i = 0 ; i < numPoints; ++i )
1410+ if ( precision > 0 . )
14101411 {
1411- QgsPointV2 pt = line->pointN ( i ); // todo: create method to get const point reference
1412- GEOSCoordSeq_setX_r ( geosinit.ctxt , coordSeq, i, pt.x () );
1413- GEOSCoordSeq_setY_r ( geosinit.ctxt , coordSeq, i, pt.y () );
1414- if ( hasZ )
1412+ for ( int i = 0 ; i < numPoints; ++i )
14151413 {
1416- GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, i, 2 , pt.z () );
1414+ QgsPointV2 pt = line->pointN ( i ); // todo: create method to get const point reference
1415+ GEOSCoordSeq_setX_r ( geosinit.ctxt , coordSeq, i, std::round ( pt.x () / precision ) * precision );
1416+ GEOSCoordSeq_setY_r ( geosinit.ctxt , coordSeq, i, std::round ( pt.y () / precision ) * precision );
1417+ if ( hasZ )
1418+ {
1419+ GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, i, 2 , std::round ( pt.z () / precision ) * precision );
1420+ }
1421+ if ( hasM )
1422+ {
1423+ GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, i, 3 , pt.m () );
1424+ }
14171425 }
1418- if ( hasM )
1426+ }
1427+ else
1428+ {
1429+ for ( int i = 0 ; i < numPoints; ++i )
14191430 {
1420- GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, i, 3 , pt.m () );
1431+ QgsPointV2 pt = line->pointN ( i ); // todo: create method to get const point reference
1432+ GEOSCoordSeq_setX_r ( geosinit.ctxt , coordSeq, i, pt.x () );
1433+ GEOSCoordSeq_setY_r ( geosinit.ctxt , coordSeq, i, pt.y () );
1434+ if ( hasZ )
1435+ {
1436+ GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, i, 2 , pt.z () );
1437+ }
1438+ if ( hasM )
1439+ {
1440+ GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, i, 3 , pt.m () );
1441+ }
14211442 }
14221443 }
14231444 }
@@ -1430,7 +1451,7 @@ GEOSCoordSequence* QgsGeos::createCoordinateSequence( const QgsCurveV2* curve )
14301451 return coordSeq;
14311452}
14321453
1433- GEOSGeometry* QgsGeos::createGeosPoint ( const QgsAbstractGeometryV2* point, int coordDims )
1454+ GEOSGeometry* QgsGeos::createGeosPoint ( const QgsAbstractGeometryV2* point, int coordDims, double precision )
14341455{
14351456 const QgsPointV2* pt = dynamic_cast <const QgsPointV2*>( point );
14361457 if ( !pt )
@@ -1441,11 +1462,23 @@ GEOSGeometry* QgsGeos::createGeosPoint( const QgsAbstractGeometryV2* point, int
14411462 try
14421463 {
14431464 GEOSCoordSequence* coordSeq = GEOSCoordSeq_create_r ( geosinit.ctxt , 1 , coordDims );
1444- GEOSCoordSeq_setX_r ( geosinit.ctxt , coordSeq, 0 , pt->x () );
1445- GEOSCoordSeq_setY_r ( geosinit.ctxt , coordSeq, 0 , pt->y () );
1446- if ( pt->is3D () )
1465+ if ( precision > 0 . )
14471466 {
1448- GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, 0 , 2 , pt->z () );
1467+ GEOSCoordSeq_setX_r ( geosinit.ctxt , coordSeq, 0 , std::round ( pt->x () / precision ) * precision );
1468+ GEOSCoordSeq_setY_r ( geosinit.ctxt , coordSeq, 0 , std::round ( pt->y () / precision ) * precision );
1469+ if ( pt->is3D () )
1470+ {
1471+ GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, 0 , 2 , std::round ( pt->z () / precision ) * precision );
1472+ }
1473+ }
1474+ else
1475+ {
1476+ GEOSCoordSeq_setX_r ( geosinit.ctxt , coordSeq, 0 , pt->x () );
1477+ GEOSCoordSeq_setY_r ( geosinit.ctxt , coordSeq, 0 , pt->y () );
1478+ if ( pt->is3D () )
1479+ {
1480+ GEOSCoordSeq_setOrdinate_r ( geosinit.ctxt , coordSeq, 0 , 2 , pt->z () );
1481+ }
14491482 }
14501483 if ( 0 /* pt->isMeasure()*/ ) // disabled until geos supports m-coordinates
14511484 {
@@ -1457,13 +1490,13 @@ GEOSGeometry* QgsGeos::createGeosPoint( const QgsAbstractGeometryV2* point, int
14571490 return geosPoint;
14581491}
14591492
1460- GEOSGeometry* QgsGeos::createGeosLinestring ( const QgsAbstractGeometryV2* curve )
1493+ GEOSGeometry* QgsGeos::createGeosLinestring ( const QgsAbstractGeometryV2* curve , double precision )
14611494{
14621495 const QgsCurveV2* c = dynamic_cast <const QgsCurveV2*>( curve );
14631496 if ( !c )
14641497 return 0 ;
14651498
1466- GEOSCoordSequence* coordSeq = createCoordinateSequence ( c );
1499+ GEOSCoordSequence* coordSeq = createCoordinateSequence ( c, precision );
14671500 if ( !coordSeq )
14681501 return 0 ;
14691502
@@ -1476,7 +1509,7 @@ GEOSGeometry* QgsGeos::createGeosLinestring( const QgsAbstractGeometryV2* curve
14761509 return geosGeom;
14771510}
14781511
1479- GEOSGeometry* QgsGeos::createGeosPolygon ( const QgsAbstractGeometryV2* poly )
1512+ GEOSGeometry* QgsGeos::createGeosPolygon ( const QgsAbstractGeometryV2* poly , double precision )
14801513{
14811514 const QgsCurvePolygonV2* polygon = dynamic_cast <const QgsCurvePolygonV2*>( poly );
14821515 if ( !polygon )
@@ -1491,7 +1524,7 @@ GEOSGeometry* QgsGeos::createGeosPolygon( const QgsAbstractGeometryV2* poly )
14911524 GEOSGeometry* geosPolygon = 0 ;
14921525 try
14931526 {
1494- GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r ( geosinit.ctxt , createCoordinateSequence ( exteriorRing ) );
1527+ GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r ( geosinit.ctxt , createCoordinateSequence ( exteriorRing, precision ) );
14951528
14961529
14971530 int nHoles = polygon->numInteriorRings ();
@@ -1504,7 +1537,7 @@ GEOSGeometry* QgsGeos::createGeosPolygon( const QgsAbstractGeometryV2* poly )
15041537 for ( int i = 0 ; i < nHoles; ++i )
15051538 {
15061539 const QgsCurveV2* interiorRing = polygon->interiorRing ( i );
1507- holes[i] = GEOSGeom_createLinearRing_r ( geosinit.ctxt , createCoordinateSequence ( interiorRing ) );
1540+ holes[i] = GEOSGeom_createLinearRing_r ( geosinit.ctxt , createCoordinateSequence ( interiorRing, precision ) );
15081541 }
15091542 geosPolygon = GEOSGeom_createPolygon_r ( geosinit.ctxt , exteriorRingGeos, holes, nHoles );
15101543 delete[] holes;
@@ -1538,7 +1571,7 @@ QgsAbstractGeometryV2* QgsGeos::reshapeGeometry( const QgsLineStringV2& reshapeW
15381571 return 0 ;
15391572 }
15401573
1541- GEOSGeometry* reshapeLineGeos = createGeosLinestring ( &reshapeWithLine );
1574+ GEOSGeometry* reshapeLineGeos = createGeosLinestring ( &reshapeWithLine, mPrecision );
15421575
15431576 // single or multi?
15441577 int numGeoms = GEOSGetNumGeometries_r ( geosinit.ctxt , mGeos );
@@ -1560,11 +1593,11 @@ QgsAbstractGeometryV2* QgsGeos::reshapeGeometry( const QgsLineStringV2& reshapeW
15601593 GEOSGeometry* reshapedGeometry;
15611594 if ( isLine )
15621595 {
1563- reshapedGeometry = reshapeLine ( mGeos , reshapeLineGeos );
1596+ reshapedGeometry = reshapeLine ( mGeos , reshapeLineGeos, mPrecision );
15641597 }
15651598 else
15661599 {
1567- reshapedGeometry = reshapePolygon ( mGeos , reshapeLineGeos );
1600+ reshapedGeometry = reshapePolygon ( mGeos , reshapeLineGeos, mPrecision );
15681601 }
15691602
15701603 if ( errorCode ) { *errorCode = 0 ; }
@@ -1585,9 +1618,9 @@ QgsAbstractGeometryV2* QgsGeos::reshapeGeometry( const QgsLineStringV2& reshapeW
15851618 for ( int i = 0 ; i < numGeoms; ++i )
15861619 {
15871620 if ( isLine )
1588- currentReshapeGeometry = reshapeLine ( GEOSGetGeometryN_r ( geosinit.ctxt , mGeos , i ), reshapeLineGeos );
1621+ currentReshapeGeometry = reshapeLine ( GEOSGetGeometryN_r ( geosinit.ctxt , mGeos , i ), reshapeLineGeos, mPrecision );
15891622 else
1590- currentReshapeGeometry = reshapePolygon ( GEOSGetGeometryN_r ( geosinit.ctxt , mGeos , i ), reshapeLineGeos );
1623+ currentReshapeGeometry = reshapePolygon ( GEOSGetGeometryN_r ( geosinit.ctxt , mGeos , i ), reshapeLineGeos, mPrecision );
15911624
15921625 if ( currentReshapeGeometry )
15931626 {
@@ -1636,7 +1669,7 @@ QgsAbstractGeometryV2* QgsGeos::reshapeGeometry( const QgsLineStringV2& reshapeW
16361669 }
16371670}
16381671
1639- GEOSGeometry* QgsGeos::reshapeLine ( const GEOSGeometry* line, const GEOSGeometry* reshapeLineGeos )
1672+ GEOSGeometry* QgsGeos::reshapeLine ( const GEOSGeometry* line, const GEOSGeometry* reshapeLineGeos , double precision )
16401673{
16411674 if ( !line || !reshapeLineGeos )
16421675 return 0 ;
@@ -1682,9 +1715,9 @@ GEOSGeometry* QgsGeos::reshapeLine( const GEOSGeometry* line, const GEOSGeometry
16821715 GEOSCoordSeq_getX_r ( geosinit.ctxt , lineCoordSeq, lineCoordSeqSize - 1 , &x2 );
16831716 GEOSCoordSeq_getY_r ( geosinit.ctxt , lineCoordSeq, lineCoordSeqSize - 1 , &y2 );
16841717 QgsPointV2 beginPoint ( x1, y1 );
1685- GEOSGeometry* beginLineVertex = createGeosPoint ( &beginPoint, 2 );
1718+ GEOSGeometry* beginLineVertex = createGeosPoint ( &beginPoint, 2 , precision );
16861719 QgsPointV2 endPoint ( x2, y2 );
1687- GEOSGeometry* endLineVertex = createGeosPoint ( &endPoint, 2 );
1720+ GEOSGeometry* endLineVertex = createGeosPoint ( &endPoint, 2 , precision );
16881721
16891722 bool isRing = false ;
16901723 if ( GEOSGeomTypeId_r ( geosinit.ctxt , line ) == GEOS_LINEARRING
@@ -1742,9 +1775,9 @@ GEOSGeometry* QgsGeos::reshapeLine( const GEOSGeometry* line, const GEOSGeometry
17421775 GEOSCoordSeq_getX_r ( geosinit.ctxt , currentCoordSeq, currentCoordSeqSize - 1 , &xEnd );
17431776 GEOSCoordSeq_getY_r ( geosinit.ctxt , currentCoordSeq, currentCoordSeqSize - 1 , &yEnd );
17441777 QgsPointV2 beginPoint ( xBegin, yBegin );
1745- GEOSGeometry* beginCurrentGeomVertex = createGeosPoint ( &beginPoint, 2 );
1778+ GEOSGeometry* beginCurrentGeomVertex = createGeosPoint ( &beginPoint, 2 , precision );
17461779 QgsPointV2 endPoint ( xEnd, yEnd );
1747- GEOSGeometry* endCurrentGeomVertex = createGeosPoint ( &endPoint, 2 );
1780+ GEOSGeometry* endCurrentGeomVertex = createGeosPoint ( &endPoint, 2 , precision );
17481781
17491782 // check how many endpoints of the line merge result are on the (original) line
17501783 int nEndpointsOnOriginalLine = 0 ;
@@ -1864,7 +1897,7 @@ GEOSGeometry* QgsGeos::reshapeLine( const GEOSGeometry* line, const GEOSGeometry
18641897 return result;
18651898}
18661899
1867- GEOSGeometry* QgsGeos::reshapePolygon ( const GEOSGeometry* polygon, const GEOSGeometry* reshapeLineGeos )
1900+ GEOSGeometry* QgsGeos::reshapePolygon ( const GEOSGeometry* polygon, const GEOSGeometry* reshapeLineGeos, double precision )
18681901{
18691902 // go through outer shell and all inner rings and check if there is exactly one intersection of a ring and the reshape line
18701903 int nIntersections = 0 ;
@@ -1913,7 +1946,7 @@ GEOSGeometry* QgsGeos::reshapePolygon( const GEOSGeometry* polygon, const GEOSGe
19131946 }
19141947
19151948 // we have one intersecting ring, let's try to reshape it
1916- GEOSGeometry* reshapeResult = reshapeLine ( lastIntersectingGeom, reshapeLineGeos );
1949+ GEOSGeometry* reshapeResult = reshapeLine ( lastIntersectingGeom, reshapeLineGeos, precision );
19171950 if ( !reshapeResult )
19181951 {
19191952 delete [] innerRings;
0 commit comments