// Fully node given linework static GEOSGeometry *LWGEOM_GEOS_nodeLines( const GEOSGeometry *lines ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); // Union with first geometry point, obtaining full noding // and dissolving of duplicated repeated points // // TODO: substitute this with UnaryUnion? GEOSGeometry *point = LWGEOM_GEOS_getPointN( lines, 0 ); if ( ! point ) return nullptr; GEOSGeometry *noded = nullptr; try { noded = GEOSUnion_r( handle, lines, point ); } catch ( GEOSException & ) { // no need to do anything here - we'll return nullptr anyway } GEOSGeom_destroy_r( handle, point ); return noded; }
// Fully node given linework static GEOSGeometry *LWGEOM_GEOS_nodeLines( const GEOSGeometry *lines ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); // Union with first geometry point, obtaining full noding // and dissolving of duplicated repeated points // // TODO: substitute this with UnaryUnion? GEOSGeometry *point = LWGEOM_GEOS_getPointN( lines, 0 ); if ( ! point ) return nullptr; GEOSGeometry *noded = GEOSUnion_r( handle, lines, point ); if ( !noded ) { GEOSGeom_destroy_r( handle, point ); return nullptr; } GEOSGeom_destroy_r( handle, point ); return noded; }
Q_NOWARN_UNREACHABLE_POP // Return Nth vertex in GEOSGeometry as a POINT. // May return NULL if the geometry has NO vertexex. static GEOSGeometry *LWGEOM_GEOS_getPointN( const GEOSGeometry *g_in, uint32_t n ) { GEOSContextHandle_t handle = QgsGeos::getGEOSHandler(); uint32_t dims; const GEOSCoordSequence *seq_in = nullptr; GEOSCoordSeq seq_out; double val; uint32_t sz; int gn; GEOSGeometry *ret = nullptr; switch ( GEOSGeomTypeId_r( handle, g_in ) ) { case GEOS_MULTIPOINT: case GEOS_MULTILINESTRING: case GEOS_MULTIPOLYGON: case GEOS_GEOMETRYCOLLECTION: { for ( gn = 0; gn < GEOSGetNumGeometries_r( handle, g_in ); ++gn ) { const GEOSGeometry *g = GEOSGetGeometryN_r( handle, g_in, gn ); ret = LWGEOM_GEOS_getPointN( g, n ); if ( ret ) return ret; } break; } case GEOS_POLYGON: { ret = LWGEOM_GEOS_getPointN( GEOSGetExteriorRing_r( handle, g_in ), n ); if ( ret ) return ret; for ( gn = 0; gn < GEOSGetNumInteriorRings_r( handle, g_in ); ++gn ) { const GEOSGeometry *g = GEOSGetInteriorRingN_r( handle, g_in, gn ); ret = LWGEOM_GEOS_getPointN( g, n ); if ( ret ) return ret; } break; } case GEOS_POINT: case GEOS_LINESTRING: case GEOS_LINEARRING: break; } seq_in = GEOSGeom_getCoordSeq_r( handle, g_in ); if ( ! seq_in ) return nullptr; if ( ! GEOSCoordSeq_getSize_r( handle, seq_in, &sz ) ) return nullptr; if ( ! sz ) return nullptr; if ( ! GEOSCoordSeq_getDimensions_r( handle, seq_in, &dims ) ) return nullptr; seq_out = GEOSCoordSeq_create_r( handle, 1, dims ); if ( ! seq_out ) return nullptr; if ( ! GEOSCoordSeq_getX_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setX_r( handle, seq_out, n, val ) ) return nullptr; if ( ! GEOSCoordSeq_getY_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setY_r( handle, seq_out, n, val ) ) return nullptr; if ( dims > 2 ) { if ( ! GEOSCoordSeq_getZ_r( handle, seq_in, n, &val ) ) return nullptr; if ( ! GEOSCoordSeq_setZ_r( handle, seq_out, n, val ) ) return nullptr; } return GEOSGeom_createPoint_r( handle, seq_out ); }