Exemplo n.º 1
0
static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
{
  // Clear out any existing value
  RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
  GEOSGeometry* self_geom = self_data->geom;
  if (self_geom) {
    GEOSGeom_destroy_r(self_data->geos_context, self_geom);
    self_data->geom = NULL;
    self_data->geos_context = NULL;
    self_data->factory = Qnil;
    self_data->klasses = Qnil;
  }
  
  // Copy value from orig
  const GEOSGeometry* geom = rgeo_get_geos_geometry_safe(orig);
  if (geom) {
    RGeo_GeometryData* orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
    GEOSContextHandle_t orig_context = orig_data->geos_context;
    GEOSGeometry* clone_geom = GEOSGeom_clone_r(orig_context, geom);
    if (clone_geom) {
      GEOSSetSRID_r(orig_context, clone_geom, GEOSGetSRID_r(orig_context, geom));
      self_data->geom = clone_geom;
      self_data->geos_context = orig_context;
      self_data->factory = orig_data->factory;
      self_data->klasses = orig_data->klasses;
    }
  }
  return self;
}
Exemplo n.º 2
0
static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
{
  RGeo_GeometryData* self_data;
  const GEOSPreparedGeometry* prep;
  const GEOSGeometry* geom;
  RGeo_GeometryData* orig_data;
  GEOSContextHandle_t orig_context;
  GEOSGeometry* clone_geom;
  RGeo_FactoryData* factory_data;

  // Clear out any existing value
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
  if (self_data->geom) {
    GEOSGeom_destroy_r(self_data->geos_context, self_data->geom);
    self_data->geom = NULL;
  }
  prep = self_data->prep;
  if (prep && prep != (GEOSPreparedGeometry*)1 && prep != (GEOSPreparedGeometry*)2) {
    GEOSPreparedGeom_destroy_r(self_data->geos_context, prep);
  }
  self_data->prep = NULL;
  self_data->geos_context = NULL;
  self_data->factory = Qnil;
  self_data->klasses = Qnil;

  // Copy value from orig
  geom = rgeo_get_geos_geometry_safe(orig);
  if (geom) {
    orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
    orig_context = orig_data->geos_context;
    clone_geom = GEOSGeom_clone_r(orig_context, geom);
    if (clone_geom) {
      factory_data = RGEO_FACTORY_DATA_PTR(orig_data->factory);
      GEOSSetSRID_r(orig_context, clone_geom, GEOSGetSRID_r(orig_context, geom));
      self_data->geom = clone_geom;
      self_data->geos_context = orig_context;
      self_data->prep = factory_data && (factory_data->flags & RGEO_FACTORYFLAGS_PREPARE_HEURISTIC != 0) ?
        (GEOSPreparedGeometry*)1 : NULL;
      self_data->factory = orig_data->factory;
      self_data->klasses = orig_data->klasses;
    }
  }
  return self;
}
Exemplo n.º 3
0
VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
{
  VALUE result;
  RGeo_FactoryData* factory_data;
  GEOSContextHandle_t factory_context;
  VALUE klasses;
  RGeo_Globals* globals;
  VALUE inferred_klass;
  char is_collection;
  RGeo_GeometryData* data;

  result = Qnil;
  if (geom || !NIL_P(klass)) {
    factory_data = NIL_P(factory) ? NULL : RGEO_FACTORY_DATA_PTR(factory);
    factory_context = factory_data ? factory_data->geos_context : NULL;
    globals = factory_data ? factory_data->globals : NULL;

    // We don't allow "empty" points, so replace such objects with
    // an empty collection.
    if (geom && factory) {
      if (GEOSGeomTypeId_r(factory_context, geom) == GEOS_POINT && GEOSGetNumCoordinates_r(factory_context, geom) == 0) {
        GEOSGeom_destroy_r(factory_context, geom);
        geom = GEOSGeom_createCollection_r(factory_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
        klass = globals->geos_geometry_collection;
      }
    }

    klasses = Qnil;
    if (TYPE(klass) != T_CLASS) {
      inferred_klass = Qnil;
      is_collection = 0;
      switch (GEOSGeomTypeId_r(factory_context, geom)) {
      case GEOS_POINT:
        inferred_klass = globals->geos_point;
        break;
      case GEOS_LINESTRING:
        inferred_klass = globals->geos_line_string;
        break;
      case GEOS_LINEARRING:
        inferred_klass = globals->geos_linear_ring;
        break;
      case GEOS_POLYGON:
        inferred_klass = globals->geos_polygon;
        break;
      case GEOS_MULTIPOINT:
        inferred_klass = globals->geos_multi_point;
        is_collection = 1;
        break;
      case GEOS_MULTILINESTRING:
        inferred_klass = globals->geos_multi_line_string;
        is_collection = 1;
        break;
      case GEOS_MULTIPOLYGON:
        inferred_klass = globals->geos_multi_polygon;
        is_collection = 1;
        break;
      case GEOS_GEOMETRYCOLLECTION:
        inferred_klass = globals->geos_geometry_collection;
        is_collection = 1;
        break;
      default:
        inferred_klass = globals->geos_geometry;
        break;
      }
      if (TYPE(klass) == T_ARRAY && is_collection) {
        klasses = klass;
      }
      klass = inferred_klass;
    }
    data = ALLOC(RGeo_GeometryData);
    if (data) {
      if (geom) {
        GEOSSetSRID_r(factory_context, geom, factory_data->srid);
      }
      data->geos_context = factory_context;
      data->geom = geom;
      data->prep = factory_data && ((factory_data->flags & RGEO_FACTORYFLAGS_PREPARE_HEURISTIC) != 0) ?
        (GEOSPreparedGeometry*)1 : NULL;
      data->factory = factory;
      data->klasses = klasses;
      result = Data_Wrap_Struct(klass, mark_geometry_func, destroy_geometry_func, data);
    }
  }
  return result;
}
Exemplo n.º 4
0
Q_NOWARN_UNREACHABLE_PUSH
static GEOSGeometry *LWGEOM_GEOS_buildArea( const GEOSGeometry *geom_in, QString &errorMessage )
{
  GEOSContextHandle_t handle = QgsGeos::getGEOSHandler();

  GEOSGeometry *tmp = nullptr;
  GEOSGeometry *shp = nullptr;
  GEOSGeometry *geos_result = nullptr;
  int srid = GEOSGetSRID_r( handle, geom_in );

  GEOSGeometry const *vgeoms[1];
  vgeoms[0] = geom_in;
  try
  {
    geos_result = GEOSPolygonize_r( handle, vgeoms, 1 );
  }
  catch ( GEOSException &e )
  {
    errorMessage = QStringLiteral( "GEOSPolygonize(): %1" ).arg( e.what() );
    return nullptr;
  }

  // We should now have a collection
#if PARANOIA_LEVEL > 0
  if ( GEOSGeometryTypeId_r( handle, geos_result ) != COLLECTIONTYPE )
  {
    GEOSGeom_destroy_r( handle, geos_result );
    errorMessage = "Unexpected return from GEOSpolygonize";
    return nullptr;
  }
#endif

  int ngeoms = GEOSGetNumGeometries_r( handle, geos_result );

  // No geometries in collection, early out
  if ( ngeoms == 0 )
  {
    GEOSSetSRID_r( handle, geos_result, srid );
    return geos_result;
  }

  // Return first geometry if we only have one in collection,
  // to avoid the unnecessary Geometry clone below.
  if ( ngeoms == 1 )
  {
    tmp = ( GEOSGeometry * )GEOSGetGeometryN_r( handle, geos_result, 0 );
    if ( ! tmp )
    {
      GEOSGeom_destroy_r( handle, geos_result );
      return nullptr;
    }
    shp = GEOSGeom_clone_r( handle, tmp );
    GEOSGeom_destroy_r( handle, geos_result ); // only safe after the clone above
    GEOSSetSRID_r( handle, shp, srid );
    return shp;
  }

  /*
   * Polygonizer returns a polygon for each face in the built topology.
   *
   * This means that for any face with holes we'll have other faces
   * representing each hole. We can imagine a parent-child relationship
   * between these faces.
   *
   * In order to maximize the number of visible rings in output we
   * only use those faces which have an even number of parents.
   *
   * Example:
   *
   *   +---------------+
   *   |     L0        |  L0 has no parents
   *   |  +---------+  |
   *   |  |   L1    |  |  L1 is an hole of L0
   *   |  |  +---+  |  |
   *   |  |  |L2 |  |  |  L2 is an hole of L1 (which is an hole of L0)
   *   |  |  |   |  |  |
   *   |  |  +---+  |  |
   *   |  +---------+  |
   *   |               |
   *   +---------------+
   *
   * See http://trac.osgeo.org/postgis/ticket/1806
   *
   */

  // Prepare face structures for later analysis
  Face **geoms = new Face*[ngeoms];
  for ( int i = 0; i < ngeoms; ++i )
    geoms[i] = newFace( GEOSGetGeometryN_r( handle, geos_result, i ) );

  // Find faces representing other faces holes
  findFaceHoles( geoms, ngeoms );

  // Build a MultiPolygon composed only by faces with an
  // even number of ancestors
  tmp = collectFacesWithEvenAncestors( geoms, ngeoms );

  // Cleanup face structures
  for ( int i = 0; i < ngeoms; ++i )
    delFace( geoms[i] );
  delete [] geoms;

  // Faces referenced memory owned by geos_result.
  // It is safe to destroy geos_result after deleting them.
  GEOSGeom_destroy_r( handle, geos_result );

  // Run a single overlay operation to dissolve shared edges
  shp = GEOSUnionCascaded_r( handle, tmp );
  if ( !shp )
  {
    GEOSGeom_destroy_r( handle, tmp );
    return nullptr;
  }

  GEOSGeom_destroy_r( handle, tmp );

  GEOSSetSRID_r( handle, shp, srid );

  return shp;
}