38 #include <netinet/in.h>
43 #define DEFAULT_QUADRANT_SEGMENTS 8
45 #define CATCH_GEOS(r) \
46 catch (GEOSException &e) \
48 QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr("GEOS") ); \
57 if ( theMsg ==
"Unknown exception thrown" && lastMsg.isNull() )
77 lastMsg = QString::null;
87 static QString lastMsg;
90 QString GEOSException::lastMsg;
98 vsnprintf( buffer,
sizeof buffer, fmt, ap );
101 qWarning() << QString(
"GEOS exception: %1" ).arg( buffer );
108 #if defined(QGISDEBUG)
113 vsnprintf( buffer,
sizeof buffer, fmt, ap );
116 QgsDebugMsg( QString(
"GEOS notice: %1" ).arg( QString::fromUtf8( buffer ) ) );
134 finishGEOS_r(
ctxt );
142 return geosinit.
ctxt;
150 , mDirtyGeos( false )
156 , mGeometrySize( rhs.mGeometrySize )
157 , mDirtyWkb( rhs.mDirtyWkb )
158 , mDirtyGeos( rhs.mDirtyGeos )
160 if ( mGeometrySize && rhs.mGeometry )
162 mGeometry =
new unsigned char[mGeometrySize];
163 memcpy( mGeometry, rhs.mGeometry, mGeometrySize );
168 mGeos = GEOSGeom_clone_r( geosinit.
ctxt, rhs.mGeos );
181 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
188 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, geom );
189 GEOSCoordSeq_getSize_r( geosinit.
ctxt, cs, &n );
195 GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosinit.
ctxt, 1, 2 );
196 GEOSCoordSeq_setX_r( geosinit.
ctxt, coord, 0, x );
197 GEOSCoordSeq_setY_r( geosinit.
ctxt, coord, 0, y );
198 return GEOSGeom_createPoint_r( geosinit.
ctxt, coord );
208 GEOSCoordSequence *coord = 0;
212 coord = GEOSCoordSeq_create_r( geosinit.
ctxt, points.count(), 2 );
214 for ( i = 0; i < points.count(); i++ )
216 GEOSCoordSeq_setX_r( geosinit.
ctxt, coord, i, points[i].x() );
217 GEOSCoordSeq_setY_r( geosinit.
ctxt, coord, i, points[i].y() );
232 GEOSGeometry **geomarr =
new GEOSGeometry*[ geoms.size()];
236 for (
int i = 0; i < geoms.size(); i++ )
237 geomarr[i] = geoms[i];
239 GEOSGeometry *geom = 0;
243 geom = GEOSGeom_createCollection_r( geosinit.
ctxt, typeId, geomarr, geoms.size() );
257 GEOSCoordSequence *coord = 0;
262 return GEOSGeom_createLineString_r( geosinit.
ctxt, coord );
276 GEOSCoordSequence *coord = 0;
278 if ( polyline.count() <= 2 )
283 if ( polyline[0] != polyline[polyline.size()-1] )
294 if ( polyline.count() == 3 )
300 return GEOSGeom_createLinearRing_r( geosinit.
ctxt, coord );
316 if ( rings.size() == 0 )
318 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
319 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
320 return GEOSGeom_createEmptyPolygon_r( geosinit.
ctxt );
322 shell = GEOSGeom_createLinearRing_r( geosinit.
ctxt, GEOSCoordSeq_create_r( geosinit.
ctxt, 0, 2 ) );
330 GEOSGeometry **holes = NULL;
333 if ( rings.size() > 1 )
335 nHoles = rings.size() - 1;
336 holes =
new GEOSGeometry*[ nHoles ];
340 for (
int i = 0; i < nHoles; i++ )
341 holes[i] = rings[i+1];
344 GEOSGeometry *geom = GEOSGeom_createPolygon_r( geosinit.
ctxt, shell, holes, nHoles );
359 if ( polygon.count() == 0 )
362 QVector<GEOSGeometry *> geoms;
366 for (
int i = 0; i < polygon.count(); i++ )
372 for (
int j = 0; j < geoms.count(); j++ )
373 GEOSGeom_destroy_r( geosinit.
ctxt, geoms[j] );
386 for (
int i = 0; i < geoms.count(); i++ )
387 GEOSGeom_destroy_r( geosinit.
ctxt, geoms[i] );
406 GEOSWKTReader *reader = GEOSWKTReader_create_r( geosinit.
ctxt );
408 GEOSWKTReader_destroy_r( geosinit.
ctxt, reader );
435 QVector<GEOSGeometry *> geoms;
439 for (
int i = 0; i < multipoint.size(); ++i )
448 for (
int i = 0; i < geoms.size(); ++i )
449 GEOSGeom_destroy_r( geosinit.
ctxt, geoms[i] );
457 QVector<GEOSGeometry *> geoms;
461 for (
int i = 0; i < multiline.count(); i++ )
470 for (
int i = 0; i < geoms.count(); i++ )
471 GEOSGeom_destroy_r( geosinit.
ctxt, geoms[i] );
479 if ( multipoly.count() == 0 )
482 QVector<GEOSGeometry *> geoms;
486 for (
int i = 0; i < multipoly.count(); i++ )
495 for (
int i = 0; i < geoms.count(); i++ )
496 GEOSGeom_destroy_r( geosinit.
ctxt, geoms[i] );
512 polygon.append( ring );
524 if ( polygon.isClosed() )
534 QgsPolygon QgsGeometry::createPolygonFromQPolygonF(
const QPolygonF &polygon )
537 result << createPolylineFromQPolygonF( polygon );
541 QgsPolyline QgsGeometry::createPolylineFromQPolygonF(
const QPolygonF &polygon )
544 QPolygonF::const_iterator it = polygon.constBegin();
545 for ( ; it != polygon.constEnd(); ++it )
564 mGeometrySize = rhs.mGeometrySize;
567 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
568 mGeos = rhs.mGeos ? GEOSGeom_clone_r( geosinit.
ctxt, rhs.mGeos ) : 0;
570 mDirtyGeos = rhs.mDirtyGeos;
571 mDirtyWkb = rhs.mDirtyWkb;
573 if ( mGeometrySize && rhs.mGeometry )
575 mGeometry =
new unsigned char[mGeometrySize];
576 memcpy( mGeometry, rhs.mGeometry, mGeometrySize );
594 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
618 return mGeometrySize;
625 if ( !exportWkbToGeos() )
639 if ( mGeometry &&
wkbSize() >= 5 )
696 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
734 bool hasZValue =
false;
746 actdist = point.
sqrDist( x, y );
763 wkbPtr +=
sizeof( double );
765 double dist = point.
sqrDist( x, y );
766 if ( dist < actdist )
772 beforeVertex =
index - 1;
773 afterVertex =
index == nPoints - 1 ? -1 :
index + 1;
790 for (
int index2 = 0; index2 < nPoints; ++index2 )
795 wkbPtr +=
sizeof( double );
797 double dist = point.
sqrDist( x, y );
798 if ( dist < actdist )
802 vertexnr = pointIndex;
807 beforeVertex = pointIndex + ( nPoints - 2 );
808 afterVertex = pointIndex + 1;
810 else if ( index2 == nPoints - 1 )
812 beforeVertex = pointIndex - 1;
813 afterVertex = pointIndex - ( nPoints - 2 );
817 beforeVertex = pointIndex - 1;
818 afterVertex = pointIndex + 1;
836 wkbPtr += 1 +
sizeof( int );
841 wkbPtr +=
sizeof( double );
843 double dist = point.
sqrDist( x, y );
844 if ( dist < actdist )
863 wkbPtr += 1 +
sizeof( int );
867 for (
int index2 = 0; index2 < nPoints; ++index2 )
872 wkbPtr +=
sizeof( double );
874 double dist = point.
sqrDist( x, y );
875 if ( dist < actdist )
879 vertexnr = pointIndex;
884 beforeVertex = vertexnr - 1;
886 if ( index2 == nPoints - 1 )
889 afterVertex = vertexnr + 1;
907 wkbPtr += 1 +
sizeof( int );
910 for (
int index2 = 0; index2 < nRings; ++index2 )
914 for (
int index3 = 0; index3 < nPoints; ++index3 )
919 wkbPtr +=
sizeof( double );
921 double dist = point.
sqrDist( x, y );
922 if ( dist < actdist )
926 vertexnr = pointIndex;
931 beforeVertex = pointIndex + ( nPoints - 2 );
932 afterVertex = pointIndex + 1;
934 else if ( index3 == nPoints - 1 )
936 beforeVertex = pointIndex - 1;
937 afterVertex = pointIndex - ( nPoints - 2 );
941 beforeVertex = pointIndex - 1;
942 afterVertex = pointIndex + 1;
980 bool hasZValue =
false;
998 if ( atVertex >= nPoints )
1001 const int index = atVertex;
1005 beforeVertex = index - 1;
1007 if ( index == nPoints - 1 )
1010 afterVertex = index + 1;
1023 for (
int index0 = 0, pointIndex = 0; index0 < nRings; ++index0 )
1027 for (
int index1 = 0; index1 < nPoints; ++index1 )
1029 wkbPtr += ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1031 if ( pointIndex == atVertex )
1035 beforeVertex = pointIndex + ( nPoints - 2 );
1036 afterVertex = pointIndex + 1;
1038 else if ( index1 == nPoints - 1 )
1040 beforeVertex = pointIndex - 1;
1041 afterVertex = pointIndex - ( nPoints - 2 );
1045 beforeVertex = pointIndex - 1;
1046 afterVertex = pointIndex + 1;
1070 for (
int index0 = 0, pointIndex = 0; index0 < nLines; ++index0 )
1072 wkbPtr += 1 +
sizeof( int );
1077 for (
int index1 = 0; index1 < nPoints; ++index1 )
1079 wkbPtr += ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1081 if ( pointIndex == atVertex )
1087 beforeVertex = pointIndex - 1;
1089 if ( index1 == nPoints - 1 )
1092 afterVertex = pointIndex + 1;
1109 for (
int index0 = 0, pointIndex = 0; index0 < nPolys; ++index0 )
1111 wkbPtr += 1 +
sizeof( int );
1115 for (
int index1 = 0; index1 < nRings; ++index1 )
1119 for (
int index2 = 0; index2 < nPoints; ++index2 )
1121 wkbPtr += ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1123 if ( pointIndex == atVertex )
1130 beforeVertex = pointIndex + ( nPoints - 2 );
1131 afterVertex = pointIndex + 1;
1133 else if ( index2 == nPoints - 1 )
1135 beforeVertex = pointIndex - 1;
1136 afterVertex = pointIndex - ( nPoints - 2 );
1140 beforeVertex = pointIndex - 1;
1141 afterVertex = pointIndex + 1;
1159 const GEOSCoordSequence *old_sequence,
1160 GEOSCoordSequence **new_sequence )
1163 if ( beforeVertex < 0 )
1169 unsigned int numPoints;
1170 GEOSCoordSeq_getSize_r( geosinit.
ctxt, old_sequence, &numPoints );
1172 *new_sequence = GEOSCoordSeq_create_r( geosinit.
ctxt, numPoints + 1, 2 );
1173 if ( !*new_sequence )
1176 bool inserted =
false;
1177 for (
unsigned int i = 0, j = 0; i < numPoints; i++, j++ )
1180 if ( beforeVertex == static_cast<int>( i ) )
1182 GEOSCoordSeq_setX_r( geosinit.
ctxt, *new_sequence, j, x );
1183 GEOSCoordSeq_setY_r( geosinit.
ctxt, *new_sequence, j, y );
1189 GEOSCoordSeq_getX_r( geosinit.
ctxt, old_sequence, i, &aX );
1190 GEOSCoordSeq_getY_r( geosinit.
ctxt, old_sequence, i, &aY );
1192 GEOSCoordSeq_setX_r( geosinit.
ctxt, *new_sequence, j, aX );
1193 GEOSCoordSeq_setY_r( geosinit.
ctxt, *new_sequence, j, aY );
1200 GEOSCoordSeq_setX_r( geosinit.
ctxt, *new_sequence, numPoints, x );
1201 GEOSCoordSeq_setY_r( geosinit.
ctxt, *new_sequence, numPoints, y );
1214 const int ps = ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1217 if ( atVertex >= pointIndex + nPoints )
1219 wkbPtr += ps * nPoints;
1220 pointIndex += nPoints;
1224 if ( isRing && atVertex == pointIndex + nPoints - 1 )
1225 atVertex = pointIndex;
1228 wkbPtr += ps * ( atVertex - pointIndex );
1233 if ( isRing && atVertex == pointIndex )
1235 wkbPtr += ps * ( nPoints - 2 );
1259 bool hasZValue =
false;
1270 if ( atVertex != 0 )
1284 if (
moveVertex( wkbPtr, x, y, atVertex, hasZValue, pointIndex,
false ) )
1301 if ( atVertex < nPoints )
1303 wkbPtr += atVertex * ( 1 +
sizeof( int ) + ( hasZValue ? 3 : 2 ) *
sizeof( double ) ) + 1 +
sizeof( int );
1324 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
1326 wkbPtr += 1 +
sizeof( int );
1327 if (
moveVertex( wkbPtr, x, y, atVertex, hasZValue, pointIndex,
false ) )
1345 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
1347 if (
moveVertex( wkbPtr, x, y, atVertex, hasZValue, pointIndex,
true ) )
1362 wkbPtr >> nPolygons;
1363 for (
int polynr = 0, pointIndex = 0; polynr < nPolygons; ++polynr )
1365 wkbPtr += 1 +
sizeof( int );
1370 for (
int ringnr = 0; ringnr < nRings; ++ringnr )
1372 if (
moveVertex( wkbPtr, x, y, atVertex, hasZValue, pointIndex,
true ) )
1401 QgsDebugMsg( QString(
"atVertex:%1 hasZValue:%2 pointIndex:%3 isRing:%4" ).arg( atVertex ).arg( hasZValue ).arg( pointIndex ).arg( isRing ) );
1402 const int ps = ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1407 if ( atVertex < pointIndex || atVertex >= pointIndex + nPoints )
1410 if ( lastItem && atVertex >= pointIndex + nPoints )
1415 int len = nPoints * ps;
1416 memcpy( dstPtr, srcPtr, len );
1419 pointIndex += nPoints;
1424 if ( isRing && atVertex == pointIndex + nPoints - 1 )
1425 atVertex = pointIndex;
1427 if ( nPoints == ( isRing ? 2 : 1 ) )
1431 srcPtr += nPoints * ps;
1432 pointIndex += nPoints;
1436 dstPtr << nPoints - 1;
1439 int len = ( atVertex - pointIndex ) * ps;
1442 memcpy( dstPtr, srcPtr, len );
1451 len = ( pointIndex + nPoints - atVertex - 1 ) * ps;
1454 const unsigned char *first = 0;
1455 if ( isRing && atVertex == pointIndex )
1463 memcpy( dstPtr, srcPtr, len );
1471 memcpy( dstPtr, first, ps );
1476 pointIndex += nPoints;
1483 QgsDebugMsg( QString(
"atVertex:%1" ).arg( atVertex ) );
1499 srcPtr >> endianness >>
wkbType;
1503 int ps = ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1505 ps += 1 +
sizeof(
int );
1507 unsigned char *dstBuffer =
new unsigned char[mGeometrySize - ps];
1509 dstPtr << endianness <<
wkbType;
1511 bool deleted =
false;
1522 int res =
deleteVertex( srcPtr, dstPtr, atVertex, hasZValue, pointIndex,
false,
true );
1541 for (
int ringnr = 0, pointIndex = 0; ringnr < nRings; ++ringnr )
1543 int res =
deleteVertex( srcPtr, dstPtr, atVertex, hasZValue, pointIndex,
true, ringnr == nRings - 1 );
1547 deleted |= res != 0;
1559 if ( atVertex < nPoints )
1561 dstPtr << nPoints - 1;
1563 int len = ps * atVertex;
1566 memcpy( dstPtr, srcPtr, len );
1573 len = ps * ( nPoints - atVertex - 1 );
1576 memcpy( dstPtr, srcPtr, len );
1595 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
1598 srcPtr >> endianness >>
wkbType;
1599 dstPtr << endianness <<
wkbType;
1601 int res =
deleteVertex( srcPtr, dstPtr, atVertex, hasZValue, pointIndex,
false, linenr == nLines - 1 );
1606 dstPtr = saveDstPtr;
1609 deleted |= res != 0;
1623 for (
int polynr = 0, pointIndex = 0; polynr < nPolys; ++polynr )
1626 srcPtr >> endianness >> wkbType >> nRings;
1628 dstPtr << endianness <<
wkbType;
1632 for (
int ringnr = 0; ringnr < nRings; ++ringnr )
1634 int res =
deleteVertex( srcPtr, dstPtr, atVertex, hasZValue, pointIndex,
true, polynr == nPolys - 1 && ringnr == nRings - 1 );
1641 ptrNPolys << nPolys - 1;
1642 dstPtr = saveDstPolyPtr;
1646 ptrNRings << nRings - 1;
1650 deleted |= res != 0;
1663 delete [] mGeometry;
1664 mGeometry = dstBuffer;
1665 mGeometrySize -= ps;
1671 delete [] dstBuffer;
1681 bool insertHere = beforeVertex >= pointIndex && beforeVertex < pointIndex + nPoints;
1686 dstPtr << nPoints + 1;
1687 len = ( hasZValue ? 3 : 2 ) * ( beforeVertex - pointIndex ) *
sizeof( double );
1690 memcpy( dstPtr, srcPtr, len );
1699 len = ( hasZValue ? 3 : 2 ) * ( pointIndex + nPoints - beforeVertex ) *
sizeof( double );
1700 if ( isRing && beforeVertex == pointIndex )
1701 len -= ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1706 len = ( hasZValue ? 3 : 2 ) * nPoints *
sizeof(
double );
1709 memcpy( dstPtr, srcPtr, len );
1713 if ( isRing && beforeVertex == pointIndex )
1720 pointIndex += nPoints;
1736 if ( beforeVertex < 0 )
1742 srcPtr >> endianness >>
wkbType;
1746 int ps = ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1748 ps += 1 +
sizeof(
int );
1750 unsigned char *dstBuffer =
new unsigned char[mGeometrySize + ps];
1752 dstPtr << endianness <<
wkbType;
1754 bool inserted =
false;
1765 inserted =
insertVertex( srcPtr, dstPtr, beforeVertex, x, y, hasZValue, pointIndex,
false );
1776 for (
int ringnr = 0, pointIndex = 0; ringnr < nRings; ++ringnr )
1777 inserted |=
insertVertex( srcPtr, dstPtr, beforeVertex, x, y, hasZValue, pointIndex,
true );
1788 if ( beforeVertex <= nPoints )
1790 dstPtr << nPoints + 1;
1792 int len = ps * beforeVertex;
1795 memcpy( dstPtr, srcPtr, len );
1804 len = ps * ( nPoints - beforeVertex );
1806 memcpy( dstPtr, srcPtr, len );
1821 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
1823 srcPtr >> endianness >>
wkbType;
1824 dstPtr << endianness <<
wkbType;
1825 inserted |=
insertVertex( srcPtr, dstPtr, beforeVertex, x, y, hasZValue, pointIndex,
false );
1837 for (
int polynr = 0, pointIndex = 0; polynr < nPolys; ++polynr )
1840 srcPtr >> endianness >> wkbType >> nRings;
1841 dstPtr << endianness << wkbType << nRings;
1843 for (
int ringnr = 0; ringnr < nRings; ++ringnr )
1844 inserted |=
insertVertex( srcPtr, dstPtr, beforeVertex, x, y, hasZValue, pointIndex,
true );
1856 delete [] mGeometry;
1857 mGeometry = dstBuffer;
1858 mGeometrySize += ps;
1864 delete [] dstBuffer;
1887 bool hasZValue =
false;
1893 if ( atVertex != 0 )
1911 if ( atVertex >= nPoints )
1915 wkbPtr += atVertex * ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1931 for (
int ringnr = 0, pointIndex = 0; ringnr < nRings; ++ringnr )
1936 if ( atVertex >= pointIndex + nPoints )
1938 wkbPtr += nPoints * ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1939 pointIndex += nPoints;
1943 wkbPtr += ( atVertex - pointIndex ) * ( hasZValue ? 3 : 2 ) *
sizeof( double );
1962 if ( atVertex >= nPoints )
1965 wkbPtr += atVertex * ( 1 +
sizeof( int ) + ( hasZValue ? 3 : 2 ) *
sizeof( double ) ) + 1 +
sizeof( int );
1980 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
1982 wkbPtr += 1 +
sizeof( int );
1986 if ( atVertex >= pointIndex + nPoints )
1988 wkbPtr += nPoints * ( hasZValue ? 3 : 2 ) *
sizeof(
double );
1989 pointIndex += nPoints;
1993 wkbPtr += ( atVertex - pointIndex ) * ( hasZValue ? 3 : 2 ) *
sizeof( double );
2010 wkbPtr >> nPolygons;
2012 for (
int polynr = 0, pointIndex = 0; polynr < nPolygons; ++polynr )
2014 wkbPtr += 1 +
sizeof( int );
2018 for (
int ringnr = 0; ringnr < nRings; ++ringnr )
2023 if ( atVertex >= pointIndex + nPoints )
2025 wkbPtr += nPoints * ( hasZValue ? 3 : 2 ) *
sizeof(
double );
2026 pointIndex += nPoints;
2030 wkbPtr += ( atVertex - pointIndex ) * ( hasZValue ? 3 : 2 ) *
sizeof( double );
2042 QgsDebugMsg(
"error: mGeometry type not recognized" );
2057 QgsDebugMsg(
"Exiting with std::numeric_limits<double>::max()." );
2070 int closestVertexIndex = 0;
2079 const GEOSGeometry *g = GEOSGetExteriorRing_r( geosinit.
ctxt, mGeos );
2083 const GEOSCoordSequence *sequence = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, g );
2086 GEOSCoordSeq_getSize_r( geosinit.
ctxt, sequence, &n );
2088 for (
unsigned int i = 0; i < n; i++ )
2091 GEOSCoordSeq_getX_r( geosinit.
ctxt, sequence, i, &x );
2092 GEOSCoordSeq_getY_r( geosinit.
ctxt, sequence, i, &y );
2094 double testDist = point.
sqrDist( x, y );
2095 if ( testDist < sqrDist )
2097 closestVertexIndex = i;
2102 atVertex = closestVertexIndex;
2140 int closestSegmentIndex = 0;
2141 bool hasZValue =
false;
2161 double prevx = 0.0, prevy = 0.0;
2164 double thisx, thisy;
2165 wkbPtr >> thisx >> thisy;
2167 wkbPtr +=
sizeof( double );
2171 double testdist = point.
sqrDistToSegment( prevx, prevy, thisx, thisy, distPoint, epsilon );
2172 if ( testdist < sqrDist )
2174 closestSegmentIndex =
index;
2176 minDistPoint = distPoint;
2179 *leftOf = QgsGeometry::leftOf( point.
x(), point.
y(), prevx, prevy, thisx, thisy );
2187 afterVertex = closestSegmentIndex;
2198 for (
int linenr = 0, pointIndex = 0; linenr < nLines; ++linenr )
2200 wkbPtr += 1 +
sizeof( int );
2204 double prevx = 0.0, prevy = 0.0;
2205 for (
int pointnr = 0; pointnr < nPoints; ++pointnr )
2207 double thisx, thisy;
2208 wkbPtr >> thisx >> thisy;
2210 wkbPtr +=
sizeof( double );
2214 double testdist = point.
sqrDistToSegment( prevx, prevy, thisx, thisy, distPoint, epsilon );
2215 if ( testdist < sqrDist )
2217 closestSegmentIndex = pointIndex;
2219 minDistPoint = distPoint;
2222 *leftOf = QgsGeometry::leftOf( point.
x(), point.
y(), prevx, prevy, thisx, thisy );
2232 afterVertex = closestSegmentIndex;
2244 for (
int ringnr = 0, pointIndex = 0; ringnr < nRings; ++ringnr )
2249 double prevx = 0.0, prevy = 0.0;
2250 for (
int pointnr = 0; pointnr < nPoints; ++pointnr )
2252 double thisx, thisy;
2253 wkbPtr >> thisx >> thisy;
2255 wkbPtr +=
sizeof( double );
2259 double testdist = point.
sqrDistToSegment( prevx, prevy, thisx, thisy, distPoint, epsilon );
2260 if ( testdist < sqrDist )
2262 closestSegmentIndex = pointIndex;
2264 minDistPoint = distPoint;
2267 *leftOf = QgsGeometry::leftOf( point.
x(), point.
y(), prevx, prevy, thisx, thisy );
2277 afterVertex = closestSegmentIndex;
2287 wkbPtr >> nPolygons;
2288 for (
int polynr = 0, pointIndex = 0; polynr < nPolygons; ++polynr )
2290 wkbPtr += 1 +
sizeof( int );
2293 for (
int ringnr = 0; ringnr < nRings; ++ringnr )
2298 double prevx = 0.0, prevy = 0.0;
2299 for (
int pointnr = 0; pointnr < nPoints; ++pointnr )
2301 double thisx, thisy;
2302 wkbPtr >> thisx >> thisy;
2304 wkbPtr +=
sizeof( double );
2308 double testdist = point.
sqrDistToSegment( prevx, prevy, thisx, thisy, distPoint, epsilon );
2309 if ( testdist < sqrDist )
2311 closestSegmentIndex = pointIndex;
2313 minDistPoint = distPoint;
2316 *leftOf = QgsGeometry::leftOf( point.
x(), point.
y(), prevx, prevy, thisx, thisy );
2327 afterVertex = closestSegmentIndex;
2338 .arg( point.
toString() ).arg( sqrDist ), 3 );
2350 if ( ring.size() < 4 )
2354 if ( ring.first() != ring.last() )
2368 int type = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
2371 QVector<const GEOSGeometry*> polygonList;
2375 if ( type != GEOS_POLYGON )
2378 polygonList << mGeos;
2382 if ( type != GEOS_MULTIPOLYGON )
2385 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); ++i )
2386 polygonList << GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i );
2390 GEOSGeometry *newRing = 0;
2391 GEOSGeometry *newRingPolygon = 0;
2396 if ( !GEOSisValid_r( geosinit.
ctxt, newRing ) )
2402 if ( !GEOSisValid_r( geosinit.
ctxt, newRingPolygon ) )
2411 if ( newRingPolygon )
2412 GEOSGeom_destroy_r( geosinit.
ctxt, newRingPolygon );
2414 GEOSGeom_destroy_r( geosinit.
ctxt, newRing );
2419 QVector<GEOSGeometry*> rings;
2422 for ( i = 0; i < polygonList.size(); i++ )
2424 for (
int j = 0; j < rings.size(); j++ )
2425 GEOSGeom_destroy_r( geosinit.
ctxt, rings[j] );
2428 GEOSGeometry *shellRing = 0;
2429 GEOSGeometry *shell = 0;
2432 shellRing = GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetExteriorRing_r( geosinit.
ctxt, polygonList[i] ) );
2435 if ( !GEOSWithin_r( geosinit.
ctxt, newRingPolygon, shell ) )
2437 GEOSGeom_destroy_r( geosinit.
ctxt, shell );
2446 GEOSGeom_destroy_r( geosinit.
ctxt, shell );
2447 else if ( shellRing )
2448 GEOSGeom_destroy_r( geosinit.
ctxt, shellRing );
2450 GEOSGeom_destroy_r( geosinit.
ctxt, newRingPolygon );
2456 rings << GEOSGeom_clone_r( geosinit.
ctxt, shellRing );
2458 GEOSGeom_destroy_r( geosinit.
ctxt, shell );
2461 int n = GEOSGetNumInteriorRings_r( geosinit.
ctxt, polygonList[i] );
2464 for ( j = 0; j < n; j++ )
2466 GEOSGeometry *holeRing = 0;
2467 GEOSGeometry *hole = 0;
2470 holeRing = GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetInteriorRingN_r( geosinit.
ctxt, polygonList[i], j ) );
2473 if ( !GEOSDisjoint_r( geosinit.
ctxt, hole, newRingPolygon ) )
2475 GEOSGeom_destroy_r( geosinit.
ctxt, hole );
2484 GEOSGeom_destroy_r( geosinit.
ctxt, hole );
2485 else if ( holeRing )
2486 GEOSGeom_destroy_r( geosinit.
ctxt, holeRing );
2491 rings << GEOSGeom_clone_r( geosinit.
ctxt, holeRing );
2492 GEOSGeom_destroy_r( geosinit.
ctxt, hole );
2500 if ( i == polygonList.size() )
2503 for (
int j = 0; j < rings.size(); j++ )
2504 GEOSGeom_destroy_r( geosinit.
ctxt, rings[j] );
2507 GEOSGeom_destroy_r( geosinit.
ctxt, newRingPolygon );
2513 rings << GEOSGeom_clone_r( geosinit.
ctxt, newRing );
2514 GEOSGeom_destroy_r( geosinit.
ctxt, newRingPolygon );
2520 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
2525 QVector<GEOSGeometry*> newPolygons;
2527 for (
int j = 0; j < polygonList.size(); j++ )
2529 newPolygons << ( i == j ? newPolygon : GEOSGeom_clone_r( geosinit.
ctxt, polygonList[j] ) );
2532 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
2552 if ( points.size() != 1 )
2554 QgsDebugMsg(
"expected 1 point: " + QString::number( points.size() ) );
2561 if ( points.size() < 2 )
2563 QgsDebugMsg(
"line must at least have two points: " + QString::number( points.size() ) );
2570 if ( points.size() < 4 )
2572 QgsDebugMsg(
"polygon must at least have three distinct points and must be closed: " + QString::number( points.size() ) );
2577 if ( points.first() != points.last() )
2585 QgsDebugMsg(
"unsupported geometry type: " + QString::number( geomType ) );
2589 GEOSGeometry *newPart = 0;
2604 GEOSGeometry *newRing = 0;
2609 if ( !GEOSisValid_r( geosinit.
ctxt, newRing ) )
2619 GEOSGeom_destroy_r( geosinit.
ctxt, newRing );
2644 const GEOSGeometry * geosPart = newPart->
asGeos();
2645 return addPart( GEOSGeom_clone_r( geosinit.
ctxt, geosPart ) );
2670 int geosType = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
2672 Q_ASSERT( newPart );
2676 if ( !GEOSisValid_r( geosinit.
ctxt, newPart ) )
2684 GEOSGeom_destroy_r( geosinit.
ctxt, newPart );
2690 QVector<GEOSGeometry*> parts;
2693 int n = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
2695 for ( i = 0; i < n; ++i )
2697 const GEOSGeometry *partN = GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i );
2699 if ( geomType ==
QGis::Polygon && GEOSOverlaps_r( geosinit.
ctxt, partN, newPart ) )
2703 parts << GEOSGeom_clone_r( geosinit.
ctxt, partN );
2709 for (
int i = 0; i < parts.size(); i++ )
2710 GEOSGeom_destroy_r( geosinit.
ctxt, parts[i] );
2716 int nPartGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, newPart );
2717 for (
int i = 0; i < nPartGeoms; ++i )
2719 parts << GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, newPart, i ) );
2721 GEOSGeom_destroy_r( geosinit.
ctxt, newPart );
2723 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
2744 bool hasZValue =
false;
2754 transformVertex( wkbPtr, t, hasZValue );
2766 transformVertex( wkbPtr, t, hasZValue );
2782 for (
int index2 = 0; index2 < nPoints; ++index2 )
2783 transformVertex( wkbPtr, t, hasZValue );
2798 wkbPtr += 1 +
sizeof( int );
2799 transformVertex( wkbPtr, t, hasZValue );
2813 wkbPtr += 1 +
sizeof( int );
2816 for (
int index2 = 0; index2 < nPoints; ++index2 )
2817 transformVertex( wkbPtr, t, hasZValue );
2832 wkbPtr += 1 +
sizeof( int );
2835 for (
int index2 = 0; index2 < nRings; ++index2 )
2839 for (
int index3 = 0; index3 < nPoints; ++index3 )
2840 transformVertex( wkbPtr, t, hasZValue );
2855 return transform( QTransform::fromTranslate( dx, dy ) );
2860 QTransform t = QTransform::fromTranslate( center.
x(), center.
y() );
2861 t.rotate( -rotation );
2862 t.translate( -center.
x(), -center.
y() );
2877 bool hasZValue =
false;
2887 transformVertex( wkbPtr, ct, hasZValue );
2899 transformVertex( wkbPtr, ct, hasZValue );
2915 for (
int index2 = 0; index2 < nPoints; ++index2 )
2916 transformVertex( wkbPtr, ct, hasZValue );
2931 wkbPtr += 1 +
sizeof( int );
2932 transformVertex( wkbPtr, ct, hasZValue );
2946 wkbPtr += 1 +
sizeof( int );
2949 for (
int index2 = 0; index2 < nPoints; ++index2 )
2950 transformVertex( wkbPtr, ct, hasZValue );
2965 wkbPtr += 1 +
sizeof( int );
2968 for (
int index2 = 0; index2 < nRings; ++index2 )
2972 for (
int index3 = 0; index3 < nPoints; ++index3 )
2973 transformVertex( wkbPtr, ct, hasZValue );
2986 int QgsGeometry::splitGeometry(
const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries,
bool topological, QList<QgsPoint> &topologyTestPoints )
3006 if ( !GEOSisValid_r( geosinit.
ctxt, mGeos ) )
3014 newGeometries.clear();
3018 GEOSGeometry* splitLineGeos;
3019 if ( splitLine.size() > 1 )
3023 else if ( splitLine.size() == 1 )
3031 if ( !GEOSisValid_r( geosinit.
ctxt, splitLineGeos ) || !GEOSisSimple_r( geosinit.
ctxt, splitLineGeos ) )
3033 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineGeos );
3040 if ( topologicalTestPointsSplit( splitLineGeos, topologyTestPoints ) != 0 )
3047 returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
3048 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineGeos );
3052 returnCode = splitPolygonGeometry( splitLineGeos, newGeometries );
3053 GEOSGeom_destroy_r( geosinit.
ctxt, splitLineGeos );
3068 if ( reshapeWithLine.size() < 2 )
3084 int numGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
3085 if ( numGeoms == -1 )
3088 bool isMultiGeom =
false;
3089 int geosTypeId = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
3090 if ( geosTypeId == GEOS_MULTILINESTRING || geosTypeId == GEOS_MULTIPOLYGON )
3098 GEOSGeometry* reshapedGeometry;
3100 reshapedGeometry = reshapeLine( mGeos, reshapeLineGeos );
3102 reshapedGeometry = reshapePolygon( mGeos, reshapeLineGeos );
3104 GEOSGeom_destroy_r( geosinit.
ctxt, reshapeLineGeos );
3105 if ( reshapedGeometry )
3107 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
3108 mGeos = reshapedGeometry;
3120 bool reshapeTookPlace =
false;
3122 GEOSGeometry* currentReshapeGeometry = 0;
3123 GEOSGeometry** newGeoms =
new GEOSGeometry*[numGeoms];
3125 for (
int i = 0; i < numGeoms; ++i )
3128 currentReshapeGeometry = reshapeLine( GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ), reshapeLineGeos );
3130 currentReshapeGeometry = reshapePolygon( GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ), reshapeLineGeos );
3132 if ( currentReshapeGeometry )
3134 newGeoms[i] = currentReshapeGeometry;
3135 reshapeTookPlace =
true;
3139 newGeoms[i] = GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ) );
3142 GEOSGeom_destroy_r( geosinit.
ctxt, reshapeLineGeos );
3144 GEOSGeometry* newMultiGeom = 0;
3147 newMultiGeom = GEOSGeom_createCollection_r( geosinit.
ctxt, GEOS_MULTILINESTRING, newGeoms, numGeoms );
3151 newMultiGeom = GEOSGeom_createCollection_r( geosinit.
ctxt, GEOS_MULTIPOLYGON, newGeoms, numGeoms );
3155 if ( !newMultiGeom )
3158 if ( reshapeTookPlace )
3160 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
3161 mGeos = newMultiGeom;
3167 GEOSGeom_destroy_r( geosinit.
ctxt, newMultiGeom );
3185 if ( !GEOSisValid_r( geosinit.
ctxt, mGeos ) )
3188 if ( !GEOSisSimple_r( geosinit.
ctxt, mGeos ) )
3192 if ( other->mDirtyGeos )
3193 other->exportWkbToGeos();
3195 if ( !other->mGeos )
3201 if ( GEOSIntersects_r( geosinit.
ctxt, mGeos, other->mGeos ) )
3206 mGeos = GEOSDifference_r( geosinit.
ctxt, mGeos, other->mGeos );
3251 bool hasZValue =
false;
3287 for (
int idx = 0; idx < nPoints; idx++ )
3289 wkbPtr += 1 +
sizeof( int );
3294 wkbPtr +=
sizeof( double );
3319 for (
int idx = 0; idx < nPoints; idx++ )
3324 wkbPtr +=
sizeof( double );
3348 for (
int jdx = 0; jdx < nLines; jdx++ )
3351 wkbPtr += 1 +
sizeof( int );
3354 for (
int idx = 0; idx < nPoints; idx++ )
3359 wkbPtr +=
sizeof( double );
3385 for (
int idx = 0; idx < nRings; idx++ )
3390 for (
int jdx = 0; jdx < nPoints; jdx++ )
3396 wkbPtr +=
sizeof( double );
3421 wkbPtr >> nPolygons;
3422 for (
int kdx = 0; kdx < nPolygons; kdx++ )
3426 wkbPtr += 1 +
sizeof( int );
3429 for (
int idx = 0; idx < nRings; idx++ )
3434 for (
int jdx = 0; jdx < nPoints; jdx++ )
3440 wkbPtr +=
sizeof( double );
3461 QgsDebugMsg( QString(
"Unknown WkbType %1 ENCOUNTERED" ).arg( wkbType ) );
3486 geometry->exportWkbToGeos();
3488 if ( !mGeos || !geometry->mGeos )
3494 return GEOSIntersects_r( geosinit.
ctxt, mGeos, geometry->mGeos );
3515 GEOSGeometry *geosPoint = 0;
3517 bool returnval =
false;
3522 returnval = GEOSContains_r( geosinit.
ctxt, mGeos, geosPoint );
3531 GEOSGeom_destroy_r( geosinit.
ctxt, geosPoint );
3536 bool QgsGeometry::geosRelOp(
3537 char( *op )( GEOSContextHandle_t handle,
const GEOSGeometry*,
const GEOSGeometry * ),
3547 a->exportWkbToGeos();
3548 b->exportWkbToGeos();
3550 if ( !a->mGeos || !b->mGeos )
3555 return op( geosinit.
ctxt, a->mGeos, b->mGeos );
3562 return geosRelOp( GEOSContains_r,
this, geometry );
3567 return geosRelOp( GEOSDisjoint_r,
this, geometry );
3572 return geosRelOp( GEOSEquals_r,
this, geometry );
3577 return geosRelOp( GEOSTouches_r,
this, geometry );
3582 return geosRelOp( GEOSOverlaps_r,
this, geometry );
3587 return geosRelOp( GEOSWithin_r,
this, geometry );
3592 return geosRelOp( GEOSCrosses_r,
this, geometry );
3605 if ( !mGeometry ||
wkbSize() < 5 )
3607 QgsDebugMsg(
"WKB geometry not available or too short!" );
3608 return QString::null;
3611 bool hasZValue =
false;
3637 wkt +=
"LINESTRING(";
3639 for (
int idx = 0; idx < nPoints; ++idx )
3644 wkbPtr +=
sizeof( double );
3667 for (
int idx = 0; idx < nRings; idx++ )
3677 for (
int jdx = 0; jdx < nPoints; jdx++ )
3685 wkbPtr +=
sizeof( double );
3703 wkt +=
"MULTIPOINT(";
3704 for (
int idx = 0; idx < nPoints; ++idx )
3706 wkbPtr += 1 +
sizeof( int );
3713 wkbPtr +=
sizeof( double );
3729 wkt +=
"MULTILINESTRING(";
3730 for (
int jdx = 0; jdx < nLines; jdx++ )
3736 wkbPtr += 1 +
sizeof( int );
3739 for (
int idx = 0; idx < nPoints; idx++ )
3747 wkbPtr +=
sizeof( double );
3763 wkbPtr >> nPolygons;
3765 wkt +=
"MULTIPOLYGON(";
3766 for (
int kdx = 0; kdx < nPolygons; kdx++ )
3772 wkbPtr += 1 +
sizeof( int );
3775 for (
int idx = 0; idx < nRings; idx++ )
3783 for (
int jdx = 0; jdx < nPoints; jdx++ )
3791 wkbPtr +=
sizeof( double );
3804 QgsDebugMsg(
"error: mGeometry type not recognized" );
3805 return QString::null;
3820 return QString::null;
3826 bool hasZValue =
false;
3839 wkt +=
"{ \"type\": \"Point\", \"coordinates\": ["
3852 wkt +=
"{ \"type\": \"LineString\", \"coordinates\": [ ";
3856 for (
int idx = 0; idx < nPoints; ++idx )
3864 wkbPtr +=
sizeof( double );
3878 wkt +=
"{ \"type\": \"Polygon\", \"coordinates\": [ ";
3885 for (
int idx = 0; idx < nRings; idx++ )
3895 for (
int jdx = 0; jdx < nPoints; jdx++ )
3903 wkbPtr +=
sizeof( double );
3918 wkt +=
"{ \"type\": \"MultiPoint\", \"coordinates\": [ ";
3921 for (
int idx = 0; idx < nPoints; ++idx )
3923 wkbPtr += 1 +
sizeof( int );
3930 wkbPtr +=
sizeof( double );
3943 wkt +=
"{ \"type\": \"MultiLineString\", \"coordinates\": [ ";
3947 for (
int jdx = 0; jdx < nLines; jdx++ )
3953 wkbPtr += 1 +
sizeof( int );
3957 for (
int idx = 0; idx < nPoints; idx++ )
3965 wkbPtr +=
sizeof( double );
3981 wkt +=
"{ \"type\": \"MultiPolygon\", \"coordinates\": [ ";
3984 wkbPtr >> nPolygons;
3985 for (
int kdx = 0; kdx < nPolygons; kdx++ )
3992 wkbPtr += 1 +
sizeof( int );
3996 for (
int idx = 0; idx < nRings; idx++ )
4005 for (
int jdx = 0; jdx < nPoints; jdx++ )
4013 wkbPtr +=
sizeof( double );
4026 QgsDebugMsg(
"error: mGeometry type not recognized" );
4027 return QString::null;
4031 bool QgsGeometry::exportWkbToGeos()
const
4043 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
4055 bool hasZValue =
false;
4080 QVector<GEOSGeometry *> points;
4084 for (
int idx = 0; idx < nPoints; idx++ )
4087 wkbPtr += 1 +
sizeof( int );
4090 wkbPtr +=
sizeof( double );
4108 for (
int idx = 0; idx < nPoints; idx++ )
4113 wkbPtr +=
sizeof( double );
4127 QVector<GEOSGeometry*> lines;
4130 for (
int jdx = 0; jdx < nLines; jdx++ )
4135 wkbPtr += 1 +
sizeof( int );
4138 for (
int idx = 0; idx < nPoints; idx++ )
4143 wkbPtr +=
sizeof( double );
4149 if ( sequence.count() > 1 )
4166 QVector<GEOSGeometry*> rings;
4168 for (
int idx = 0; idx < nRings; idx++ )
4177 for (
int jdx = 0; jdx < nPoints; jdx++ )
4183 wkbPtr +=
sizeof( double );
4189 if ( ring ) rings << ring;
4201 QVector<GEOSGeometry*> polygons;
4205 wkbPtr >> nPolygons;
4207 for (
int kdx = 0; kdx < nPolygons; kdx++ )
4210 QVector<GEOSGeometry*> rings;
4214 wkbPtr += 1 +
sizeof( int );
4217 for (
int idx = 0; idx < numRings; idx++ )
4226 for (
int jdx = 0; jdx < nPoints; jdx++ )
4232 wkbPtr +=
sizeof( double );
4238 if ( ring ) rings << ring;
4242 if ( polygon ) polygons << polygon;
4270 delete [] mGeometry;
4284 switch ( GEOSGeomTypeId_r( geosinit.
ctxt, mGeos ) )
4290 2 *
sizeof(
double );
4291 mGeometry =
new unsigned char[mGeometrySize];
4294 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, mGeos );
4297 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, 0, &x );
4298 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, 0, &y );
4307 case GEOS_LINESTRING:
4311 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, mGeos );
4312 unsigned int nPoints;
4313 GEOSCoordSeq_getSize_r( geosinit.
ctxt, cs, &nPoints );
4319 ((
sizeof( double ) +
4320 sizeof(
double ) ) * nPoints );
4322 mGeometry =
new unsigned char[mGeometrySize];
4327 const GEOSCoordSequence *sequence = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, mGeos );
4330 for (
unsigned int n = 0; n < nPoints; n++ )
4333 GEOSCoordSeq_getX_r( geosinit.
ctxt, sequence, n, &x );
4334 GEOSCoordSeq_getY_r( geosinit.
ctxt, sequence, n, &y );
4344 case GEOS_LINEARRING:
4352 int nPointsInRing = 0;
4355 int geometrySize = 1 + 2 *
sizeof( int );
4356 const GEOSGeometry *theRing = GEOSGetExteriorRing_r( geosinit.
ctxt, mGeos );
4359 geometrySize +=
sizeof( int );
4362 for (
int i = 0; i < GEOSGetNumInteriorRings_r( geosinit.
ctxt, mGeos ); ++i )
4364 geometrySize +=
sizeof( int );
4365 theRing = GEOSGetInteriorRingN_r( geosinit.
ctxt, mGeos, i );
4372 mGeometry =
new unsigned char[geometrySize];
4373 mGeometrySize = geometrySize;
4378 int nRings = GEOSGetNumInteriorRings_r( geosinit.
ctxt, mGeos ) + 1;
4382 theRing = GEOSGetExteriorRing_r( geosinit.
ctxt, mGeos );
4387 wkbPtr << nPointsInRing;
4389 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, theRing );
4391 GEOSCoordSeq_getSize_r( geosinit.
ctxt, cs, &n );
4393 for (
unsigned int j = 0; j < n; ++j )
4396 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, j, &x );
4397 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, j, &y );
4403 for (
int i = 0; i < GEOSGetNumInteriorRings_r( geosinit.
ctxt, mGeos ); i++ )
4405 theRing = GEOSGetInteriorRingN_r( geosinit.
ctxt, mGeos, i );
4407 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, theRing );
4409 unsigned int nPointsInRing;
4410 GEOSCoordSeq_getSize_r( geosinit.
ctxt, cs, &nPointsInRing );
4411 wkbPtr << nPointsInRing;
4413 for (
unsigned int j = 0; j < nPointsInRing; j++ )
4416 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, j, &x );
4417 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, j, &y );
4426 case GEOS_MULTIPOINT:
4429 int geometrySize = 1 + 2 *
sizeof( int );
4430 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); i++ )
4432 geometrySize += 1 +
sizeof( int ) + 2 *
sizeof(
double );
4435 mGeometry =
new unsigned char[geometrySize];
4436 mGeometrySize = geometrySize;
4439 int numPoints = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
4443 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); i++ )
4448 const GEOSGeometry *currentPoint = GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i );
4450 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, currentPoint );
4453 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, 0, &x );
4454 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, 0, &y );
4461 case GEOS_MULTILINESTRING:
4464 int geometrySize = 1 + 2 *
sizeof( int );
4465 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); i++ )
4467 geometrySize += 1 + 2 *
sizeof( int );
4468 geometrySize +=
getNumGeosPoints( GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ) ) * 2 *
sizeof( double );
4471 mGeometry =
new unsigned char[geometrySize];
4472 mGeometrySize = geometrySize;
4476 int numLines = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
4480 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); i++ )
4485 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i ) );
4488 unsigned int lineSize;
4489 GEOSCoordSeq_getSize_r( geosinit.
ctxt, cs, &lineSize );
4493 for (
unsigned int j = 0; j < lineSize; ++j )
4496 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, j, &x );
4497 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, j, &y );
4505 case GEOS_MULTIPOLYGON:
4508 int geometrySize = 1 + 2 *
sizeof( int );
4509 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); i++ )
4511 const GEOSGeometry *thePoly = GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i );
4512 geometrySize += 1 + 2 *
sizeof( int );
4514 geometrySize +=
sizeof( int );
4515 const GEOSGeometry *exRing = GEOSGetExteriorRing_r( geosinit.
ctxt, thePoly );
4518 const GEOSGeometry *intRing = 0;
4519 for (
int j = 0; j < GEOSGetNumInteriorRings_r( geosinit.
ctxt, thePoly ); j++ )
4521 geometrySize +=
sizeof( int );
4522 intRing = GEOSGetInteriorRingN_r( geosinit.
ctxt, thePoly, j );
4527 mGeometry =
new unsigned char[geometrySize];
4528 mGeometrySize = geometrySize;
4531 int numPolygons = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
4535 for (
int i = 0; i < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); i++ )
4537 const GEOSGeometry *thePoly = GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i );
4538 int numRings = GEOSGetNumInteriorRings_r( geosinit.
ctxt, thePoly ) + 1;
4541 const GEOSGeometry *theRing = GEOSGetExteriorRing_r( geosinit.
ctxt, thePoly );
4546 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, theRing );
4548 for (
int k = 0; k < nPointsInRing; ++k )
4551 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, k, &x );
4552 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, k, &y );
4557 for (
int j = 0; j < GEOSGetNumInteriorRings_r( geosinit.
ctxt, thePoly ); j++ )
4559 theRing = GEOSGetInteriorRingN_r( geosinit.
ctxt, thePoly, j );
4562 wkbPtr << nPointsInRing;
4564 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, theRing );
4566 for (
int k = 0; k < nPointsInRing; ++k )
4569 GEOSCoordSeq_getX_r( geosinit.
ctxt, cs, k, &x );
4570 GEOSCoordSeq_getY_r( geosinit.
ctxt, cs, k, &y );
4579 case GEOS_GEOMETRYCOLLECTION:
4582 QgsDebugMsg(
"geometry collection - not supported" );
4596 return convertToPoint( destMultipart );
4599 return convertToLine( destMultipart );
4602 return convertToPolygon( destMultipart );
4631 size_t newGeomSize = mGeometrySize + 1 + 2 *
sizeof( int );
4632 unsigned char* newGeometry =
new unsigned char[newGeomSize];
4638 wkbPtr << byteOrder;
4651 case QGis::WKBLineString:
4664 delete [] newGeometry;
4668 wkbPtr << newMultiType << 1;
4671 memcpy( wkbPtr, mGeometry, mGeometrySize );
4673 delete [] mGeometry;
4674 mGeometry = newGeometry;
4675 mGeometrySize = newGeomSize;
4680 void QgsGeometry::transformVertex(
QgsWkbPtr &wkbPtr,
const QTransform& trans,
bool hasZValue )
4682 double x, y, rotated_x, rotated_y;
4686 trans.map( x, y, &rotated_x, &rotated_y );
4687 wkbPtr << rotated_x << rotated_y;
4690 wkbPtr +=
sizeof( double );
4695 double x, y, z = 0.0;
4703 wkbPtr +=
sizeof( double );
4706 GEOSGeometry* QgsGeometry::linePointDifference( GEOSGeometry* GEOSsplitPoint )
4708 int type = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
4711 if ( type == GEOS_MULTILINESTRING )
4713 else if ( type == GEOS_LINESTRING )
4728 for (
int i = 0; i < multiLine.size() ; ++i )
4730 line = multiLine[i];
4732 newline.append( line[0] );
4734 for (
int j = 1; j < line.size() - 1 ; ++j )
4736 newline.append( line[j] );
4737 if ( line[j] == splitPoint )
4739 lines.append( newline );
4741 newline.append( line[j] );
4744 newline.append( line.last() );
4745 lines.append( newline );
4748 GEOSGeometry* splitGeom = GEOSGeom_clone_r( geosinit.
ctxt, splitLines->
asGeos() );
4754 int QgsGeometry::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries )
4766 if ( !GEOSIntersects_r( geosinit.
ctxt, splitLine, mGeos ) )
4770 int linearIntersect = GEOSRelatePattern_r( geosinit.
ctxt, mGeos, splitLine,
"1********" );
4771 if ( linearIntersect > 0 )
4774 int splitGeomType = GEOSGeomTypeId_r( geosinit.
ctxt, splitLine );
4776 GEOSGeometry* splitGeom;
4777 if ( splitGeomType == GEOS_POINT )
4779 splitGeom = linePointDifference( splitLine );
4783 splitGeom = GEOSDifference_r( geosinit.
ctxt, mGeos, splitLine );
4785 QVector<GEOSGeometry*> lineGeoms;
4787 int splitType = GEOSGeomTypeId_r( geosinit.
ctxt, splitGeom );
4788 if ( splitType == GEOS_MULTILINESTRING )
4790 int nGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, splitGeom );
4791 for (
int i = 0; i < nGeoms; ++i )
4792 lineGeoms << GEOSGeom_clone_r( geosinit.
ctxt, GEOSGetGeometryN_r( geosinit.
ctxt, splitGeom, i ) );
4797 lineGeoms << GEOSGeom_clone_r( geosinit.
ctxt, splitGeom );
4800 mergeGeometriesMultiTypeSplit( lineGeoms );
4802 if ( lineGeoms.size() > 0 )
4807 for (
int i = 1; i < lineGeoms.size(); ++i )
4812 GEOSGeom_destroy_r( geosinit.
ctxt, splitGeom );
4816 int QgsGeometry::splitPolygonGeometry( GEOSGeometry* splitLine, QList<QgsGeometry*>& newGeometries )
4828 if ( !GEOSIntersects_r( geosinit.
ctxt, splitLine, mGeos ) )
4832 GEOSGeometry *nodedGeometry = nodeGeometries( splitLine, mGeos );
4833 if ( !nodedGeometry )
4836 GEOSGeometry *polygons = GEOSPolygonize_r( geosinit.
ctxt, &nodedGeometry, 1 );
4837 if ( !polygons || numberOfGeometries( polygons ) == 0 )
4840 GEOSGeom_destroy_r( geosinit.
ctxt, polygons );
4842 GEOSGeom_destroy_r( geosinit.
ctxt, nodedGeometry );
4847 GEOSGeom_destroy_r( geosinit.
ctxt, nodedGeometry );
4851 QVector<GEOSGeometry*> testedGeometries;
4852 GEOSGeometry *intersectGeometry = 0;
4857 for (
int i = 0; i < numberOfGeometries( polygons ); i++ )
4859 const GEOSGeometry *polygon = GEOSGetGeometryN_r( geosinit.
ctxt, polygons, i );
4860 intersectGeometry = GEOSIntersection_r( geosinit.
ctxt, mGeos, polygon );
4861 if ( !intersectGeometry )
4867 double intersectionArea;
4868 GEOSArea_r( geosinit.
ctxt, intersectGeometry, &intersectionArea );
4871 GEOSArea_r( geosinit.
ctxt, polygon, &polygonArea );
4873 const double areaRatio = intersectionArea / polygonArea;
4874 if ( areaRatio > 0.99 && areaRatio < 1.01 )
4875 testedGeometries << GEOSGeom_clone_r( geosinit.
ctxt, polygon );
4877 GEOSGeom_destroy_r( geosinit.
ctxt, intersectGeometry );
4880 bool splitDone =
true;
4881 int nGeometriesThis = numberOfGeometries( mGeos );
4882 if ( testedGeometries.size() == nGeometriesThis )
4887 mergeGeometriesMultiTypeSplit( testedGeometries );
4892 for (
int i = 0; i < testedGeometries.size(); ++i )
4894 GEOSGeom_destroy_r( geosinit.
ctxt, testedGeometries[i] );
4898 else if ( testedGeometries.size() > 0 )
4900 GEOSGeom_destroy_r( geosinit.
ctxt, mGeos );
4901 mGeos = testedGeometries[0];
4906 for ( i = 1; i < testedGeometries.size() && GEOSisValid_r( geosinit.
ctxt, testedGeometries[i] ); ++i )
4909 if ( i < testedGeometries.size() )
4911 for ( i = 0; i < testedGeometries.size(); ++i )
4912 GEOSGeom_destroy_r( geosinit.
ctxt, testedGeometries[i] );
4917 for ( i = 1; i < testedGeometries.size(); ++i )
4920 GEOSGeom_destroy_r( geosinit.
ctxt, polygons );
4924 GEOSGeometry* QgsGeometry::reshapePolygon(
const GEOSGeometry* polygon,
const GEOSGeometry* reshapeLineGeos )
4927 int nIntersections = 0;
4928 int lastIntersectingRing = -2;
4929 const GEOSGeometry* lastIntersectingGeom = 0;
4931 int nRings = GEOSGetNumInteriorRings_r( geosinit.
ctxt, polygon );
4936 const GEOSGeometry* outerRing = GEOSGetExteriorRing_r( geosinit.
ctxt, polygon );
4937 if ( GEOSIntersects_r( geosinit.
ctxt, outerRing, reshapeLineGeos ) == 1 )
4940 lastIntersectingRing = -1;
4941 lastIntersectingGeom = outerRing;
4945 const GEOSGeometry **innerRings =
new const GEOSGeometry*[nRings];
4949 for (
int i = 0; i < nRings; ++i )
4951 innerRings[i] = GEOSGetInteriorRingN_r( geosinit.
ctxt, polygon, i );
4952 if ( GEOSIntersects_r( geosinit.
ctxt, innerRings[i], reshapeLineGeos ) == 1 )
4955 lastIntersectingRing = i;
4956 lastIntersectingGeom = innerRings[i];
4966 if ( nIntersections != 1 )
4968 delete [] innerRings;
4973 GEOSGeometry* reshapeResult = reshapeLine( lastIntersectingGeom, reshapeLineGeos );
4974 if ( !reshapeResult )
4976 delete [] innerRings;
4981 GEOSGeometry* newRing = 0;
4982 const GEOSCoordSequence* reshapeSequence = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, reshapeResult );
4983 GEOSCoordSequence* newCoordSequence = GEOSCoordSeq_clone_r( geosinit.
ctxt, reshapeSequence );
4985 GEOSGeom_destroy_r( geosinit.
ctxt, reshapeResult );
4989 newRing = GEOSGeom_createLinearRing_r( geosinit.
ctxt, newCoordSequence );
4998 delete [] innerRings;
5002 GEOSGeometry* newOuterRing = 0;
5003 if ( lastIntersectingRing == -1 )
5004 newOuterRing = newRing;
5006 newOuterRing = GEOSGeom_clone_r( geosinit.
ctxt, outerRing );
5009 QList<GEOSGeometry*> ringList;
5012 GEOSGeometry* outerRingPoly = GEOSGeom_createPolygon_r( geosinit.
ctxt, GEOSGeom_clone_r( geosinit.
ctxt, newOuterRing ), 0, 0 );
5013 if ( outerRingPoly )
5015 GEOSGeometry* currentRing = 0;
5016 for (
int i = 0; i < nRings; ++i )
5018 if ( lastIntersectingRing == i )
5019 currentRing = newRing;
5021 currentRing = GEOSGeom_clone_r( geosinit.
ctxt, innerRings[i] );
5024 if ( GEOSContains_r( geosinit.
ctxt, outerRingPoly, currentRing ) == 1 )
5025 ringList.push_back( currentRing );
5027 GEOSGeom_destroy_r( geosinit.
ctxt, currentRing );
5030 GEOSGeom_destroy_r( geosinit.
ctxt, outerRingPoly );
5033 GEOSGeometry** newInnerRings =
new GEOSGeometry*[ringList.size()];
5034 for (
int i = 0; i < ringList.size(); ++i )
5035 newInnerRings[i] = ringList.at( i );
5037 delete [] innerRings;
5039 GEOSGeometry* reshapedPolygon = GEOSGeom_createPolygon_r( geosinit.
ctxt, newOuterRing, newInnerRings, ringList.size() );
5040 delete[] newInnerRings;
5042 return reshapedPolygon;
5045 GEOSGeometry* QgsGeometry::reshapeLine(
const GEOSGeometry* line,
const GEOSGeometry* reshapeLineGeos )
5047 if ( !line || !reshapeLineGeos )
5050 bool atLeastTwoIntersections =
false;
5055 GEOSGeometry* intersectGeom = GEOSIntersection_r( geosinit.
ctxt, line, reshapeLineGeos );
5056 if ( intersectGeom )
5058 atLeastTwoIntersections = ( GEOSGeomTypeId_r( geosinit.
ctxt, intersectGeom ) == GEOS_MULTIPOINT && GEOSGetNumGeometries_r( geosinit.
ctxt, intersectGeom ) > 1 );
5059 GEOSGeom_destroy_r( geosinit.
ctxt, intersectGeom );
5065 atLeastTwoIntersections =
false;
5068 if ( !atLeastTwoIntersections )
5072 const GEOSCoordSequence* lineCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, line );
5073 if ( !lineCoordSeq )
5076 unsigned int lineCoordSeqSize;
5077 if ( GEOSCoordSeq_getSize_r( geosinit.
ctxt, lineCoordSeq, &lineCoordSeqSize ) == 0 )
5080 if ( lineCoordSeqSize < 2 )
5084 double x1, y1, x2, y2;
5085 GEOSCoordSeq_getX_r( geosinit.
ctxt, lineCoordSeq, 0, &x1 );
5086 GEOSCoordSeq_getY_r( geosinit.
ctxt, lineCoordSeq, 0, &y1 );
5087 GEOSCoordSeq_getX_r( geosinit.
ctxt, lineCoordSeq, lineCoordSeqSize - 1, &x2 );
5088 GEOSCoordSeq_getY_r( geosinit.
ctxt, lineCoordSeq, lineCoordSeqSize - 1, &y2 );
5092 bool isRing =
false;
5093 if ( GEOSGeomTypeId_r( geosinit.
ctxt, line ) == GEOS_LINEARRING || GEOSEquals_r( geosinit.
ctxt, beginLineVertex, endLineVertex ) == 1 )
5097 GEOSGeometry* nodedGeometry = nodeGeometries( reshapeLineGeos, line );
5098 if ( !nodedGeometry )
5100 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
5101 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
5106 GEOSGeometry *mergedLines = GEOSLineMerge_r( geosinit.
ctxt, nodedGeometry );
5107 GEOSGeom_destroy_r( geosinit.
ctxt, nodedGeometry );
5110 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
5111 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
5115 int numMergedLines = GEOSGetNumGeometries_r( geosinit.
ctxt, mergedLines );
5116 if ( numMergedLines < 2 )
5118 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
5119 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
5120 if ( numMergedLines == 1 )
5121 return GEOSGeom_clone_r( geosinit.
ctxt, reshapeLineGeos );
5126 QList<GEOSGeometry*> resultLineParts;
5127 QList<GEOSGeometry*> probableParts;
5129 for (
int i = 0; i < numMergedLines; ++i )
5131 const GEOSGeometry* currentGeom;
5133 currentGeom = GEOSGetGeometryN_r( geosinit.
ctxt, mergedLines, i );
5134 const GEOSCoordSequence* currentCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, currentGeom );
5135 unsigned int currentCoordSeqSize;
5136 GEOSCoordSeq_getSize_r( geosinit.
ctxt, currentCoordSeq, ¤tCoordSeqSize );
5137 if ( currentCoordSeqSize < 2 )
5141 double xBegin, xEnd, yBegin, yEnd;
5142 GEOSCoordSeq_getX_r( geosinit.
ctxt, currentCoordSeq, 0, &xBegin );
5143 GEOSCoordSeq_getY_r( geosinit.
ctxt, currentCoordSeq, 0, &yBegin );
5144 GEOSCoordSeq_getX_r( geosinit.
ctxt, currentCoordSeq, currentCoordSeqSize - 1, &xEnd );
5145 GEOSCoordSeq_getY_r( geosinit.
ctxt, currentCoordSeq, currentCoordSeqSize - 1, &yEnd );
5150 int nEndpointsOnOriginalLine = 0;
5151 if ( pointContainedInLine( beginCurrentGeomVertex, line ) == 1 )
5152 nEndpointsOnOriginalLine += 1;
5154 if ( pointContainedInLine( endCurrentGeomVertex, line ) == 1 )
5155 nEndpointsOnOriginalLine += 1;
5158 int nEndpointsSameAsOriginalLine = 0;
5159 if ( GEOSEquals_r( geosinit.
ctxt, beginCurrentGeomVertex, beginLineVertex ) == 1 || GEOSEquals_r( geosinit.
ctxt, beginCurrentGeomVertex, endLineVertex ) == 1 )
5160 nEndpointsSameAsOriginalLine += 1;
5162 if ( GEOSEquals_r( geosinit.
ctxt, endCurrentGeomVertex, beginLineVertex ) == 1 || GEOSEquals_r( geosinit.
ctxt, endCurrentGeomVertex, endLineVertex ) == 1 )
5163 nEndpointsSameAsOriginalLine += 1;
5166 bool currentGeomOverlapsOriginalGeom =
false;
5167 bool currentGeomOverlapsReshapeLine =
false;
5168 if ( QgsGeometry::lineContainedInLine( currentGeom, line ) == 1 )
5169 currentGeomOverlapsOriginalGeom =
true;
5171 if ( QgsGeometry::lineContainedInLine( currentGeom, reshapeLineGeos ) == 1 )
5172 currentGeomOverlapsReshapeLine =
true;
5175 if ( nEndpointsSameAsOriginalLine == 1 && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
5177 resultLineParts.push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
5180 else if ( isRing && nEndpointsOnOriginalLine == 2 && currentGeomOverlapsOriginalGeom )
5182 probableParts.push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
5184 else if ( nEndpointsOnOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
5186 resultLineParts.push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
5188 else if ( nEndpointsSameAsOriginalLine == 2 && !currentGeomOverlapsOriginalGeom )
5190 resultLineParts.push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
5192 else if ( currentGeomOverlapsOriginalGeom && currentGeomOverlapsReshapeLine )
5194 resultLineParts.push_back( GEOSGeom_clone_r( geosinit.
ctxt, currentGeom ) );
5197 GEOSGeom_destroy_r( geosinit.
ctxt, beginCurrentGeomVertex );
5198 GEOSGeom_destroy_r( geosinit.
ctxt, endCurrentGeomVertex );
5202 if ( isRing && probableParts.size() > 0 )
5204 GEOSGeometry* maxGeom = 0;
5205 GEOSGeometry* currentGeom = 0;
5206 double maxLength = -DBL_MAX;
5207 double currentLength = 0;
5208 for (
int i = 0; i < probableParts.size(); ++i )
5210 currentGeom = probableParts.at( i );
5211 GEOSLength_r( geosinit.
ctxt, currentGeom, ¤tLength );
5212 if ( currentLength > maxLength )
5214 maxLength = currentLength;
5215 GEOSGeom_destroy_r( geosinit.
ctxt, maxGeom );
5216 maxGeom = currentGeom;
5220 GEOSGeom_destroy_r( geosinit.
ctxt, currentGeom );
5223 resultLineParts.push_back( maxGeom );
5226 GEOSGeom_destroy_r( geosinit.
ctxt, beginLineVertex );
5227 GEOSGeom_destroy_r( geosinit.
ctxt, endLineVertex );
5228 GEOSGeom_destroy_r( geosinit.
ctxt, mergedLines );
5230 GEOSGeometry* result = 0;
5231 if ( resultLineParts.size() < 1 )
5234 if ( resultLineParts.size() == 1 )
5236 result = resultLineParts[0];
5240 GEOSGeometry **lineArray =
new GEOSGeometry*[resultLineParts.size()];
5241 for (
int i = 0; i < resultLineParts.size(); ++i )
5243 lineArray[i] = resultLineParts[i];
5247 GEOSGeometry* multiLineGeom = GEOSGeom_createCollection_r( geosinit.
ctxt, GEOS_MULTILINESTRING, lineArray, resultLineParts.size() );
5248 delete [] lineArray;
5251 result = GEOSLineMerge_r( geosinit.
ctxt, multiLineGeom );
5252 GEOSGeom_destroy_r( geosinit.
ctxt, multiLineGeom );
5256 if ( GEOSGeomTypeId_r( geosinit.
ctxt, result ) != GEOS_LINESTRING )
5258 GEOSGeom_destroy_r( geosinit.
ctxt, result );
5265 int QgsGeometry::topologicalTestPointsSplit(
const GEOSGeometry* splitLine, QList<QgsPoint>& testPoints )
const
5272 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.
ctxt, mGeos, splitLine );
5273 if ( !intersectionGeom )
5276 bool simple =
false;
5277 int nIntersectGeoms = 1;
5278 if ( GEOSGeomTypeId_r( geosinit.
ctxt, intersectionGeom ) == GEOS_LINESTRING || GEOSGeomTypeId_r( geosinit.
ctxt, intersectionGeom ) == GEOS_POINT )
5282 nIntersectGeoms = GEOSGetNumGeometries_r( geosinit.
ctxt, intersectionGeom );
5284 for (
int i = 0; i < nIntersectGeoms; ++i )
5286 const GEOSGeometry* currentIntersectGeom;
5288 currentIntersectGeom = intersectionGeom;
5290 currentIntersectGeom = GEOSGetGeometryN_r( geosinit.
ctxt, intersectionGeom, i );
5292 const GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, currentIntersectGeom );
5293 unsigned int sequenceSize = 0;
5295 if ( GEOSCoordSeq_getSize_r( geosinit.
ctxt, lineSequence, &sequenceSize ) != 0 )
5297 for (
unsigned int i = 0; i < sequenceSize; ++i )
5299 if ( GEOSCoordSeq_getX_r( geosinit.
ctxt, lineSequence, i, &x ) != 0 )
5301 if ( GEOSCoordSeq_getY_r( geosinit.
ctxt, lineSequence, i, &y ) != 0 )
5303 testPoints.push_back(
QgsPoint( x, y ) );
5309 GEOSGeom_destroy_r( geosinit.
ctxt, intersectionGeom );
5313 GEOSGeometry *QgsGeometry::nodeGeometries(
const GEOSGeometry *splitLine,
const GEOSGeometry *geom )
5315 if ( !splitLine || !geom )
5318 if ( GEOSGeomTypeId_r( geosinit.
ctxt, geom ) == GEOS_POLYGON || GEOSGeomTypeId_r( geosinit.
ctxt, geom ) == GEOS_MULTIPOLYGON )
5320 GEOSGeometry *geometryBoundary = GEOSBoundary_r( geosinit.
ctxt, geom );
5321 GEOSGeometry *unionGeometry = GEOSUnion_r( geosinit.
ctxt, splitLine, geometryBoundary );
5322 GEOSGeom_destroy_r( geosinit.
ctxt, geometryBoundary );
5323 return unionGeometry;
5327 return GEOSUnion_r( geosinit.
ctxt, splitLine, geom );
5331 int QgsGeometry::lineContainedInLine(
const GEOSGeometry* line1,
const GEOSGeometry* line2 )
5333 if ( !line1 || !line2 )
5338 double bufferDistance = pow( 10.0L, geomDigits( line2 ) - 11 );
5344 GEOSGeometry* intersectionGeom = GEOSIntersection_r( geosinit.
ctxt, bufferGeom, line1 );
5347 double intersectGeomLength;
5350 GEOSLength_r( geosinit.
ctxt, intersectionGeom, &intersectGeomLength );
5351 GEOSLength_r( geosinit.
ctxt, line1, &line1Length );
5353 GEOSGeom_destroy_r( geosinit.
ctxt, bufferGeom );
5354 GEOSGeom_destroy_r( geosinit.
ctxt, intersectionGeom );
5356 double intersectRatio = line1Length / intersectGeomLength;
5357 if ( intersectRatio > 0.9 && intersectRatio < 1.1 )
5363 int QgsGeometry::pointContainedInLine(
const GEOSGeometry* point,
const GEOSGeometry* line )
5365 if ( !point || !line )
5368 double bufferDistance = pow( 10.0L, geomDigits( line ) - 11 );
5370 GEOSGeometry* lineBuffer = GEOSBuffer_r( geosinit.
ctxt, line, bufferDistance, 8 );
5374 bool contained =
false;
5375 if ( GEOSContains_r( geosinit.
ctxt, lineBuffer, point ) == 1 )
5378 GEOSGeom_destroy_r( geosinit.
ctxt, lineBuffer );
5382 int QgsGeometry::geomDigits(
const GEOSGeometry* geom )
5384 GEOSGeometry* bbox = GEOSEnvelope_r( geosinit.
ctxt, geom );
5388 const GEOSGeometry* bBoxRing = GEOSGetExteriorRing_r( geosinit.
ctxt, bbox );
5392 const GEOSCoordSequence* bBoxCoordSeq = GEOSGeom_getCoordSeq_r( geosinit.
ctxt, bBoxRing );
5394 if ( !bBoxCoordSeq )
5397 unsigned int nCoords = 0;
5398 if ( !GEOSCoordSeq_getSize_r( geosinit.
ctxt, bBoxCoordSeq, &nCoords ) )
5402 for (
unsigned int i = 0; i < nCoords - 1; ++i )
5405 GEOSCoordSeq_getX_r( geosinit.
ctxt, bBoxCoordSeq, i, &t );
5408 digits = ceil( log10( fabs( t ) ) );
5409 if ( digits > maxDigits )
5412 GEOSCoordSeq_getY_r( geosinit.
ctxt, bBoxCoordSeq, i, &t );
5413 digits = ceil( log10( fabs( t ) ) );
5414 if ( digits > maxDigits )
5421 int QgsGeometry::numberOfGeometries( GEOSGeometry* g )
const
5426 int geometryType = GEOSGeomTypeId_r( geosinit.
ctxt, g );
5427 if ( geometryType == GEOS_POINT || geometryType == GEOS_LINESTRING || geometryType == GEOS_LINEARRING
5428 || geometryType == GEOS_POLYGON )
5432 return GEOSGetNumGeometries_r( geosinit.
ctxt, g );
5435 int QgsGeometry::mergeGeometriesMultiTypeSplit( QVector<GEOSGeometry*>& splitResult )
5444 int type = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
5445 if ( type != GEOS_GEOMETRYCOLLECTION &&
5446 type != GEOS_MULTILINESTRING &&
5447 type != GEOS_MULTIPOLYGON &&
5448 type != GEOS_MULTIPOINT )
5451 QVector<GEOSGeometry*> copyList = splitResult;
5452 splitResult.clear();
5455 QVector<GEOSGeometry*> unionGeom;
5457 for (
int i = 0; i < copyList.size(); ++i )
5460 bool isPart =
false;
5461 for (
int j = 0; j < GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos ); j++ )
5463 if ( GEOSEquals_r( geosinit.
ctxt, copyList[i], GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, j ) ) )
5472 unionGeom << copyList[i];
5476 QVector<GEOSGeometry*> geomVector;
5477 geomVector << copyList[i];
5479 if ( type == GEOS_MULTILINESTRING )
5481 else if ( type == GEOS_MULTIPOLYGON )
5484 GEOSGeom_destroy_r( geosinit.
ctxt, copyList[i] );
5489 if ( unionGeom.size() > 0 )
5491 if ( type == GEOS_MULTILINESTRING )
5493 else if ( type == GEOS_MULTIPOLYGON )
5506 wkbPtr += 1 +
sizeof( int );
5511 wkbPtr +=
sizeof( double );
5518 wkbPtr += 1 +
sizeof( int );
5520 unsigned int nPoints;
5526 for ( uint i = 0; i < nPoints; ++i )
5531 wkbPtr +=
sizeof( double );
5541 wkbPtr += 1 +
sizeof( int );
5544 unsigned int numRings;
5547 if ( numRings == 0 )
5552 for ( uint idx = 0; idx < numRings; idx++ )
5559 for (
int jdx = 0; jdx < nPoints; jdx++ )
5564 wkbPtr +=
sizeof( double );
5619 for (
int i = 0; i < nPoints; i++ )
5621 points[i] =
asPoint( wkbPtr, hasZValue );
5638 wkbPtr >> numLineStrings;
5642 for (
int i = 0; i < numLineStrings; i++ )
5659 wkbPtr >> numPolygons;
5663 for (
int i = 0; i < numPolygons; i++ )
5664 polygons[i] =
asPolygon( wkbPtr, hasZValue );
5681 if ( GEOSArea_r( geosinit.
ctxt, mGeos, &area ) == 0 )
5701 if ( GEOSLength_r( geosinit.
ctxt, mGeos, &length ) == 0 )
5713 if ( geom.mDirtyGeos )
5714 geom.exportWkbToGeos();
5716 if ( !mGeos || !geom.mGeos )
5723 GEOSDistance_r( geosinit.
ctxt, mGeos, geom.mGeos, &dist );
5740 return fromGeosGeom( GEOSBuffer_r( geosinit.
ctxt, mGeos, distance, segments ) );
5747 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
5748 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
5757 return fromGeosGeom( GEOSBufferWithStyle_r( geosinit.
ctxt, mGeos, distance, segments, endCapStyle, joinStyle, mitreLimit ) );
5767 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
5768 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
5777 return fromGeosGeom( GEOSOffsetCurve_r( geosinit.
ctxt, mGeos, distance, segments, joinStyle, mitreLimit ) );
5795 return fromGeosGeom( GEOSTopologyPreserveSimplify_r( geosinit.
ctxt, mGeos, tolerance ) );
5847 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
5848 ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=2)))
5857 return fromGeosGeom( GEOSInterpolate_r( geosinit.
ctxt, mGeos, distance ) );
5874 if ( geometry->mDirtyGeos )
5875 geometry->exportWkbToGeos();
5877 if ( !mGeos || !geometry->mGeos )
5882 return fromGeosGeom( GEOSIntersection_r( geosinit.
ctxt, mGeos, geometry->mGeos ) );
5895 if ( geometry->mDirtyGeos )
5896 geometry->exportWkbToGeos();
5898 if ( !mGeos || !geometry->mGeos )
5903 GEOSGeometry* unionGeom = GEOSUnion_r( geosinit.
ctxt, mGeos, geometry->mGeos );
5909 GEOSGeometry* mergedGeom = GEOSLineMerge_r( geosinit.
ctxt, unionGeom );
5912 GEOSGeom_destroy_r( geosinit.
ctxt, unionGeom );
5913 unionGeom = mergedGeom;
5929 if ( geometry->mDirtyGeos )
5930 geometry->exportWkbToGeos();
5932 if ( !mGeos || !geometry->mGeos )
5937 return fromGeosGeom( GEOSDifference_r( geosinit.
ctxt, mGeos, geometry->mGeos ) );
5950 if ( geometry->mDirtyGeos )
5951 geometry->exportWkbToGeos();
5953 if ( !mGeos || !geometry->mGeos )
5958 return fromGeosGeom( GEOSSymDifference_r( geosinit.
ctxt, mGeos, geometry->mGeos ) );
5969 return QList<QgsGeometry*>();
5971 int type = GEOSGeomTypeId_r( geosinit.
ctxt, mGeos );
5972 QgsDebugMsg(
"geom type: " + QString::number( type ) );
5974 QList<QgsGeometry*> geomCollection;
5976 if ( type != GEOS_MULTIPOINT &&
5977 type != GEOS_MULTILINESTRING &&
5978 type != GEOS_MULTIPOLYGON &&
5979 type != GEOS_GEOMETRYCOLLECTION )
5982 geomCollection.append(
new QgsGeometry( *
this ) );
5983 return geomCollection;
5986 int count = GEOSGetNumGeometries_r( geosinit.
ctxt, mGeos );
5987 QgsDebugMsg(
"geom count: " + QString::number( count ) );
5989 for (
int i = 0; i < count; ++i )
5991 const GEOSGeometry * geometry = GEOSGetGeometryN_r( geosinit.
ctxt, mGeos, i );
5992 geomCollection.append(
fromGeosGeom( GEOSGeom_clone_r( geosinit.
ctxt, geometry ) ) );
5995 return geomCollection;
6016 if ( polygon.size() < 1 )
6018 polyline = polygon.at( 0 );
6025 QgsPolyline::const_iterator lineIt = polyline.constBegin();
6026 for ( ; lineIt != polyline.constEnd(); ++lineIt )
6028 result << lineIt->toQPointF();
6035 if ( ringNum <= 0 || partNum < 0 )
6047 if ( ringNum >= polygon.count() )
6050 polygon.remove( ringNum );
6063 if ( partNum >= mpolygon.count() )
6066 if ( ringNum >= mpolygon[partNum].count() )
6069 mpolygon[partNum].remove( ringNum );
6094 if ( partNum >= mpoint.size() || mpoint.size() == 1 )
6097 mpoint.remove( partNum );
6110 if ( partNum >= mline.size() || mline.size() == 1 )
6113 mline.remove( partNum );
6126 if ( partNum >= mpolygon.size() || mpolygon.size() == 1 )
6129 mpolygon.remove( partNum );
6149 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && (((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)) || (GEOS_VERSION_MAJOR>3))
6150 GEOSGeometry* geomCollection = 0;
6152 GEOSGeometry* geomUnion = GEOSUnaryUnion_r( geosinit.
ctxt, geomCollection );
6153 GEOSGeom_destroy_r( geosinit.
ctxt, geomCollection );
6156 GEOSGeometry* geomCollection = geoms.takeFirst();
6158 while ( !geoms.isEmpty() )
6160 GEOSGeometry* g = geoms.takeFirst();
6161 GEOSGeometry* geomCollectionNew = GEOSUnion_r( geosinit.
ctxt, geomCollection, g );
6162 GEOSGeom_destroy_r( geosinit.
ctxt, geomCollection );
6163 GEOSGeom_destroy_r( geosinit.
ctxt, g );
6164 geomCollection = geomCollectionNew;
6167 return geomCollection;
6173 int returnValue = 0;
6187 QList<GEOSGeometry*> nearGeometries;
6191 QStringList::const_iterator aIt = avoidIntersectionsList.constBegin();
6192 for ( ; aIt != avoidIntersectionsList.constEnd(); ++aIt )
6198 QMap<QgsVectorLayer*, QSet<qint64> >::const_iterator ignoreIt = ignoreFeatures.find( currentLayer );
6199 if ( ignoreIt != ignoreFeatures.constEnd() )
6200 ignoreIds = ignoreIt.value();
6208 if ( ignoreIds.contains( f.
id() ) )
6219 if ( nearGeometries.isEmpty() )
6222 GEOSGeometry* nearGeometriesUnion = 0;
6223 GEOSGeometry* geomWithoutIntersections = 0;
6226 nearGeometriesUnion =
_makeUnion( nearGeometries );
6227 geomWithoutIntersections = GEOSDifference_r( geosinit.
ctxt,
asGeos(), nearGeometriesUnion );
6229 fromGeos( geomWithoutIntersections );
6231 GEOSGeom_destroy_r( geosinit.
ctxt, nearGeometriesUnion );
6235 if ( nearGeometriesUnion )
6236 GEOSGeom_destroy_r( geosinit.
ctxt, nearGeometriesUnion );
6237 if ( geomWithoutIntersections )
6238 GEOSGeom_destroy_r( geosinit.
ctxt, geomWithoutIntersections );
6245 if (
wkbType() != geomTypeBeforeModification )
6260 const GEOSGeometry *g =
asGeos();
6265 return GEOSisValid_r( geosinit.
ctxt, g );
6276 return geosRelOp( GEOSEquals_r,
this, &g );
6283 const GEOSGeometry *g =
asGeos();
6288 return GEOSisEmpty_r( geosinit.
ctxt, g );
6297 double QgsGeometry::leftOf(
double x,
double y,
double& x1,
double& y1,
double& x2,
double& y2 )
6300 double f2 = y2 - y1;
6302 double f4 = x2 - x1;
6303 return f1*f2 - f3*f4;
6306 QgsGeometry* QgsGeometry::convertToPoint(
bool destMultipart )
6314 if (( destMultipart && srcIsMultipart ) ||
6315 ( !destMultipart && !srcIsMultipart ) )
6320 if ( destMultipart )
6329 if ( multiPoint.count() == 1 )
6340 if ( !destMultipart )
6348 for ( QgsMultiPolyline::const_iterator multiLineIt = multiLine.constBegin(); multiLineIt != multiLine.constEnd(); ++multiLineIt )
6349 for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
6350 multiPoint << *lineIt;
6357 if ( !line.isEmpty() )
6366 if ( !destMultipart )
6374 for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
6375 for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
6376 for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
6377 multiPoint << *lineIt;
6385 for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
6386 for ( QgsPolyline::const_iterator lineIt = ( *multiLineIt ).constBegin(); lineIt != ( *multiLineIt ).constEnd(); ++lineIt )
6387 multiPoint << *lineIt;
6397 QgsGeometry* QgsGeometry::convertToLine(
bool destMultipart )
6407 if ( multiPoint.count() < 2 )
6410 if ( destMultipart )
6420 if (( destMultipart && srcIsMultipart ) ||
6421 ( !destMultipart && ! srcIsMultipart ) )
6426 if ( destMultipart )
6430 if ( !line.isEmpty() )
6437 if ( multiLine.count() == 1 )
6450 for ( QgsMultiPolygon::const_iterator polygonIt = multiPolygon.constBegin(); polygonIt != multiPolygon.constEnd(); ++polygonIt )
6451 for ( QgsMultiPolyline::const_iterator multiLineIt = ( *polygonIt ).constBegin(); multiLineIt != ( *polygonIt ).constEnd(); ++multiLineIt )
6452 multiLine << *multiLineIt;
6454 if ( destMultipart )
6459 else if ( multiLine.count() == 1 )
6470 if ( polygon.count() > 1 )
6474 if ( destMultipart )
6478 for ( QgsMultiPolyline::const_iterator multiLineIt = polygon.constBegin(); multiLineIt != polygon.constEnd(); ++multiLineIt )
6479 multiLine << *multiLineIt;
6484 else if ( polygon.count() == 1 )
6486 if ( destMultipart )
6504 QgsGeometry* QgsGeometry::convertToPolygon(
bool destMultipart )
6514 if ( multiPoint.count() < 3 )
6517 if ( multiPoint.last() != multiPoint.first() )
6518 multiPoint << multiPoint.first();
6521 if ( destMultipart )
6534 for ( QgsMultiPolyline::iterator multiLineIt = multiLine.begin(); multiLineIt != multiLine.end(); ++multiLineIt )
6537 if (( *multiLineIt ).count() < 3 )
6539 if (( *multiLineIt ).count() == 3 && ( *multiLineIt ).first() == ( *multiLineIt ).last() )
6543 if (( *multiLineIt ).first() != ( *multiLineIt ).last() )
6544 *multiLineIt << ( *multiLineIt ).first();
6545 multiPolygon << (
QgsPolygon() << *multiLineIt );
6548 if ( !multiPolygon.isEmpty() )
6550 if ( destMultipart )
6554 else if ( multiPolygon.count() == 1 )
6567 if ( line.count() < 3 )
6569 if ( line.count() == 3 && line.first() == line.last() )
6573 if ( line.first() != line.last() )
6574 line << line.first();
6577 if ( destMultipart )
6593 if (( destMultipart && srcIsMultipart ) ||
6594 ( !destMultipart && ! srcIsMultipart ) )
6599 if ( destMultipart )
6603 if ( !polygon.isEmpty() )
6609 if ( multiPolygon.count() == 1 )
6625 QList<GEOSGeometry*> geoms;
6628 geoms.append( GEOSGeom_clone_r( geosinit.
ctxt, g->
asGeos() ) );
6630 GEOSGeometry *geomUnion =
_makeUnion( geoms );