static VALUE method_line_string_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) { GEOSContextHandle_t self_context = self_data->geos_context; const GEOSCoordSequence* coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom); if (coord_seq) { char has_z = (char)(RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); unsigned int size; if (GEOSCoordSeq_getSize_r(self_context, coord_seq, &size)) { result = rb_ary_new2(size); double x, y, z; unsigned int i; for (i=0; i<size; ++i) { VALUE point = get_point_from_coordseq(self, coord_seq, i, has_z); if (!NIL_P(point)) { rb_ary_store(result, i, point); } } } } } 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_point_n(VALUE self, VALUE n) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { GEOSContextHandle_t self_context = self_data->geos_context; const GEOSCoordSequence* coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom); if (coord_seq) { char has_z = (char)(RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); int si = NUM2INT(n); if (si >= 0) { unsigned int i = si; unsigned int size; if (GEOSCoordSeq_getSize_r(self_context, coord_seq, &size)) { if (i < size) { unsigned int dims; result = get_point_from_coordseq(self, coord_seq, i, has_z); } } } } } return result; }
static VALUE cmethod_create_line(VALUE module, VALUE factory, VALUE start, VALUE end) { VALUE result = Qnil; RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory); char has_z = (char)(factory_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); VALUE point_type = factory_data->globals->feature_point; GEOSContextHandle_t context = factory_data->geos_context; const GEOSGeometry* start_geom = rgeo_convert_to_geos_geometry(factory, start, point_type); if (start_geom) { const GEOSGeometry* end_geom = rgeo_convert_to_geos_geometry(factory, end, point_type); if (end_geom) { GEOSCoordSequence* coord_seq = GEOSCoordSeq_create_r(context, 2, 3); if (coord_seq) { populate_geom_into_coord_seq(context, start_geom, coord_seq, 0, has_z); populate_geom_into_coord_seq(context, end_geom, coord_seq, 1, has_z); GEOSGeometry* geom = GEOSGeom_createLineString_r(context, coord_seq); if (geom) { result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_line); } } } } return result; }
static VALUE method_polygon_geometry_type(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); if (self_data->geom) { result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_polygon; } return result; }
static VALUE method_set_wkrep_parsers(VALUE self, VALUE wkt_parser, VALUE wkb_parser) { RGeo_FactoryData* self_data; self_data = RGEO_FACTORY_DATA_PTR(self); self_data->wkrep_wkt_parser = wkt_parser; self_data->wkrep_wkb_parser = wkb_parser; return self; }
st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t hash) { ID hash_method; RGeo_Objbase_Hash_Struct hash_struct; hash_method = RGEO_FACTORY_DATA_PTR(factory)->globals->id_hash; hash_struct.seed_hash = hash; hash_struct.h1 = FIX2LONG(rb_funcall(factory, hash_method, 0)); hash_struct.h2 = FIX2LONG(rb_funcall(type_module, hash_method, 0)); return rb_memhash(&hash_struct, sizeof(RGeo_Objbase_Hash_Struct)); }
static VALUE method_geometry_buffer(VALUE self, VALUE distance) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { VALUE factory = self_data->factory; int resolution = NUM2INT(RGEO_FACTORY_DATA_PTR(factory)->buffer_resolution); result = rgeo_wrap_geos_geometry(factory, GEOSBuffer_r(self_data->geos_context, self_geom, rb_num2dbl(distance), resolution), Qnil); } return result; }
static VALUE method_factory_write_for_psych(VALUE self, VALUE obj) { RGeo_FactoryData* self_data; GEOSContextHandle_t self_context; GEOSWKTWriter* wkt_writer; const GEOSGeometry* geom; VALUE result; char* str; size_t size; char has_3d; #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION RGeo_Globals* globals; VALUE wkt_generator; #endif self_data = RGEO_FACTORY_DATA_PTR(self); self_context = self_data->geos_context; has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M; #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION if (has_3d) { globals = self_data->globals; wkt_generator = globals->psych_wkt_generator; if (NIL_P(wkt_generator)) { wkt_generator = rb_funcall( rb_const_get_at(globals->geos_module, rb_intern("Utils")), rb_intern("psych_wkt_generator"), 0); globals->psych_wkt_generator = wkt_generator; } return rb_funcall(wkt_generator, globals->id_generate, 1, obj); } #endif wkt_writer = self_data->psych_wkt_writer; if (!wkt_writer) { wkt_writer = GEOSWKTWriter_create_r(self_context); if (has_3d) { GEOSWKTWriter_setOutputDimension_r(self_context, wkt_writer, 3); } self_data->psych_wkt_writer = wkt_writer; } result = Qnil; if (wkt_writer) { geom = rgeo_get_geos_geometry_safe(obj); if (geom) { str = GEOSWKTWriter_write_r(self_context, wkt_writer, geom); if (str) { result = rb_str_new2(str); GEOSFree_r(self_context, str); } } } return result; }
static VALUE cmethod_create_linear_ring(VALUE module, VALUE factory, VALUE array) { VALUE result = Qnil; GEOSCoordSequence* coord_seq = coord_seq_from_array(factory, array, 1); if (coord_seq) { RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory); GEOSGeometry* geom = GEOSGeom_createLinearRing_r(factory_data->geos_context, coord_seq); if (geom) { result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_linear_ring); } } return result; }
VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass) { VALUE result; GEOSGeometry* clone_geom; result = Qnil; if (geom) { clone_geom = GEOSGeom_clone_r(RGEO_FACTORY_DATA_PTR(factory)->geos_context, geom); if (clone_geom) { result = rgeo_wrap_geos_geometry(factory, clone_geom, klass); } } return result; }
static VALUE method_line_hash(VALUE self) { st_index_t hash; RGeo_GeometryData* self_data; VALUE factory; self_data = RGEO_GEOMETRY_DATA_PTR(self); factory = self_data->factory; hash = rb_hash_start(0); hash = rgeo_geos_objbase_hash(factory, RGEO_FACTORY_DATA_PTR(factory)->globals->feature_line, hash); hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash); return LONG2FIX(rb_hash_end(hash)); }
static VALUE method_geometry_geometry_type(VALUE self) { VALUE result; RGeo_GeometryData* self_data; const GEOSGeometry* self_geom; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); self_geom = self_data->geom; if (self_geom) { result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_geometry; } return result; }
RGEO_BEGIN_C static VALUE method_line_string_geometry_type(VALUE self) { VALUE result; RGeo_GeometryData* self_data; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); if (self_data->geom) { result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_line_string; } return result; }
VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2) { VALUE result; VALUE factory; result = Qnil; if (rb_obj_class(obj1) != rb_obj_class(obj2)) { result = Qfalse; } else { factory = RGEO_GEOMETRY_DATA_PTR(obj1)->factory; result = rb_funcall(factory, RGEO_FACTORY_DATA_PTR(factory)->globals->id_eql, 1, RGEO_GEOMETRY_DATA_PTR(obj2)->factory); } return result; }
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; }
static VALUE method_polygon_interior_ring_n(VALUE self, VALUE n) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { int i = NUM2INT(n); if (i >= 0) { GEOSContextHandle_t self_context = self_data->geos_context; int num = GEOSGetNumInteriorRings_r(self_context, self_geom); if (i < num) { result = rgeo_wrap_geos_geometry_clone(self_data->factory, GEOSGetInteriorRingN_r(self_context, self_geom, i), RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->geos_linear_ring); } } } return result; }
static VALUE get_3d_point(VALUE self, int flag) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { if (RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & flag) { GEOSContextHandle_t self_context = self_data->geos_context; const GEOSCoordSequence* coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom); if (coord_seq) { double val; if (GEOSCoordSeq_getZ_r(self_context, coord_seq, 0, &val)) { result = rb_float_new(val); } } } } return result; }
const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type) { VALUE object; const GEOSGeometry* geom; RGeo_Globals* globals; if (NIL_P(type) && TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func && RGEO_GEOMETRY_DATA_PTR(obj)->factory == factory) { object = obj; } else { globals = RGEO_FACTORY_DATA_PTR(factory)->globals; object = rb_funcall(globals->feature_module, globals->id_cast, 3, obj, factory, type); } geom = NULL; if (!NIL_P(object)) { geom = RGEO_GEOMETRY_DATA_PTR(object)->geom; } return geom; }
VALUE rgeo_create_geos_point(VALUE factory, double x, double y, double z) { VALUE result = Qnil; RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory); GEOSContextHandle_t context = factory_data->geos_context; GEOSCoordSequence* coord_seq = GEOSCoordSeq_create_r(context, 1, 3); if (coord_seq) { if (GEOSCoordSeq_setX_r(context, coord_seq, 0, x)) { if (GEOSCoordSeq_setY_r(context, coord_seq, 0, y)) { if (GEOSCoordSeq_setZ_r(context, coord_seq, 0, z)) { GEOSGeometry* geom = GEOSGeom_createPoint_r(context, coord_seq); if (geom) { result = rgeo_wrap_geos_geometry(factory, geom, factory_data->globals->geos_point); } } } } } return result; }
static VALUE method_polygon_interior_rings(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { GEOSContextHandle_t self_context = self_data->geos_context; int count = GEOSGetNumInteriorRings_r(self_context, self_geom); if (count >= 0) { result = rb_ary_new2(count); VALUE factory = self_data->factory; VALUE linear_ring_class = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->geos_linear_ring; int i; for (i=0; i<count; ++i) { rb_ary_store(result, i, rgeo_wrap_geos_geometry_clone(factory, GEOSGetInteriorRingN_r(self_context, self_geom, i), linear_ring_class)); } } } return result; }
static VALUE method_geometry_as_text(VALUE self) { VALUE result = Qnil; RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); const GEOSGeometry* self_geom = self_data->geom; if (self_geom) { RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory); GEOSWKTWriter* wkt_writer = factory_data->wkt_writer; GEOSContextHandle_t geos_context = self_data->geos_context; if (!wkt_writer) { wkt_writer = GEOSWKTWriter_create_r(geos_context); factory_data->wkt_writer = wkt_writer; } char* str = GEOSWKTWriter_write_r(geos_context, wkt_writer, self_geom); if (str) { result = rb_str_new2(str); GEOSFree_r(geos_context, str); } } return result; }
static VALUE method_geometry_buffer_with_style(VALUE self, VALUE distance, VALUE endCapStyle, VALUE joinStyle, VALUE mitreLimit) { VALUE result; RGeo_GeometryData* self_data; const GEOSGeometry* self_geom; VALUE factory; int resolution; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); self_geom = self_data->geom; if (self_geom) { factory = self_data->factory; result = rgeo_wrap_geos_geometry(factory, GEOSBufferWithStyle_r(self_data->geos_context, self_geom, rb_num2dbl(distance), RGEO_FACTORY_DATA_PTR(factory)->buffer_resolution, endCapStyle, joinStyle, mitreLimit), Qnil); } return result; }
static VALUE method_geometry_as_binary(VALUE self) { VALUE result; RGeo_GeometryData* self_data; const GEOSGeometry* self_geom; RGeo_FactoryData* factory_data; VALUE wkb_generator; GEOSWKBWriter* wkb_writer; GEOSContextHandle_t geos_context; size_t size; char* str; result = Qnil; self_data = RGEO_GEOMETRY_DATA_PTR(self); self_geom = self_data->geom; if (self_geom) { factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory); wkb_generator = factory_data->wkrep_wkb_generator; if (!NIL_P(wkb_generator)) { result = rb_funcall(wkb_generator, factory_data->globals->id_generate, 1, self); } else { wkb_writer = factory_data->wkb_writer; geos_context = self_data->geos_context; if (!wkb_writer) { wkb_writer = GEOSWKBWriter_create_r(geos_context); factory_data->wkb_writer = wkb_writer; } str = (char*)GEOSWKBWriter_write_r(geos_context, wkb_writer, self_geom, &size); if (str) { result = rb_str_new(str, size); GEOSFree_r(geos_context, str); } } } return result; }
static VALUE method_get_coord_sys(VALUE self) { return RGEO_FACTORY_DATA_PTR(self)->coord_sys_obj; }
static VALUE cmethod_create(VALUE module, VALUE factory, VALUE x, VALUE y, VALUE z) { return rgeo_create_geos_point(factory, rb_num2dbl(x), rb_num2dbl(y), RGEO_FACTORY_DATA_PTR(factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M ? rb_num2dbl(z) : 0); }
static VALUE method_point_eql(VALUE self, VALUE rhs) { VALUE result = rgeo_geos_klasses_and_factories_eql(self, rhs); if (RTEST(result)) { RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self); result = rgeo_geos_coordseqs_eql(self_data->geos_context, self_data->geom, RGEO_GEOMETRY_DATA_PTR(rhs)->geom, RGEO_FACTORY_DATA_PTR(self_data->factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M); } return result; }
static VALUE method_get_wkt_generator(VALUE self) { return RGEO_FACTORY_DATA_PTR(self)->wkrep_wkt_generator; }
static VALUE method_get_wkb_parser(VALUE self) { return RGEO_FACTORY_DATA_PTR(self)->wkrep_wkb_parser; }
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; }