// 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;
}
Example #2
0
// 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 );
}