static VALUE method_geometry_envelope(VALUE self) { VALUE result; RGeo_GeometryData* self_data; const GEOSGeometry* self_geom; GEOSContextHandle_t geos_context; GEOSGeometry* envelope; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); self_geom = self_data->geom; if (self_geom) { geos_context = self_data->geos_context; envelope = GEOSEnvelope_r(geos_context, self_geom); // GEOS returns an "empty" point for an empty collection's envelope. // We don't allow that type, so we replace it with an empty collection. if (!envelope || GEOSGeomTypeId_r(geos_context, envelope) == GEOS_POINT && GEOSGetNumCoordinates_r(geos_context, envelope) == 0) { if (envelope) { GEOSGeom_destroy_r(geos_context, envelope); } envelope = GEOSGeom_createCollection_r(geos_context, GEOS_GEOMETRYCOLLECTION, NULL, 0); } result = rgeo_wrap_geos_geometry(self_data->factory, envelope, Qnil); } return result; }
VALUE rgeo_is_geos_line_string_closed(GEOSContextHandle_t context, const GEOSGeometry* geom) { VALUE result; unsigned int n; double x1, x2, y1, y2, z1, z2; const GEOSCoordSequence* coord_seq; result = Qnil; n = GEOSGetNumCoordinates_r(context, geom); if (n > 0) { coord_seq = GEOSGeom_getCoordSeq_r(context, geom); if (GEOSCoordSeq_getX_r(context, coord_seq, 0, &x1)) { if (GEOSCoordSeq_getX_r(context, coord_seq, n-1, &x2)) { if (x1 == x2) { if (GEOSCoordSeq_getY_r(context, coord_seq, 0, &y1)) { if (GEOSCoordSeq_getY_r(context, coord_seq, n-1, &y2)) { result = y1 == y2 ? Qtrue : Qfalse; } } } else { result = Qfalse; } } } } return result; }
static VALUE impl_copy_from(VALUE klass, VALUE factory, VALUE original, char subtype) { VALUE result; const GEOSGeometry* original_geom; GEOSContextHandle_t context; const GEOSCoordSequence* original_coord_seq; GEOSCoordSequence* coord_seq; GEOSGeometry* geom; result = Qnil; original_geom = RGEO_GEOMETRY_DATA_PTR(original)->geom; if (original_geom) { context = RGEO_FACTORY_DATA_PTR(factory)->geos_context; if (subtype == 1 && GEOSGetNumCoordinates_r(context, original_geom) != 2) { original_geom = NULL; } if (original_geom) { original_coord_seq = GEOSGeom_getCoordSeq_r(context, original_geom); if (original_coord_seq) { coord_seq = GEOSCoordSeq_clone_r(context, original_coord_seq); if (coord_seq) { geom = subtype == 2 ? GEOSGeom_createLinearRing_r(context, coord_seq) : GEOSGeom_createLineString_r(context, coord_seq); if (geom) { result = rgeo_wrap_geos_geometry(factory, geom, klass); } } } } } return result; }
static VALUE method_line_string_num_points(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { result = INT2NUM(GEOSGetNumCoordinates_r(self_data->geos_context, self_geom)); } return result; }
static VALUE method_line_string_end_point(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { unsigned int n = GEOSGetNumCoordinates_r(self_data->geos_context, self_geom); if (n > 0) { result = method_line_string_point_n(self, INT2NUM(n-1)); } } return result; }
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; }