rgeo 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,238 @@
1
+ /*
2
+ Factory and utility functions for GEOS wrapper
3
+ */
4
+
5
+ #ifndef RGEO_GEOS_FACTORY_INCLUDED
6
+ #define RGEO_GEOS_FACTORY_INCLUDED
7
+
8
+ #include <ruby.h>
9
+ #include <geos_c.h>
10
+
11
+ RGEO_BEGIN_C
12
+
13
+
14
+ /*
15
+ Per-interpreter globals.
16
+ Most of these are cached references to commonly used classes, modules,
17
+ and symbols so we don't have to do a lot of constant lookups and calls
18
+ to rb_intern.
19
+ */
20
+ typedef struct {
21
+ VALUE feature_module;
22
+ VALUE feature_geometry;
23
+ VALUE feature_point;
24
+ VALUE feature_line_string;
25
+ VALUE feature_linear_ring;
26
+ VALUE feature_line;
27
+ VALUE feature_polygon;
28
+ VALUE feature_geometry_collection;
29
+ VALUE feature_multi_point;
30
+ VALUE feature_multi_line_string;
31
+ VALUE feature_multi_polygon;
32
+ VALUE geos_module;
33
+ VALUE geos_geometry;
34
+ VALUE geos_point;
35
+ VALUE geos_line_string;
36
+ VALUE geos_linear_ring;
37
+ VALUE geos_line;
38
+ VALUE geos_polygon;
39
+ VALUE geos_geometry_collection;
40
+ VALUE geos_multi_point;
41
+ VALUE geos_multi_line_string;
42
+ VALUE geos_multi_polygon;
43
+ ID id_cast;
44
+ ID id_eql;
45
+ ID id_generate;
46
+ ID id_enum_for;
47
+ ID id_hash;
48
+ VALUE sym_force_new;
49
+ VALUE sym_keep_subtype;
50
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
51
+ VALUE psych_wkt_generator;
52
+ VALUE marshal_wkb_generator;
53
+ #endif
54
+ } RGeo_Globals;
55
+
56
+
57
+ /*
58
+ Wrapped structure for Factory objects.
59
+ A factory encapsulates the GEOS context, and GEOS serializer settings.
60
+ It also stores the SRID for all geometries created by this factory,
61
+ and the resolution for buffers created for this factory's geometries.
62
+ Finally, it provides easy access to the globals.
63
+ */
64
+ typedef struct {
65
+ RGeo_Globals* globals;
66
+ GEOSContextHandle_t geos_context;
67
+ GEOSWKTReader* wkt_reader;
68
+ GEOSWKBReader* wkb_reader;
69
+ GEOSWKTWriter* wkt_writer;
70
+ GEOSWKBWriter* wkb_writer;
71
+ VALUE wkrep_wkt_generator;
72
+ VALUE wkrep_wkb_generator;
73
+ VALUE wkrep_wkt_parser;
74
+ VALUE wkrep_wkb_parser;
75
+ GEOSWKTReader* psych_wkt_reader;
76
+ GEOSWKBReader* marshal_wkb_reader;
77
+ GEOSWKTWriter* psych_wkt_writer;
78
+ GEOSWKBWriter* marshal_wkb_writer;
79
+ VALUE proj4_obj;
80
+ VALUE coord_sys_obj;
81
+ int flags;
82
+ int srid;
83
+ int buffer_resolution;
84
+ } RGeo_FactoryData;
85
+
86
+ #define RGEO_FACTORYFLAGS_LENIENT_MULTIPOLYGON 1
87
+ #define RGEO_FACTORYFLAGS_SUPPORTS_Z 2
88
+ #define RGEO_FACTORYFLAGS_SUPPORTS_M 4
89
+ #define RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M 6
90
+ #define RGEO_FACTORYFLAGS_PREPARE_HEURISTIC 8
91
+
92
+
93
+ /*
94
+ Wrapped structure for Geometry objects.
95
+ Includes a handle to the underlying GEOS geometry itself (which could
96
+ be null for an uninitialized geometry).
97
+ It also provides a handle to the factory that created this geometry.
98
+
99
+ The klasses object is used by geometry collections. Its value is
100
+ generally an array of the ruby classes for the colletion's elements,
101
+ so that we can reproduce the exact class for those elements in cases
102
+ where the class cannot be inferred directly from the GEOS type (as
103
+ in Line objects, which have no GEOS type). Any array element, or the
104
+ array itself, could be Qnil, indicating fall back to the default
105
+ inferred from the GEOS type.
106
+
107
+ The GEOS context handle is also included here. Ideally, it would be
108
+ available by following the factory reference and getting it from the
109
+ factory data. However, one use case is in the destroy_geometry_func
110
+ in factory.c, and Rubinius 1.1.1 seems to crash when you try to
111
+ evaluate a DATA_PTR from that function, so we copy the context handle
112
+ here so the destroy_geometry_func can get to it.
113
+ */
114
+ typedef struct {
115
+ GEOSContextHandle_t geos_context;
116
+ GEOSGeometry* geom;
117
+ const GEOSPreparedGeometry* prep;
118
+ VALUE factory;
119
+ VALUE klasses;
120
+ } RGeo_GeometryData;
121
+
122
+
123
+ // Returns the RGeo_FactoryData* given a ruby Factory object
124
+ #define RGEO_FACTORY_DATA_PTR(factory) ((RGeo_FactoryData*)DATA_PTR(factory))
125
+
126
+ // Returns the RGeo_GeometryData* given a ruby Geometry object
127
+ #define RGEO_GEOMETRY_DATA_PTR(geometry) ((RGeo_GeometryData*)DATA_PTR(geometry))
128
+
129
+
130
+ /*
131
+ Initializes the factory module. This should be called first in the
132
+ initialization process.
133
+ */
134
+ RGeo_Globals* rgeo_init_geos_factory();
135
+
136
+ /*
137
+ Given a GEOS geometry handle, wraps it in a ruby Geometry object of the
138
+ given klass. The geometry is then owned by the ruby object, so make sure
139
+ you clone the GEOS object first if something else thinks it owns it.
140
+ You may pass Qnil for the klass to have the klass auto-detected. (But
141
+ note that it cannot auto-detect the Line type because GEOS doesn't
142
+ explicitly represent that type-- it will come out as LineString.)
143
+ You may also pass a ruby Array for the klass if the geometry is a
144
+ collection of some sort. In this case, the array elements should be the
145
+ classes for the elements of the collection.
146
+ Returns Qnil if the wrapping failed for any reason.
147
+ */
148
+ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass);
149
+
150
+ /*
151
+ Same as rgeo_wrap_geos_geometry except that it wraps a clone of the
152
+ given geom, so the original geom doesn't change ownership.
153
+ */
154
+ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass);
155
+
156
+ /*
157
+ Gets the GEOS geometry for a given ruby Geometry object. If the given
158
+ ruby object is not a GEOS geometry implementation, it is converted to a
159
+ GEOS implementation first. You may also optionally cast it to a type,
160
+ specified by an appropriate feature module. Passing Qnil for the type
161
+ disables this auto-cast. The returned GEOS geometry is owned by rgeo,
162
+ and you should not dispose it or take ownership of it yourself.
163
+ */
164
+ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type);
165
+
166
+ /*
167
+ Gets a GEOS geometry for a given ruby Geometry object. You must provide
168
+ a GEOS factory for the geometry; the object is cast to that factory if
169
+ it is not already of it. You may also optionally cast it to a type,
170
+ specified by an appropriate feature module. Passing Qnil for the type
171
+ disables this auto-cast. The returned GEOS geometry is owned by the
172
+ caller-- that is, if the original ruby object is already of the desired
173
+ factory, the returned GEOS geometry is a clone of the original.
174
+
175
+ If the klasses parameter is not NULL, its referent is set to the
176
+ klasses saved in the original ruby Geometry object (if any), or else to
177
+ the class of the converted GEOS object. This is so that you can use the
178
+ result of this function to build a GEOS-backed clone of the original
179
+ geometry, or to include the given geometry in a collection while keeping
180
+ the klasses intact.
181
+ */
182
+ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, VALUE type, VALUE* klasses);
183
+
184
+ /*
185
+ Returns 1 if the given ruby object is a GEOS Geometry implementation,
186
+ or 0 if not.
187
+ */
188
+ char rgeo_is_geos_object(VALUE obj);
189
+
190
+ /*
191
+ Gets the underlying GEOS geometry for a given ruby object. Returns NULL
192
+ if the given ruby object is not a GEOS geometry wrapper.
193
+ */
194
+ const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj);
195
+
196
+ /*
197
+ Compares the coordinate sequences for two given GEOS geometries.
198
+ The two given geometries MUST be of types backed directly by
199
+ coordinate sequences-- i.e. points or line strings.
200
+ Returns Qtrue if the two coordinate sequences are equal, Qfalse
201
+ if they are inequal, or Qnil if an error occurs.
202
+ */
203
+ VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z);
204
+
205
+ /*
206
+ Compares the ruby classes and geometry factories of the two given ruby
207
+ objects. Returns Qtrue if everything is equal (that is, the two objects
208
+ are of the same type and factory), or Qfalse otherwise.
209
+ */
210
+ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2);
211
+
212
+ /*
213
+ A tool for building up hash values.
214
+ You must pass in the context, a geos geometry, and a seed hash.
215
+ Returns an updated hash.
216
+ This call is useful in sequence, and should be bracketed by calls to
217
+ rb_hash_start and rb_hash_end.
218
+ */
219
+ st_index_t rgeo_geos_coordseq_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash);
220
+
221
+ /*
222
+ A tool for building up hash values.
223
+ You must pass in a factory, a feature type module, and a seed hash.
224
+ Returns an updated hash.
225
+ This call is useful in sequence, and should be bracketed by calls to
226
+ rb_hash_start and rb_hash_end.
227
+ */
228
+ st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t hash);
229
+
230
+ /*
231
+ Internal tool for creating simple (FNV-1A 32 bit) hashes.
232
+ */
233
+ st_index_t rgeo_internal_memhash(const void* ptr, long len);
234
+
235
+
236
+ RGEO_END_C
237
+
238
+ #endif
@@ -0,0 +1,1028 @@
1
+ /*
2
+ Geometry base class methods for GEOS wrapper
3
+ */
4
+
5
+
6
+ #include "preface.h"
7
+
8
+ #ifdef RGEO_GEOS_SUPPORTED
9
+
10
+ #include <string.h>
11
+ #include <ruby.h>
12
+ #include <geos_c.h>
13
+
14
+ #include "factory.h"
15
+ #include "geometry.h"
16
+
17
+ RGEO_BEGIN_C
18
+
19
+
20
+ /**** INTERNAL UTILITY FUNCTIONS ****/
21
+
22
+
23
+ // Determine the dimension of the given geometry. Empty collections have dimension -1.
24
+ // Recursively checks collection elemenets.
25
+
26
+ static int compute_dimension(GEOSContextHandle_t context, const GEOSGeometry* geom)
27
+ {
28
+ int result;
29
+ int size;
30
+ int i;
31
+ int dim;
32
+
33
+ result = -1;
34
+ if (geom) {
35
+ switch (GEOSGeomTypeId_r(context, geom)) {
36
+ case GEOS_POINT:
37
+ result = 0;
38
+ break;
39
+ case GEOS_MULTIPOINT:
40
+ if (!GEOSisEmpty_r(context, geom)) {
41
+ result = 0;
42
+ }
43
+ break;
44
+ case GEOS_LINESTRING:
45
+ case GEOS_LINEARRING:
46
+ result = 1;
47
+ break;
48
+ case GEOS_MULTILINESTRING:
49
+ if (!GEOSisEmpty_r(context, geom)) {
50
+ result = 1;
51
+ }
52
+ break;
53
+ case GEOS_POLYGON:
54
+ result = 2;
55
+ break;
56
+ case GEOS_MULTIPOLYGON:
57
+ if (!GEOSisEmpty_r(context, geom)) {
58
+ result = 2;
59
+ }
60
+ break;
61
+ case GEOS_GEOMETRYCOLLECTION:
62
+ size = GEOSGetNumGeometries_r(context, geom);
63
+ for (i=0; i<size; ++i) {
64
+ dim = compute_dimension(context, GEOSGetGeometryN_r(context, geom, i));
65
+ if (dim > result) {
66
+ result = dim;
67
+ }
68
+ }
69
+ break;
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+
75
+
76
+ // Returns a prepared geometry, honoring the preparation policy.
77
+
78
+ static const GEOSPreparedGeometry* rgeo_request_prepared_geometry(RGeo_GeometryData* object_data)
79
+ {
80
+ const GEOSPreparedGeometry* prep;
81
+
82
+ prep = object_data->prep;
83
+ if (prep == (const GEOSPreparedGeometry*)1) {
84
+ object_data->prep = (GEOSPreparedGeometry*)2;
85
+ prep = NULL;
86
+ }
87
+ else if (prep == (const GEOSPreparedGeometry*)2) {
88
+ if (object_data->geom) {
89
+ prep = GEOSPrepare_r(object_data->geos_context, object_data->geom);
90
+ }
91
+ else {
92
+ prep = NULL;
93
+ }
94
+ if (prep) {
95
+ object_data->prep = prep;
96
+ }
97
+ else {
98
+ object_data->prep = (const GEOSPreparedGeometry*)3;
99
+ }
100
+ }
101
+ else if (prep == (const GEOSPreparedGeometry*)3) {
102
+ prep = NULL;
103
+ }
104
+ return prep;
105
+ }
106
+
107
+
108
+ /**** RUBY METHOD DEFINITIONS ****/
109
+
110
+
111
+ static VALUE method_geometry_initialized_p(VALUE self)
112
+ {
113
+ return RGEO_GEOMETRY_DATA_PTR(self)->geom ? Qtrue : Qfalse;
114
+ }
115
+
116
+
117
+ static VALUE method_geometry_factory(VALUE self)
118
+ {
119
+ return RGEO_GEOMETRY_DATA_PTR(self)->factory;
120
+ }
121
+
122
+
123
+ static VALUE method_geometry_set_factory(VALUE self, VALUE factory)
124
+ {
125
+ RGEO_GEOMETRY_DATA_PTR(self)->factory = factory;
126
+ return factory;
127
+ }
128
+
129
+
130
+ static VALUE method_geometry_prepared_p(VALUE self)
131
+ {
132
+ const GEOSPreparedGeometry* prep;
133
+
134
+ prep = RGEO_GEOMETRY_DATA_PTR(self)->prep;
135
+ return (prep && prep != (const GEOSPreparedGeometry*)1 &&
136
+ prep != (const GEOSPreparedGeometry*)2 &&
137
+ prep != (GEOSPreparedGeometry*)3) ? Qtrue : Qfalse;
138
+ }
139
+
140
+
141
+ static VALUE method_geometry_prepare(VALUE self)
142
+ {
143
+ RGeo_GeometryData* self_data;
144
+ const GEOSPreparedGeometry* prep;
145
+
146
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
147
+ if (self_data->geom) {
148
+ prep = self_data->prep;
149
+ if (!prep || prep == (const GEOSPreparedGeometry*)1 || prep == (const GEOSPreparedGeometry*)2) {
150
+ prep = GEOSPrepare_r(self_data->geos_context, self_data->geom);
151
+ if (prep) {
152
+ self_data->prep = prep;
153
+ }
154
+ else {
155
+ self_data->prep = (const GEOSPreparedGeometry*)3;
156
+ }
157
+ }
158
+ }
159
+ return self;
160
+ }
161
+
162
+
163
+ static VALUE method_geometry_dimension(VALUE self)
164
+ {
165
+ VALUE result;
166
+ RGeo_GeometryData* self_data;
167
+ const GEOSGeometry* self_geom;
168
+
169
+ result = Qnil;
170
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
171
+ self_geom = self_data->geom;
172
+ if (self_geom) {
173
+ result = INT2NUM(compute_dimension(self_data->geos_context, self_geom));
174
+ }
175
+ return result;
176
+ }
177
+
178
+
179
+ static VALUE method_geometry_geometry_type(VALUE self)
180
+ {
181
+ VALUE result;
182
+ RGeo_GeometryData* self_data;
183
+ const GEOSGeometry* self_geom;
184
+
185
+ result = Qnil;
186
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
187
+ self_geom = self_data->geom;
188
+ if (self_geom) {
189
+ result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_geometry;
190
+ }
191
+ return result;
192
+ }
193
+
194
+
195
+ static VALUE method_geometry_srid(VALUE self)
196
+ {
197
+ VALUE result;
198
+ RGeo_GeometryData* self_data;
199
+ const GEOSGeometry* self_geom;
200
+
201
+ result = Qnil;
202
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
203
+ self_geom = self_data->geom;
204
+ if (self_geom) {
205
+ result = INT2NUM(GEOSGetSRID_r(self_data->geos_context, self_geom));
206
+ }
207
+ return result;
208
+ }
209
+
210
+
211
+ static VALUE method_geometry_envelope(VALUE self)
212
+ {
213
+ VALUE result;
214
+ RGeo_GeometryData* self_data;
215
+ const GEOSGeometry* self_geom;
216
+ GEOSContextHandle_t geos_context;
217
+ GEOSGeometry* envelope;
218
+
219
+ result = Qnil;
220
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
221
+ self_geom = self_data->geom;
222
+ if (self_geom) {
223
+ geos_context = self_data->geos_context;
224
+ envelope = GEOSEnvelope_r(geos_context, self_geom);
225
+ if (!envelope) {
226
+ envelope = GEOSGeom_createCollection_r(geos_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
227
+ }
228
+ result = rgeo_wrap_geos_geometry(self_data->factory, envelope, Qnil);
229
+ }
230
+ return result;
231
+ }
232
+
233
+
234
+ static VALUE method_geometry_boundary(VALUE self)
235
+ {
236
+ VALUE result;
237
+ RGeo_GeometryData* self_data;
238
+ const GEOSGeometry* self_geom;
239
+ GEOSContextHandle_t geos_context;
240
+ GEOSGeometry* boundary;
241
+
242
+ result = Qnil;
243
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
244
+ self_geom = self_data->geom;
245
+ if (self_geom) {
246
+ geos_context = self_data->geos_context;
247
+ boundary = GEOSBoundary_r(geos_context, self_geom);
248
+ if (boundary) {
249
+ result = rgeo_wrap_geos_geometry(self_data->factory, boundary, Qnil);
250
+ }
251
+ }
252
+ return result;
253
+ }
254
+
255
+
256
+ static VALUE method_geometry_as_text(VALUE self)
257
+ {
258
+ VALUE result;
259
+ RGeo_GeometryData* self_data;
260
+ const GEOSGeometry* self_geom;
261
+ RGeo_FactoryData* factory_data;
262
+ VALUE wkt_generator;
263
+ GEOSWKTWriter* wkt_writer;
264
+ GEOSContextHandle_t geos_context;
265
+ char* str;
266
+
267
+ result = Qnil;
268
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
269
+ self_geom = self_data->geom;
270
+ if (self_geom) {
271
+ factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory);
272
+ wkt_generator = factory_data->wkrep_wkt_generator;
273
+ if (!NIL_P(wkt_generator)) {
274
+ result = rb_funcall(wkt_generator, factory_data->globals->id_generate, 1, self);
275
+ }
276
+ else {
277
+ wkt_writer = factory_data->wkt_writer;
278
+ geos_context = self_data->geos_context;
279
+ if (!wkt_writer) {
280
+ wkt_writer = GEOSWKTWriter_create_r(geos_context);
281
+ factory_data->wkt_writer = wkt_writer;
282
+ }
283
+ str = GEOSWKTWriter_write_r(geos_context, wkt_writer, self_geom);
284
+ if (str) {
285
+ result = rb_str_new2(str);
286
+ GEOSFree_r(geos_context, str);
287
+ }
288
+ }
289
+ }
290
+ return result;
291
+ }
292
+
293
+
294
+ static VALUE method_geometry_as_binary(VALUE self)
295
+ {
296
+ VALUE result;
297
+ RGeo_GeometryData* self_data;
298
+ const GEOSGeometry* self_geom;
299
+ RGeo_FactoryData* factory_data;
300
+ VALUE wkb_generator;
301
+ GEOSWKBWriter* wkb_writer;
302
+ GEOSContextHandle_t geos_context;
303
+ size_t size;
304
+ char* str;
305
+
306
+ result = Qnil;
307
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
308
+ self_geom = self_data->geom;
309
+ if (self_geom) {
310
+ factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory);
311
+ wkb_generator = factory_data->wkrep_wkb_generator;
312
+ if (!NIL_P(wkb_generator)) {
313
+ result = rb_funcall(wkb_generator, factory_data->globals->id_generate, 1, self);
314
+ }
315
+ else {
316
+ wkb_writer = factory_data->wkb_writer;
317
+ geos_context = self_data->geos_context;
318
+ if (!wkb_writer) {
319
+ wkb_writer = GEOSWKBWriter_create_r(geos_context);
320
+ factory_data->wkb_writer = wkb_writer;
321
+ }
322
+ str = (char*)GEOSWKBWriter_write_r(geos_context, wkb_writer, self_geom, &size);
323
+ if (str) {
324
+ result = rb_str_new(str, size);
325
+ GEOSFree_r(geos_context, str);
326
+ }
327
+ }
328
+ }
329
+ return result;
330
+ }
331
+
332
+
333
+ static VALUE method_geometry_is_empty(VALUE self)
334
+ {
335
+ VALUE result;
336
+ RGeo_GeometryData* self_data;
337
+ const GEOSGeometry* self_geom;
338
+ char val;
339
+
340
+ result = Qnil;
341
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
342
+ self_geom = self_data->geom;
343
+ if (self_geom) {
344
+ val = GEOSisEmpty_r(self_data->geos_context, self_geom);
345
+ if (val == 0) {
346
+ result = Qfalse;
347
+ }
348
+ else if (val == 1) {
349
+ result = Qtrue;
350
+ }
351
+ }
352
+ return result;
353
+ }
354
+
355
+
356
+ static VALUE method_geometry_is_simple(VALUE self)
357
+ {
358
+ VALUE result;
359
+ RGeo_GeometryData* self_data;
360
+ const GEOSGeometry* self_geom;
361
+ char val;
362
+
363
+ result = Qnil;
364
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
365
+ self_geom = self_data->geom;
366
+ if (self_geom) {
367
+ val = GEOSisSimple_r(self_data->geos_context, self_geom);
368
+ if (val == 0) {
369
+ result = Qfalse;
370
+ }
371
+ else if (val == 1) {
372
+ result = Qtrue;
373
+ }
374
+ }
375
+ return result;
376
+ }
377
+
378
+
379
+ static VALUE method_geometry_equals(VALUE self, VALUE rhs)
380
+ {
381
+ VALUE result;
382
+ RGeo_GeometryData* self_data;
383
+ const GEOSGeometry* self_geom;
384
+ const GEOSGeometry* rhs_geom;
385
+ GEOSContextHandle_t self_context;
386
+ char val;
387
+
388
+ result = Qnil;
389
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
390
+ self_geom = self_data->geom;
391
+ if (self_geom) {
392
+ rhs_geom = rgeo_get_geos_geometry_safe(rhs);
393
+ if (rhs_geom) {
394
+ self_context = self_data->geos_context;
395
+ // GEOS has a bug where empty geometries are not spatially equal
396
+ // to each other. Work around this case first.
397
+ if (GEOSisEmpty_r(self_context, self_geom) == 1 &&
398
+ GEOSisEmpty_r(RGEO_GEOMETRY_DATA_PTR(rhs)->geos_context, rhs_geom) == 1) {
399
+ result = Qtrue;
400
+ }
401
+ else {
402
+ val = GEOSEquals_r(self_context, self_geom, rhs_geom);
403
+ if (val == 0) {
404
+ result = Qfalse;
405
+ }
406
+ else if (val == 1) {
407
+ result = Qtrue;
408
+ }
409
+ }
410
+ }
411
+ }
412
+ return result;
413
+ }
414
+
415
+
416
+ static VALUE method_geometry_eql(VALUE self, VALUE rhs)
417
+ {
418
+ // This should be overridden by the subclass.
419
+ return self == rhs ? Qtrue : Qfalse;
420
+ }
421
+
422
+
423
+ static VALUE method_geometry_disjoint(VALUE self, VALUE rhs)
424
+ {
425
+ VALUE result;
426
+ RGeo_GeometryData* self_data;
427
+ const GEOSGeometry* self_geom;
428
+ const GEOSGeometry* rhs_geom;
429
+ char val;
430
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
431
+ const GEOSPreparedGeometry* prep;
432
+ #endif
433
+
434
+ result = Qnil;
435
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
436
+ self_geom = self_data->geom;
437
+ if (self_geom) {
438
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
439
+ if (rhs_geom) {
440
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
441
+ prep = rgeo_request_prepared_geometry(self_data);
442
+ if (prep)
443
+ val = GEOSPreparedDisjoint_r(self_data->geos_context, prep, rhs_geom);
444
+ else
445
+ #endif
446
+ val = GEOSDisjoint_r(self_data->geos_context, self_geom, rhs_geom);
447
+ if (val == 0) {
448
+ result = Qfalse;
449
+ }
450
+ else if (val == 1) {
451
+ result = Qtrue;
452
+ }
453
+ }
454
+ }
455
+ return result;
456
+ }
457
+
458
+
459
+ static VALUE method_geometry_intersects(VALUE self, VALUE rhs)
460
+ {
461
+ VALUE result;
462
+ RGeo_GeometryData* self_data;
463
+ const GEOSGeometry* self_geom;
464
+ const GEOSGeometry* rhs_geom;
465
+ char val;
466
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
467
+ const GEOSPreparedGeometry* prep;
468
+ #endif
469
+
470
+ result = Qnil;
471
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
472
+ self_geom = self_data->geom;
473
+ if (self_geom) {
474
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
475
+ if (rhs_geom) {
476
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
477
+ prep = rgeo_request_prepared_geometry(self_data);
478
+ if (prep)
479
+ val = GEOSPreparedIntersects_r(self_data->geos_context, prep, rhs_geom);
480
+ else
481
+ #endif
482
+ val = GEOSIntersects_r(self_data->geos_context, self_geom, rhs_geom);
483
+ if (val == 0) {
484
+ result = Qfalse;
485
+ }
486
+ else if (val == 1) {
487
+ result = Qtrue;
488
+ }
489
+ }
490
+ }
491
+ return result;
492
+ }
493
+
494
+
495
+ static VALUE method_geometry_touches(VALUE self, VALUE rhs)
496
+ {
497
+ VALUE result;
498
+ RGeo_GeometryData* self_data;
499
+ const GEOSGeometry* self_geom;
500
+ const GEOSGeometry* rhs_geom;
501
+ char val;
502
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
503
+ const GEOSPreparedGeometry* prep;
504
+ #endif
505
+
506
+ result = Qnil;
507
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
508
+ self_geom = self_data->geom;
509
+ if (self_geom) {
510
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
511
+ if (rhs_geom) {
512
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
513
+ prep = rgeo_request_prepared_geometry(self_data);
514
+ if (prep)
515
+ val = GEOSPreparedTouches_r(self_data->geos_context, prep, rhs_geom);
516
+ else
517
+ #endif
518
+ val = GEOSTouches_r(self_data->geos_context, self_geom, rhs_geom);
519
+ if (val == 0) {
520
+ result = Qfalse;
521
+ }
522
+ else if (val == 1) {
523
+ result = Qtrue;
524
+ }
525
+ }
526
+ }
527
+ return result;
528
+ }
529
+
530
+
531
+ static VALUE method_geometry_crosses(VALUE self, VALUE rhs)
532
+ {
533
+ VALUE result;
534
+ RGeo_GeometryData* self_data;
535
+ const GEOSGeometry* self_geom;
536
+ const GEOSGeometry* rhs_geom;
537
+ char val;
538
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
539
+ const GEOSPreparedGeometry* prep;
540
+ #endif
541
+
542
+ result = Qnil;
543
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
544
+ self_geom = self_data->geom;
545
+ if (self_geom) {
546
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
547
+ if (rhs_geom) {
548
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
549
+ prep = rgeo_request_prepared_geometry(self_data);
550
+ if (prep)
551
+ val = GEOSPreparedCrosses_r(self_data->geos_context, prep, rhs_geom);
552
+ else
553
+ #endif
554
+ val = GEOSCrosses_r(self_data->geos_context, self_geom, rhs_geom);
555
+ if (val == 0) {
556
+ result = Qfalse;
557
+ }
558
+ else if (val == 1) {
559
+ result = Qtrue;
560
+ }
561
+ }
562
+ }
563
+ return result;
564
+ }
565
+
566
+
567
+ static VALUE method_geometry_within(VALUE self, VALUE rhs)
568
+ {
569
+ VALUE result;
570
+ RGeo_GeometryData* self_data;
571
+ const GEOSGeometry* self_geom;
572
+ const GEOSGeometry* rhs_geom;
573
+ char val;
574
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
575
+ const GEOSPreparedGeometry* prep;
576
+ #endif
577
+
578
+ result = Qnil;
579
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
580
+ self_geom = self_data->geom;
581
+ if (self_geom) {
582
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
583
+ if (rhs_geom) {
584
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
585
+ prep = rgeo_request_prepared_geometry(self_data);
586
+ if (prep)
587
+ val = GEOSPreparedWithin_r(self_data->geos_context, prep, rhs_geom);
588
+ else
589
+ #endif
590
+ val = GEOSWithin_r(self_data->geos_context, self_geom, rhs_geom);
591
+ if (val == 0) {
592
+ result = Qfalse;
593
+ }
594
+ else if (val == 1) {
595
+ result = Qtrue;
596
+ }
597
+ }
598
+ }
599
+ return result;
600
+ }
601
+
602
+
603
+ static VALUE method_geometry_contains(VALUE self, VALUE rhs)
604
+ {
605
+ VALUE result;
606
+ RGeo_GeometryData* self_data;
607
+ const GEOSGeometry* self_geom;
608
+ const GEOSGeometry* rhs_geom;
609
+ char val;
610
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
611
+ const GEOSPreparedGeometry* prep;
612
+ #endif
613
+
614
+ result = Qnil;
615
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
616
+ self_geom = self_data->geom;
617
+ if (self_geom) {
618
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
619
+ if (rhs_geom) {
620
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED1
621
+ prep = rgeo_request_prepared_geometry(self_data);
622
+ if (prep)
623
+ val = GEOSPreparedContains_r(self_data->geos_context, prep, rhs_geom);
624
+ else
625
+ #endif
626
+ val = GEOSContains_r(self_data->geos_context, self_geom, rhs_geom);
627
+ if (val == 0) {
628
+ result = Qfalse;
629
+ }
630
+ else if (val == 1) {
631
+ result = Qtrue;
632
+ }
633
+ }
634
+ }
635
+ return result;
636
+ }
637
+
638
+
639
+ static VALUE method_geometry_overlaps(VALUE self, VALUE rhs)
640
+ {
641
+ VALUE result;
642
+ RGeo_GeometryData* self_data;
643
+ const GEOSGeometry* self_geom;
644
+ const GEOSGeometry* rhs_geom;
645
+ char val;
646
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
647
+ const GEOSPreparedGeometry* prep;
648
+ #endif
649
+
650
+ result = Qnil;
651
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
652
+ self_geom = self_data->geom;
653
+ if (self_geom) {
654
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
655
+ if (rhs_geom) {
656
+ #ifdef RGEO_GEOS_SUPPORTS_PREPARED2
657
+ prep = rgeo_request_prepared_geometry(self_data);
658
+ if (prep)
659
+ val = GEOSPreparedOverlaps_r(self_data->geos_context, prep, rhs_geom);
660
+ else
661
+ #endif
662
+ val = GEOSOverlaps_r(self_data->geos_context, self_geom, rhs_geom);
663
+ if (val == 0) {
664
+ result = Qfalse;
665
+ }
666
+ else if (val == 1) {
667
+ result = Qtrue;
668
+ }
669
+ }
670
+ }
671
+ return result;
672
+ }
673
+
674
+
675
+ static VALUE method_geometry_relate(VALUE self, VALUE rhs, VALUE pattern)
676
+ {
677
+ VALUE result;
678
+ RGeo_GeometryData* self_data;
679
+ const GEOSGeometry* self_geom;
680
+ const GEOSGeometry* rhs_geom;
681
+ char val;
682
+
683
+ result = Qnil;
684
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
685
+ self_geom = self_data->geom;
686
+ if (self_geom) {
687
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
688
+ if (rhs_geom) {
689
+ val = GEOSRelatePattern_r(self_data->geos_context, self_geom, rhs_geom, StringValuePtr(pattern));
690
+ if (val == 0) {
691
+ result = Qfalse;
692
+ }
693
+ else if (val == 1) {
694
+ result = Qtrue;
695
+ }
696
+ }
697
+ }
698
+ return result;
699
+ }
700
+
701
+
702
+ static VALUE method_geometry_distance(VALUE self, VALUE rhs)
703
+ {
704
+ VALUE result;
705
+ RGeo_GeometryData* self_data;
706
+ const GEOSGeometry* self_geom;
707
+ const GEOSGeometry* rhs_geom;
708
+ double dist;
709
+
710
+ result = Qnil;
711
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
712
+ self_geom = self_data->geom;
713
+ if (self_geom) {
714
+ rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
715
+ if (rhs_geom) {
716
+ if (GEOSDistance_r(self_data->geos_context, self_geom, rhs_geom, &dist)) {
717
+ result = rb_float_new(dist);
718
+ }
719
+ }
720
+ }
721
+ return result;
722
+ }
723
+
724
+
725
+ static VALUE method_geometry_buffer(VALUE self, VALUE distance)
726
+ {
727
+ VALUE result;
728
+ RGeo_GeometryData* self_data;
729
+ const GEOSGeometry* self_geom;
730
+ VALUE factory;
731
+ int resolution;
732
+
733
+ result = Qnil;
734
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
735
+ self_geom = self_data->geom;
736
+ if (self_geom) {
737
+ factory = self_data->factory;
738
+ result = rgeo_wrap_geos_geometry(factory, GEOSBuffer_r(self_data->geos_context, self_geom,
739
+ rb_num2dbl(distance), RGEO_FACTORY_DATA_PTR(factory)->buffer_resolution), Qnil);
740
+ }
741
+ return result;
742
+ }
743
+
744
+ static VALUE method_geometry_buffer_with_style(VALUE self, VALUE distance, VALUE endCapStyle, VALUE joinStyle, VALUE mitreLimit)
745
+ {
746
+ VALUE result;
747
+ RGeo_GeometryData* self_data;
748
+ const GEOSGeometry* self_geom;
749
+ VALUE factory;
750
+ int resolution;
751
+
752
+ result = Qnil;
753
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
754
+ self_geom = self_data->geom;
755
+ if (self_geom) {
756
+ factory = self_data->factory;
757
+ result = rgeo_wrap_geos_geometry(factory,
758
+ GEOSBufferWithStyle_r(self_data->geos_context, self_geom,
759
+ rb_num2dbl(distance),
760
+ RGEO_FACTORY_DATA_PTR(factory)->buffer_resolution,
761
+ endCapStyle, joinStyle, mitreLimit),
762
+ Qnil);
763
+ }
764
+ return result;
765
+ }
766
+
767
+ static VALUE method_geometry_simplify(VALUE self, VALUE tolerance)
768
+ {
769
+ VALUE result;
770
+ RGeo_GeometryData* self_data;
771
+ const GEOSGeometry* self_geom;
772
+ VALUE factory;
773
+
774
+ result = Qnil;
775
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
776
+ self_geom = self_data->geom;
777
+ if (self_geom) {
778
+ factory = self_data->factory;
779
+ result = rgeo_wrap_geos_geometry(factory, GEOSSimplify_r(self_data->geos_context, self_geom,
780
+ rb_num2dbl(tolerance)), Qnil);
781
+ }
782
+ return result;
783
+ }
784
+
785
+
786
+ static VALUE method_geometry_convex_hull(VALUE self)
787
+ {
788
+ VALUE result;
789
+ RGeo_GeometryData* self_data;
790
+ const GEOSGeometry* self_geom;
791
+
792
+ result = Qnil;
793
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
794
+ self_geom = self_data->geom;
795
+ if (self_geom) {
796
+ result = rgeo_wrap_geos_geometry(self_data->factory, GEOSConvexHull_r(self_data->geos_context, self_geom), Qnil);
797
+ }
798
+ return result;
799
+ }
800
+
801
+
802
+ static VALUE method_geometry_intersection(VALUE self, VALUE rhs)
803
+ {
804
+ VALUE result;
805
+ RGeo_GeometryData* self_data;
806
+ const GEOSGeometry* self_geom;
807
+ VALUE factory;
808
+ const GEOSGeometry* rhs_geom;
809
+
810
+ result = Qnil;
811
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
812
+ self_geom = self_data->geom;
813
+ if (self_geom) {
814
+ factory = self_data->factory;
815
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
816
+ if (rhs_geom) {
817
+ result = rgeo_wrap_geos_geometry(factory, GEOSIntersection_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
818
+ }
819
+ }
820
+ return result;
821
+ }
822
+
823
+
824
+ static VALUE method_geometry_union(VALUE self, VALUE rhs)
825
+ {
826
+ VALUE result;
827
+ RGeo_GeometryData* self_data;
828
+ const GEOSGeometry* self_geom;
829
+ VALUE factory;
830
+ const GEOSGeometry* rhs_geom;
831
+
832
+ result = Qnil;
833
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
834
+ self_geom = self_data->geom;
835
+ if (self_geom) {
836
+ factory = self_data->factory;
837
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
838
+ if (rhs_geom) {
839
+ result = rgeo_wrap_geos_geometry(factory, GEOSUnion_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
840
+ }
841
+ }
842
+ return result;
843
+ }
844
+
845
+
846
+ static VALUE method_geometry_difference(VALUE self, VALUE rhs)
847
+ {
848
+ VALUE result;
849
+ RGeo_GeometryData* self_data;
850
+ const GEOSGeometry* self_geom;
851
+ VALUE factory;
852
+ const GEOSGeometry* rhs_geom;
853
+
854
+ result = Qnil;
855
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
856
+ self_geom = self_data->geom;
857
+ if (self_geom) {
858
+ factory = self_data->factory;
859
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
860
+ if (rhs_geom) {
861
+ result = rgeo_wrap_geos_geometry(factory, GEOSDifference_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
862
+ }
863
+ }
864
+ return result;
865
+ }
866
+
867
+
868
+ static VALUE method_geometry_sym_difference(VALUE self, VALUE rhs)
869
+ {
870
+ VALUE result;
871
+ RGeo_GeometryData* self_data;
872
+ const GEOSGeometry* self_geom;
873
+ VALUE factory;
874
+ const GEOSGeometry* rhs_geom;
875
+
876
+ result = Qnil;
877
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
878
+ self_geom = self_data->geom;
879
+ if (self_geom) {
880
+ factory = self_data->factory;
881
+ rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
882
+ if (rhs_geom) {
883
+ result = rgeo_wrap_geos_geometry(factory, GEOSSymDifference_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
884
+ }
885
+ }
886
+ return result;
887
+ }
888
+
889
+
890
+ static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
891
+ {
892
+ RGeo_GeometryData* self_data;
893
+ const GEOSPreparedGeometry* prep;
894
+ const GEOSGeometry* geom;
895
+ RGeo_GeometryData* orig_data;
896
+ GEOSContextHandle_t orig_context;
897
+ GEOSGeometry* clone_geom;
898
+ RGeo_FactoryData* factory_data;
899
+
900
+ // Clear out any existing value
901
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
902
+ if (self_data->geom) {
903
+ GEOSGeom_destroy_r(self_data->geos_context, self_data->geom);
904
+ self_data->geom = NULL;
905
+ }
906
+ prep = self_data->prep;
907
+ if (prep && prep != (GEOSPreparedGeometry*)1 && prep != (GEOSPreparedGeometry*)2) {
908
+ GEOSPreparedGeom_destroy_r(self_data->geos_context, prep);
909
+ }
910
+ self_data->prep = NULL;
911
+ self_data->geos_context = NULL;
912
+ self_data->factory = Qnil;
913
+ self_data->klasses = Qnil;
914
+
915
+ // Copy value from orig
916
+ geom = rgeo_get_geos_geometry_safe(orig);
917
+ if (geom) {
918
+ orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
919
+ orig_context = orig_data->geos_context;
920
+ clone_geom = GEOSGeom_clone_r(orig_context, geom);
921
+ if (clone_geom) {
922
+ factory_data = RGEO_FACTORY_DATA_PTR(orig_data->factory);
923
+ GEOSSetSRID_r(orig_context, clone_geom, GEOSGetSRID_r(orig_context, geom));
924
+ self_data->geom = clone_geom;
925
+ self_data->geos_context = orig_context;
926
+ self_data->prep = factory_data && ((factory_data->flags & RGEO_FACTORYFLAGS_PREPARE_HEURISTIC) != 0) ?
927
+ (GEOSPreparedGeometry*)1 : NULL;
928
+ self_data->factory = orig_data->factory;
929
+ self_data->klasses = orig_data->klasses;
930
+ }
931
+ }
932
+ return self;
933
+ }
934
+
935
+
936
+ static VALUE method_geometry_steal(VALUE self, VALUE orig)
937
+ {
938
+ RGeo_GeometryData* self_data;
939
+ const GEOSPreparedGeometry* prep;
940
+ const GEOSGeometry* geom;
941
+ RGeo_GeometryData* orig_data;
942
+
943
+ geom = rgeo_get_geos_geometry_safe(orig);
944
+ if (geom) {
945
+ // Clear out any existing value
946
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
947
+ if (self_data->geom) {
948
+ GEOSGeom_destroy_r(self_data->geos_context, self_data->geom);
949
+ }
950
+ prep = self_data->prep;
951
+ if (prep && prep != (GEOSPreparedGeometry*)1 && prep != (GEOSPreparedGeometry*)2) {
952
+ GEOSPreparedGeom_destroy_r(self_data->geos_context, prep);
953
+ }
954
+
955
+ // Steal value from orig
956
+ orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
957
+ self_data->geom = orig_data->geom;
958
+ self_data->prep = orig_data->prep;
959
+ self_data->geos_context = orig_data->geos_context;
960
+ self_data->factory = orig_data->factory;
961
+ self_data->klasses = orig_data->klasses;
962
+
963
+ // Clear out orig
964
+ orig_data->geom = NULL;
965
+ orig_data->prep = NULL;
966
+ orig_data->geos_context = NULL;
967
+ orig_data->factory = Qnil;
968
+ orig_data->klasses = Qnil;
969
+ }
970
+ return self;
971
+ }
972
+
973
+
974
+ /**** INITIALIZATION FUNCTION ****/
975
+
976
+
977
+ void rgeo_init_geos_geometry(RGeo_Globals* globals)
978
+ {
979
+ VALUE geos_geometry_methods;
980
+
981
+ geos_geometry_methods = rb_define_module_under(globals->geos_module, "CAPIGeometryMethods");
982
+
983
+ rb_define_method(geos_geometry_methods, "_set_factory", method_geometry_set_factory, 1);
984
+ rb_define_method(geos_geometry_methods, "initialize_copy", method_geometry_initialize_copy, 1);
985
+ rb_define_method(geos_geometry_methods, "_steal", method_geometry_steal, 1);
986
+ rb_define_method(geos_geometry_methods, "initialized?", method_geometry_initialized_p, 0);
987
+ rb_define_method(geos_geometry_methods, "factory", method_geometry_factory, 0);
988
+ rb_define_method(geos_geometry_methods, "prepared?", method_geometry_prepared_p, 0);
989
+ rb_define_method(geos_geometry_methods, "prepare!", method_geometry_prepare, 0);
990
+ rb_define_method(geos_geometry_methods, "dimension", method_geometry_dimension, 0);
991
+ rb_define_method(geos_geometry_methods, "geometry_type", method_geometry_geometry_type, 0);
992
+ rb_define_method(geos_geometry_methods, "srid", method_geometry_srid, 0);
993
+ rb_define_method(geos_geometry_methods, "envelope", method_geometry_envelope, 0);
994
+ rb_define_method(geos_geometry_methods, "boundary", method_geometry_boundary, 0);
995
+ rb_define_method(geos_geometry_methods, "_as_text", method_geometry_as_text, 0);
996
+ rb_define_method(geos_geometry_methods, "as_binary", method_geometry_as_binary, 0);
997
+ rb_define_method(geos_geometry_methods, "is_empty?", method_geometry_is_empty, 0);
998
+ rb_define_method(geos_geometry_methods, "is_simple?", method_geometry_is_simple, 0);
999
+ rb_define_method(geos_geometry_methods, "equals?", method_geometry_equals, 1);
1000
+ rb_define_method(geos_geometry_methods, "==", method_geometry_equals, 1);
1001
+ rb_define_method(geos_geometry_methods, "rep_equals?", method_geometry_eql, 1);
1002
+ rb_define_method(geos_geometry_methods, "eql?", method_geometry_eql, 1);
1003
+ rb_define_method(geos_geometry_methods, "disjoint?", method_geometry_disjoint, 1);
1004
+ rb_define_method(geos_geometry_methods, "intersects?", method_geometry_intersects, 1);
1005
+ rb_define_method(geos_geometry_methods, "touches?", method_geometry_touches, 1);
1006
+ rb_define_method(geos_geometry_methods, "crosses?", method_geometry_crosses, 1);
1007
+ rb_define_method(geos_geometry_methods, "within?", method_geometry_within, 1);
1008
+ rb_define_method(geos_geometry_methods, "contains?", method_geometry_contains, 1);
1009
+ rb_define_method(geos_geometry_methods, "overlaps?", method_geometry_overlaps, 1);
1010
+ rb_define_method(geos_geometry_methods, "relate?", method_geometry_relate, 2);
1011
+ rb_define_method(geos_geometry_methods, "distance", method_geometry_distance, 1);
1012
+ rb_define_method(geos_geometry_methods, "buffer", method_geometry_buffer, 1);
1013
+ rb_define_method(geos_geometry_methods, "buffer_with_style", method_geometry_buffer_with_style, 4);
1014
+ rb_define_method(geos_geometry_methods, "simplify", method_geometry_simplify, 1);
1015
+ rb_define_method(geos_geometry_methods, "convex_hull", method_geometry_convex_hull, 0);
1016
+ rb_define_method(geos_geometry_methods, "intersection", method_geometry_intersection, 1);
1017
+ rb_define_method(geos_geometry_methods, "*", method_geometry_intersection, 1);
1018
+ rb_define_method(geos_geometry_methods, "union", method_geometry_union, 1);
1019
+ rb_define_method(geos_geometry_methods, "+", method_geometry_union, 1);
1020
+ rb_define_method(geos_geometry_methods, "difference", method_geometry_difference, 1);
1021
+ rb_define_method(geos_geometry_methods, "-", method_geometry_difference, 1);
1022
+ rb_define_method(geos_geometry_methods, "sym_difference", method_geometry_sym_difference, 1);
1023
+ }
1024
+
1025
+
1026
+ RGEO_END_C
1027
+
1028
+ #endif