rgeo 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. data/History.rdoc +9 -7
  2. data/README.rdoc +7 -5
  3. data/Version +1 -1
  4. data/ext/geos_c_impl/factory.c +12 -19
  5. data/ext/geos_c_impl/factory.h +15 -21
  6. data/ext/geos_c_impl/geometry.c +19 -36
  7. data/ext/geos_c_impl/geometry.h +2 -12
  8. data/ext/geos_c_impl/geometry_collection.c +38 -157
  9. data/ext/geos_c_impl/geometry_collection.h +2 -12
  10. data/ext/geos_c_impl/line_string.c +83 -80
  11. data/ext/geos_c_impl/line_string.h +2 -12
  12. data/ext/geos_c_impl/main.c +5 -0
  13. data/ext/geos_c_impl/point.c +2 -12
  14. data/ext/geos_c_impl/point.h +2 -12
  15. data/ext/geos_c_impl/polygon.c +5 -14
  16. data/ext/geos_c_impl/polygon.h +2 -12
  17. data/ext/geos_c_impl/preface.h +8 -0
  18. data/lib/rgeo.rb +34 -16
  19. data/lib/rgeo/{geography/simple_spherical/geometry_collection_impl.rb → cartesian.rb} +19 -26
  20. data/lib/rgeo/cartesian/calculations.rb +129 -0
  21. data/lib/rgeo/cartesian/interface.rb +85 -0
  22. data/lib/rgeo/cartesian/simple_factory.rb +159 -0
  23. data/lib/rgeo/cartesian/simple_feature_classes.rb +187 -0
  24. data/lib/rgeo/cartesian/simple_feature_methods.rb +97 -0
  25. data/lib/rgeo/features.rb +1 -0
  26. data/lib/rgeo/features/curve.rb +3 -2
  27. data/lib/rgeo/features/factory.rb +62 -37
  28. data/lib/rgeo/features/geometry.rb +10 -32
  29. data/lib/rgeo/features/geometry_collection.rb +3 -2
  30. data/lib/rgeo/features/line.rb +3 -2
  31. data/lib/rgeo/features/line_string.rb +3 -2
  32. data/lib/rgeo/features/linear_ring.rb +3 -2
  33. data/lib/rgeo/features/multi_curve.rb +3 -2
  34. data/lib/rgeo/features/multi_line_string.rb +3 -2
  35. data/lib/rgeo/features/multi_point.rb +3 -2
  36. data/lib/rgeo/features/multi_polygon.rb +3 -2
  37. data/lib/rgeo/features/multi_surface.rb +3 -2
  38. data/lib/rgeo/features/point.rb +3 -2
  39. data/lib/rgeo/features/polygon.rb +3 -2
  40. data/lib/rgeo/features/surface.rb +3 -2
  41. data/lib/rgeo/features/types.rb +198 -0
  42. data/lib/rgeo/geography.rb +4 -14
  43. data/lib/rgeo/geography/factory.rb +7 -64
  44. data/lib/rgeo/geography/{simple_spherical/geometry_methods.rb → helper.rb} +4 -13
  45. data/lib/rgeo/geography/simple_mercator/feature_classes.rb +35 -89
  46. data/lib/rgeo/geography/simple_mercator/feature_methods.rb +22 -31
  47. data/lib/rgeo/geography/simple_mercator/projector.rb +4 -8
  48. data/lib/rgeo/geography/simple_spherical/calculations.rb +11 -9
  49. data/lib/rgeo/geography/simple_spherical/feature_classes.rb +189 -0
  50. data/lib/rgeo/geography/simple_spherical/{line_string_impl.rb → feature_methods.rb} +16 -64
  51. data/lib/rgeo/geos/factory.rb +26 -40
  52. data/lib/rgeo/geos/impl_additions.rb +3 -5
  53. data/lib/rgeo/{geography/simple_spherical/polygon_impl.rb → impl_helpers.rb} +16 -26
  54. data/lib/rgeo/impl_helpers/basic_geometry_collection_methods.rb +186 -0
  55. data/lib/rgeo/impl_helpers/basic_geometry_methods.rb +90 -0
  56. data/lib/rgeo/impl_helpers/basic_line_string_methods.rb +188 -0
  57. data/lib/rgeo/impl_helpers/basic_point_methods.rb +149 -0
  58. data/lib/rgeo/{geography/common/helper.rb → impl_helpers/basic_polygon_methods.rb} +62 -53
  59. data/lib/rgeo/{geography/common/polygon_methods.rb → impl_helpers/serialization.rb} +50 -42
  60. data/tests/common/geometry_collection_tests.rb +9 -7
  61. data/tests/common/multi_line_string_tests.rb +16 -13
  62. data/tests/common/multi_point_tests.rb +16 -13
  63. data/tests/common/multi_polygon_tests.rb +8 -6
  64. data/tests/common/point_tests.rb +1 -2
  65. data/tests/common/polygon_tests.rb +9 -9
  66. data/tests/geos/tc_multi_line_string.rb +2 -2
  67. data/tests/simple_cartesian/tc_calculations.rb +138 -0
  68. data/tests/simple_cartesian/tc_geometry_collection.rb +68 -0
  69. data/tests/simple_cartesian/tc_line_string.rb +70 -0
  70. data/{lib/rgeo/geography/simple_spherical/multi_line_string_impl.rb → tests/simple_cartesian/tc_multi_line_string.rb} +19 -19
  71. data/{lib/rgeo/geography/simple_spherical/multi_polygon_impl.rb → tests/simple_cartesian/tc_multi_point.rb} +19 -19
  72. data/{lib/rgeo/geography/common/geometry_methods.rb → tests/simple_cartesian/tc_multi_polygon.rb} +19 -41
  73. data/{lib/rgeo/geography/simple_spherical/point_impl.rb → tests/simple_cartesian/tc_point.rb} +33 -35
  74. data/tests/simple_cartesian/tc_polygon.rb +67 -0
  75. data/tests/simple_spherical/tc_geometry_collection.rb +68 -0
  76. data/tests/simple_spherical/tc_line_string.rb +10 -171
  77. data/tests/simple_spherical/tc_multi_line_string.rb +67 -0
  78. data/{lib/rgeo/geography/simple_spherical/multi_point_impl.rb → tests/simple_spherical/tc_multi_point.rb} +19 -19
  79. data/tests/simple_spherical/tc_multi_polygon.rb +70 -0
  80. data/tests/simple_spherical/tc_point.rb +17 -115
  81. data/tests/simple_spherical/tc_polygon.rb +67 -0
  82. metadata +46 -18
  83. data/ext/geos_c_impl/globals.h +0 -58
  84. data/lib/rgeo/geography/common/geometry_collection_methods.rb +0 -217
  85. data/lib/rgeo/geography/common/line_string_methods.rb +0 -201
  86. data/lib/rgeo/geography/common/point_methods.rb +0 -153
data/History.rdoc CHANGED
@@ -1,8 +1,14 @@
1
- === 0.1.12 / 2010-10-23
1
+ === 0.1.13 / 2010-10-26
2
2
 
3
- Further development and fixes in the geographic coordinate systems.
3
+ * Reworked the way casting is done. Casting has two dimensions: factory casting and type casting, either or both of which can be done at once. Implemented a standard casting algorithm to handle these cases, and an override mechanism for factories that want to do some of their own casting. Removed Factory#cast and Geometry#cast, and implemented a global Features::cast entry point instead.
4
+ * All factory and relational methods now perform auto-casting on inputs.
5
+ * Removed the "auto-flattening" behavior of Factory#multi_point, Factory#multi_line_string, and Factory#multi_polygon because it seemed overkill for factory methods. These methods now just attempt to auto-cast the immediate objects.
6
+ * Filled out more test cases for SimpleSpherical.
7
+ * Provided SimpleCartesian as a fallback implementation in case Geos is not available. SimpleCartesian is like SimpleSpherical in that some operations are not provided, but it is pure ruby and doesn't depend on external libraries.
8
+ * Improved feature type checking facilities.
9
+ * Documentation updates.
4
10
 
5
- Changes since 0.1.11:
11
+ === 0.1.12 / 2010-10-23
6
12
 
7
13
  * API CHANGE: Factory#coerce renamed to Factory#cast. I think this should be the final name for this function.
8
14
  * Some new tests and a lot of fixes in SimpleMercator and SimpleSpherical.
@@ -12,10 +18,6 @@ Changes since 0.1.11:
12
18
 
13
19
  === 0.1.11 / 2010-10-21
14
20
 
15
- Further development and fixing in the geographic coordinate systems.
16
-
17
- Changes since 0.1.10:
18
-
19
21
  * API CHANGE: Factory#convert renamed to Factory#coerce.
20
22
  * Some implementations that inherit from RGeo::Features::Geometry (e.g. the Geography implementations) raised Unimplemented from operator implementations because they had aliased the wrong methods. Fixed.
21
23
  * Geos coercer didn't properly coerce "contained" elements in a compound geometry. Fixed.
data/README.rdoc CHANGED
@@ -42,7 +42,9 @@ Use RGeo to:
42
42
  RGeo has the following prerequisites:
43
43
 
44
44
  * Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred.
45
- * GEOS 3.2 or later. This C/C++ library may be available via your
45
+ Rubinius and JRuby are not yet supported.
46
+ * GEOS 3.2 or later highly recommended. Some functions will not be
47
+ available without it. This C/C++ library may be available via your
46
48
  operating system's package manager, or you can download it from
47
49
  http://trac.osgeo.org/geos/
48
50
 
@@ -71,12 +73,12 @@ For example:
71
73
  RGeo is currently under development and several planned features are not
72
74
  yet complete. These include:
73
75
 
74
- * Test coverage of the SimpleMercator implementation.
75
- * The spherical geometry data objects.
76
+ * Some operations on SimpleCartesian and SimpleSpherical.
76
77
  * Rails (ActiveRecord or ActiveModel) integration.
77
78
  * Other third-party integration, including possibly SimpleGeo.
78
- * JRuby support via JTS.
79
- * Rubinius support.
79
+ * Support for additional formats such as ESRI shapefiles.
80
+ * JRuby support via JTS integration.
81
+ * Rubinius support for Geos integration.
80
82
 
81
83
  Additionally, not all implemented features are well-tested yet. In
82
84
  general, we currently consider this library to be "pre-alpha" quality,
data/Version CHANGED
@@ -1 +1 @@
1
- 0.1.12
1
+ 0.1.13
@@ -49,12 +49,7 @@
49
49
  #include "polygon.h"
50
50
  #include "geometry_collection.h"
51
51
 
52
- #ifdef __cplusplus
53
- extern "C" {
54
- #if 0
55
- }
56
- #endif
57
- #endif
52
+ RGEO_BEGIN_C
58
53
 
59
54
 
60
55
  /**** RUBY AND GEOS CALLBACKS ****/
@@ -330,9 +325,9 @@ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VAL
330
325
  }
331
326
 
332
327
 
333
- const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj)
328
+ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type)
334
329
  {
335
- VALUE object = rb_funcall(factory, rb_intern("cast"), 1, obj);
330
+ VALUE object = rb_funcall(RGEO_GLOBALS_FROM_FACTORY(factory)->features_module, rb_intern("cast"), 3, obj, factory, type);
336
331
  const GEOSGeometry* geom = NULL;
337
332
  if (!NIL_P(object)) {
338
333
  geom = RGEO_GET_GEOS_GEOMETRY(object);
@@ -341,21 +336,24 @@ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj)
341
336
  }
342
337
 
343
338
 
344
- GEOSGeometry* rgeo_convert_to_detached_geos_geometry(RGeo_Globals* globals, VALUE obj, VALUE* klasses)
339
+ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(RGeo_Globals* globals, VALUE obj, VALUE type, VALUE* klasses)
345
340
  {
346
341
  if (klasses) {
347
342
  *klasses = Qnil;
348
343
  }
349
- VALUE object = rb_funcall(globals->default_factory, rb_intern("cast"), 2, obj, Qtrue);
344
+ VALUE object = rb_funcall(globals->features_module, rb_intern("cast"), 5, obj, globals->default_factory, type, ID2SYM(rb_intern("force_new")), ID2SYM(rb_intern("keep_subtype")));
350
345
  GEOSGeometry* geom = NULL;
351
346
  if (!NIL_P(object)) {
352
347
  geom = RGEO_GEOMETRY_DATA_PTR(object)->geom;
348
+ if (klasses) {
349
+ *klasses = RGEO_KLASSES_FROM_GEOMETRY(object);
350
+ if (NIL_P(*klasses)) {
351
+ *klasses = CLASS_OF(object);
352
+ }
353
+ }
353
354
  RGEO_GEOMETRY_DATA_PTR(object)->geom = NULL;
354
355
  RGEO_GEOMETRY_DATA_PTR(object)->factory = Qnil;
355
356
  RGEO_GEOMETRY_DATA_PTR(object)->klasses = Qnil;
356
- if (klasses) {
357
- *klasses = rgeo_is_geos_object(obj) ? RGEO_KLASSES_FROM_GEOMETRY(obj) : Qnil;
358
- }
359
357
  }
360
358
  return geom;
361
359
  }
@@ -458,11 +456,6 @@ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2)
458
456
  }
459
457
 
460
458
 
461
- #ifdef __cplusplus
462
- #if 0
463
- {
464
- #endif
465
- }
466
- #endif
459
+ RGEO_END_C
467
460
 
468
461
  #endif
@@ -41,12 +41,7 @@
41
41
  #include <ruby.h>
42
42
  #include <geos_c.h>
43
43
 
44
- #ifdef __cplusplus
45
- extern "C" {
46
- #if 0
47
- }
48
- #endif
49
- #endif
44
+ RGEO_BEGIN_C
50
45
 
51
46
 
52
47
  // Per-interpreter globals
@@ -158,25 +153,29 @@ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VAL
158
153
  /*
159
154
  Gets the GEOS geometry for a given ruby Geometry object. If the given
160
155
  ruby object is not a GEOS geometry implementation, it is converted to a
161
- GEOS implementation first. The returned GEOS geometry is owned by rgeo,
156
+ GEOS implementation first. You may also optionally cast it to a type,
157
+ specified by an appropriate feature module. Passing Qnil for the type
158
+ disables this auto-cast. The returned GEOS geometry is owned by rgeo,
162
159
  and you should not dispose it or take ownership of it yourself.
163
160
  */
164
- const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj);
161
+ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type);
165
162
 
166
163
  /*
167
164
  Gets a GEOS geometry for a given ruby Geometry object. If the given
168
165
  ruby object is not a GEOS geometry implementation, it is converted to a
169
- GEOS implementation first. The returned GEOS geometry is owned by the
166
+ GEOS implementation first. You may also optionally cast it to a type,
167
+ specified by an appropriate feature module. Passing Qnil for the type
168
+ disables this auto-cast. The returned GEOS geometry is owned by the
170
169
  caller-- that is, if the original ruby object is a GEOS implementation,
171
170
  the returned GEOS geometry is a clone of the original.
172
171
  If the klasses parameters is not NULL, its referent is set to the
173
- klasses saved in the original ruby Geometry object (if any), or to Qnil
174
- if the original object is not a GEOS implementation. This is so that
175
- you can use the result of this function to build a GEOS-backed clone
176
- of the original geometry, or to include the given geometry in a
177
- collection while keeping the klasses intact.
172
+ klasses saved in the original ruby Geometry object (if any), or else to
173
+ the class of the converted GEOS object. This is so that you can use the
174
+ result of this function to build a GEOS-backed clone of the original
175
+ geometry, or to include the given geometry in a collection while keeping
176
+ the klasses intact.
178
177
  */
179
- GEOSGeometry* rgeo_convert_to_detached_geos_geometry(RGeo_Globals* globals, VALUE obj, VALUE* klasses);
178
+ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(RGeo_Globals* globals, VALUE obj, VALUE type, VALUE* klasses);
180
179
 
181
180
  /*
182
181
  Returns 1 if the given ruby object is a GEOS Geometry implementation,
@@ -207,11 +206,6 @@ VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* g
207
206
  VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2);
208
207
 
209
208
 
210
- #ifdef __cplusplus
211
- #if 0
212
- {
213
- #endif
214
- }
215
- #endif
209
+ RGEO_END_C
216
210
 
217
211
  #endif
@@ -46,12 +46,7 @@
46
46
  #include "factory.h"
47
47
  #include "geometry.h"
48
48
 
49
- #ifdef __cplusplus
50
- extern "C" {
51
- #if 0
52
- }
53
- #endif
54
- #endif
49
+ RGEO_BEGIN_C
55
50
 
56
51
 
57
52
  /**** INTERNAL UTILITY FUNCTIONS ****/
@@ -121,17 +116,10 @@ static VALUE method_geometry_factory(VALUE self)
121
116
  }
122
117
 
123
118
 
124
- static VALUE method_geometry_cast(VALUE self, VALUE type)
119
+ static VALUE method_geometry_set_factory(VALUE self, VALUE factory)
125
120
  {
126
- VALUE result = Qnil;
127
- const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
128
- if (self_geom) {
129
- char* my_type_str = GEOSGeomType_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom);
130
- VALUE type_name = rb_funcall(type, rb_intern("name"), 0);
131
- result = strcmp(my_type_str, StringValuePtr(type_name)) ? Qnil : self;
132
- free(my_type_str);
133
- }
134
- return result;
121
+ RGEO_GEOMETRY_DATA_PTR(self)->factory = factory;
122
+ return factory;
135
123
  }
136
124
 
137
125
 
@@ -305,7 +293,7 @@ static VALUE method_geometry_disjoint(VALUE self, VALUE rhs)
305
293
  VALUE result = Qnil;
306
294
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
307
295
  if (self_geom) {
308
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
296
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
309
297
  if (rhs_geom) {
310
298
  char val = GEOSDisjoint_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
311
299
  if (val == 0) {
@@ -325,7 +313,7 @@ static VALUE method_geometry_intersects(VALUE self, VALUE rhs)
325
313
  VALUE result = Qnil;
326
314
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
327
315
  if (self_geom) {
328
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
316
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
329
317
  if (rhs_geom) {
330
318
  char val = GEOSIntersects_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
331
319
  if (val == 0) {
@@ -345,7 +333,7 @@ static VALUE method_geometry_touches(VALUE self, VALUE rhs)
345
333
  VALUE result = Qnil;
346
334
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
347
335
  if (self_geom) {
348
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
336
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
349
337
  if (rhs_geom) {
350
338
  char val = GEOSTouches_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
351
339
  if (val == 0) {
@@ -365,7 +353,7 @@ static VALUE method_geometry_crosses(VALUE self, VALUE rhs)
365
353
  VALUE result = Qnil;
366
354
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
367
355
  if (self_geom) {
368
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
356
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
369
357
  if (rhs_geom) {
370
358
  char val = GEOSCrosses_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
371
359
  if (val == 0) {
@@ -385,7 +373,7 @@ static VALUE method_geometry_within(VALUE self, VALUE rhs)
385
373
  VALUE result = Qnil;
386
374
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
387
375
  if (self_geom) {
388
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
376
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
389
377
  if (rhs_geom) {
390
378
  char val = GEOSWithin_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
391
379
  if (val == 0) {
@@ -405,7 +393,7 @@ static VALUE method_geometry_contains(VALUE self, VALUE rhs)
405
393
  VALUE result = Qnil;
406
394
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
407
395
  if (self_geom) {
408
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
396
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
409
397
  if (rhs_geom) {
410
398
  char val = GEOSContains_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
411
399
  if (val == 0) {
@@ -425,7 +413,7 @@ static VALUE method_geometry_overlaps(VALUE self, VALUE rhs)
425
413
  VALUE result = Qnil;
426
414
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
427
415
  if (self_geom) {
428
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
416
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
429
417
  if (rhs_geom) {
430
418
  char val = GEOSOverlaps_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom);
431
419
  if (val == 0) {
@@ -445,7 +433,7 @@ static VALUE method_geometry_relate(VALUE self, VALUE rhs, VALUE pattern)
445
433
  VALUE result = Qnil;
446
434
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
447
435
  if (self_geom) {
448
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
436
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
449
437
  if (rhs_geom) {
450
438
  char val = GEOSRelatePattern_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom, StringValuePtr(pattern));
451
439
  if (val == 0) {
@@ -465,7 +453,7 @@ static VALUE method_geometry_distance(VALUE self, VALUE rhs)
465
453
  VALUE result = Qnil;
466
454
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
467
455
  if (self_geom) {
468
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
456
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
469
457
  if (rhs_geom) {
470
458
  double dist;
471
459
  if (GEOSDistance_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom, &dist)) {
@@ -505,7 +493,7 @@ static VALUE method_geometry_intersection(VALUE self, VALUE rhs)
505
493
  VALUE result = Qnil;
506
494
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
507
495
  if (self_geom) {
508
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
496
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
509
497
  if (rhs_geom) {
510
498
  result = rgeo_wrap_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), GEOSIntersection_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom), Qnil);
511
499
  }
@@ -519,7 +507,7 @@ static VALUE method_geometry_union(VALUE self, VALUE rhs)
519
507
  VALUE result = Qnil;
520
508
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
521
509
  if (self_geom) {
522
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
510
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
523
511
  if (rhs_geom) {
524
512
  result = rgeo_wrap_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), GEOSUnion_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom), Qnil);
525
513
  }
@@ -533,7 +521,7 @@ static VALUE method_geometry_difference(VALUE self, VALUE rhs)
533
521
  VALUE result = Qnil;
534
522
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
535
523
  if (self_geom) {
536
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
524
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
537
525
  if (rhs_geom) {
538
526
  result = rgeo_wrap_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), GEOSDifference_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom), Qnil);
539
527
  }
@@ -547,7 +535,7 @@ static VALUE method_geometry_sym_difference(VALUE self, VALUE rhs)
547
535
  VALUE result = Qnil;
548
536
  const GEOSGeometry* self_geom = RGEO_GET_GEOS_GEOMETRY(self);
549
537
  if (self_geom) {
550
- const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs);
538
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), rhs, Qnil);
551
539
  if (rhs_geom) {
552
540
  result = rgeo_wrap_geos_geometry(RGEO_FACTORY_FROM_GEOMETRY(self), GEOSSymDifference_r(RGEO_CONTEXT_FROM_GEOMETRY(self), self_geom, rhs_geom), Qnil);
553
541
  }
@@ -596,10 +584,10 @@ void rgeo_init_geos_geometry(RGeo_Globals* globals)
596
584
  VALUE geos_geometry_class = rb_define_class_under(globals->geos_module, "GeometryImpl", rb_cObject);
597
585
 
598
586
  rb_define_alloc_func(geos_geometry_class, alloc_geometry);
587
+ rb_define_method(geos_geometry_class, "_set_factory", method_geometry_set_factory, 1);
599
588
  rb_define_method(geos_geometry_class, "initialize_copy", method_geometry_initialize_copy, 1);
600
589
  rb_define_method(geos_geometry_class, "initialized?", method_geometry_initialized_p, 0);
601
590
  rb_define_method(geos_geometry_class, "factory", method_geometry_factory, 0);
602
- rb_define_method(geos_geometry_class, "cast", method_geometry_cast, 1);
603
591
  rb_define_method(geos_geometry_class, "dimension", method_geometry_dimension, 0);
604
592
  rb_define_method(geos_geometry_class, "geometry_type", method_geometry_geometry_type, 0);
605
593
  rb_define_method(geos_geometry_class, "srid", method_geometry_srid, 0);
@@ -634,11 +622,6 @@ void rgeo_init_geos_geometry(RGeo_Globals* globals)
634
622
  }
635
623
 
636
624
 
637
- #ifdef __cplusplus
638
- #if 0
639
- {
640
- #endif
641
- }
642
- #endif
625
+ RGEO_END_C
643
626
 
644
627
  #endif
@@ -40,12 +40,7 @@
40
40
 
41
41
  #include "factory.h"
42
42
 
43
- #ifdef __cplusplus
44
- extern "C" {
45
- #if 0
46
- }
47
- #endif
48
- #endif
43
+ RGEO_BEGIN_C
49
44
 
50
45
 
51
46
  /*
@@ -55,11 +50,6 @@ extern "C" {
55
50
  void rgeo_init_geos_geometry(RGeo_Globals* globals);
56
51
 
57
52
 
58
- #ifdef __cplusplus
59
- #if 0
60
- {
61
- #endif
62
- }
63
- #endif
53
+ RGEO_END_C
64
54
 
65
55
  #endif
@@ -48,179 +48,64 @@
48
48
  #include "polygon.h"
49
49
  #include "geometry_collection.h"
50
50
 
51
- #ifdef __cplusplus
52
- extern "C" {
53
- #if 0
54
- }
55
- #endif
56
- #endif
51
+ RGEO_BEGIN_C
57
52
 
58
53
 
59
54
  /**** INTERNAL IMPLEMENTATION OF CREATE ****/
60
55
 
61
56
 
62
- static char compute_collection_klasses_internal(int type, VALUE factory, const GEOSGeometry* geom, VALUE in_klass, VALUE out_klasses)
63
- {
64
- char good = 1;
65
- int geom_type = GEOSGeomTypeId_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom);
66
- if (type == GEOS_MULTIPOINT && geom_type == GEOS_POINT ||
67
- type == GEOS_MULTILINESTRING && (geom_type == GEOS_LINESTRING || geom_type == GEOS_LINEARRING) ||
68
- type == GEOS_MULTIPOLYGON && geom_type == GEOS_POLYGON) {
69
- rb_ary_push(out_klasses, in_klass);
70
- }
71
- else if (geom_type == GEOS_GEOMETRYCOLLECTION || type == geom_type) {
72
- int len = GEOSGetNumGeometries_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom);
73
- int i;
74
- for (i=0; i<len; ++i) {
75
- const GEOSGeometry* sub_geom = GEOSGetGeometryN_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom, i);
76
- if (sub_geom) {
77
- VALUE sub_klass = (TYPE(in_klass) == T_ARRAY) ? rb_ary_entry(in_klass, i) : Qnil;
78
- good = compute_collection_klasses_internal(type, factory, sub_geom, sub_klass, out_klasses);
79
- if (!good) {
80
- break;
81
- }
82
- }
83
- else {
84
- good = 0;
85
- break;
86
- }
87
- }
88
- }
89
- else {
90
- good = 0;
91
- }
92
- return good;
93
- }
94
-
95
-
96
- // This walks through an array of geometry objects, and determines the
97
- // size of the collection that should be built. For straight
98
- // GeometryCollection objects, the size is the same as the length of
99
- // the array. For MultiPoint, MultiLineString, and MultiPolygon, we do
100
- // recursive gathering of any sub-geometries, so the resulting collection
101
- // may have a different length.
102
- // We also build an array of the klasses for the geometries gathered.
103
- // The array is returned. If a problem occurs-- usually a type mismatch
104
- // such as trying to add a LineString to a MultiPoint-- we return Qnil.
57
+ // Main implementation of the "create" class method for geometry collections.
58
+ // You must pass in the correct GEOS geometry type ID.
105
59
 
106
- static VALUE compute_collection_klasses(int type, VALUE factory, VALUE array)
60
+ static VALUE create_geometry_collection(VALUE module, int type, VALUE factory, VALUE array)
107
61
  {
62
+ VALUE result = Qnil;
63
+ Check_Type(array, T_ARRAY);
108
64
  unsigned int len = (unsigned int)RARRAY_LEN(array);
109
- VALUE result = rb_ary_new();
110
- unsigned int i;
111
- for (i=0; i<len; ++i) {
112
- VALUE entry = rb_ary_entry(array, i);
113
- const GEOSGeometry* geom = rgeo_get_geos_geometry_safe(entry);
114
- if (!geom) {
115
- result = Qnil;
65
+ GEOSGeometry** geoms = ALLOC_N(GEOSGeometry*, len == 0 ? 1 : len);
66
+ if (geoms) {
67
+ VALUE klass;
68
+ unsigned int i,j;
69
+ VALUE klasses = Qnil;
70
+ VALUE cast_type = Qnil;
71
+ switch (type) {
72
+ case GEOS_MULTIPOINT:
73
+ cast_type = rb_const_get_at(RGEO_GLOBALS_FROM_FACTORY(factory)->features_module, rb_intern("Point"));
74
+ break;
75
+ case GEOS_MULTILINESTRING:
76
+ cast_type = rb_const_get_at(RGEO_GLOBALS_FROM_FACTORY(factory)->features_module, rb_intern("LineString"));
77
+ break;
78
+ case GEOS_MULTIPOLYGON:
79
+ cast_type = rb_const_get_at(RGEO_GLOBALS_FROM_FACTORY(factory)->features_module, rb_intern("Polygon"));
116
80
  break;
117
81
  }
118
- VALUE klass = RGEO_KLASSES_FROM_GEOMETRY(entry);
119
- if (NIL_P(klass)) {
120
- klass = CLASS_OF(entry);
121
- }
122
- if (type == GEOS_GEOMETRYCOLLECTION) {
123
- rb_ary_push(result, klass);
124
- }
125
- else {
126
- char good = compute_collection_klasses_internal(type, factory, geom, klass, result);
127
- if (!good) {
128
- result = Qnil;
129
- break;
130
- }
131
- }
132
- }
133
- return result;
134
- }
135
-
136
-
137
- static char gather_geometry_collection_internal(int type, VALUE factory, GEOSGeometry** geoms, unsigned int* ci, const GEOSGeometry* geom, char geom_mine)
138
- {
139
- char good = 1;
140
- int geom_type = GEOSGeomTypeId_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom);
141
- if (type != GEOS_GEOMETRYCOLLECTION && (geom_type == GEOS_GEOMETRYCOLLECTION || geom_type == type)) {
142
- int len = GEOSGetNumGeometries_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom);
143
- int i;
144
82
  for (i=0; i<len; ++i) {
145
- const GEOSGeometry* sub_geom = GEOSGetGeometryN_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom, i);
146
- if (sub_geom) {
147
- good = gather_geometry_collection_internal(type, factory, geoms, ci, sub_geom, 0);
148
- if (!good) {
149
- break;
150
- }
151
- }
152
- else {
153
- good = 0;
83
+ GEOSGeometry* geom = rgeo_convert_to_detached_geos_geometry(RGEO_GLOBALS_FROM_FACTORY(factory), rb_ary_entry(array, i), cast_type, &klass);
84
+ if (!geom) {
154
85
  break;
155
86
  }
156
- }
157
- }
158
- else {
159
- geoms[(*ci)++] = geom_mine ? (GEOSGeometry*)geom : GEOSGeom_clone_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom);
160
- }
161
- return good;
162
- }
163
-
164
-
165
- // This walks through the array of geometries and builds a C array of the
166
- // geometries to add to the collection we're building. If we're building
167
- // a simple GeometryCollection, we just gather the geometries as they are.
168
- // If we're building a MultiPoint, MultiLineString, or MultiPolygon, we
169
- // recursively gather the contents of any collections we encounter.
170
-
171
- static GEOSGeometry** gather_geometry_collection(int type, VALUE factory, VALUE array, unsigned int len)
172
- {
173
- GEOSGeometry** geoms = ALLOC_N(GEOSGeometry*, len == 0 ? 1 : len);
174
- unsigned int ci = 0;
175
- if (geoms) {
176
- unsigned int array_len = (unsigned int)RARRAY_LEN(array);
177
- unsigned int ai;
178
- for (ai=0; ai<array_len; ++ai) {
179
- GEOSGeometry* geom = rgeo_convert_to_detached_geos_geometry(RGEO_GLOBALS_FROM_FACTORY(factory), rb_ary_entry(array, ai), NULL);
180
- if (geom) {
181
- if (!gather_geometry_collection_internal(type, factory, geoms, &ci, geom, 1)) {
182
- break;
87
+ geoms[i] = geom;
88
+ if (!NIL_P(klass) && NIL_P(klasses)) {
89
+ klasses = rb_ary_new2(len);
90
+ for (j=0; j<i; ++j) {
91
+ rb_ary_push(klasses, Qnil);
183
92
  }
184
93
  }
185
- else {
186
- break;
94
+ if (!NIL_P(klasses)) {
95
+ rb_ary_push(klasses, klass);
187
96
  }
188
97
  }
189
- }
190
- if (ci != len) {
191
- unsigned int i;
192
- for (i=0; i<ci; ++i) {
193
- GEOSGeom_destroy_r(RGEO_CONTEXT_FROM_FACTORY(factory), geoms[i]);
98
+ if (i != len) {
99
+ for (j=0; j<i; ++j) {
100
+ GEOSGeom_destroy_r(RGEO_CONTEXT_FROM_FACTORY(factory), geoms[j]);
101
+ }
194
102
  }
195
- free(geoms);
196
- geoms = NULL;
197
- }
198
- return geoms;
199
- }
200
-
201
-
202
- // Main implementation of the "create" class method for geometry collections.
203
- // You must pass in the correct GEOS geometry type ID.
204
-
205
- static VALUE create_geometry_collection(VALUE module, int type, VALUE factory, VALUE array)
206
- {
207
- VALUE result = Qnil;
208
- Check_Type(array, T_ARRAY);
209
- // First pass: we determine the size of the collection to create, and
210
- // build the klasses array.
211
- VALUE klasses = compute_collection_klasses(type, factory, array);
212
- if (!NIL_P(klasses)) {
213
- unsigned int len = (unsigned int)RARRAY_LEN(klasses);
214
- // Second pass: we gather the actual geometries into a C array
215
- GEOSGeometry** geoms = gather_geometry_collection(type, factory, array, len);
216
- if (geoms) {
217
- // Create the collection itself.
103
+ else {
218
104
  GEOSGeometry* collection = GEOSGeom_createCollection_r(RGEO_CONTEXT_FROM_FACTORY(factory), type, geoms, len);
219
105
  // Due to a limitation of GEOS, the MultiPolygon assertions are not checked.
220
106
  // We do that manually here.
221
107
  if (collection && type == GEOS_MULTIPOLYGON && (RGEO_FACTORY_DATA_PTR(factory)->flags & 1) == 0) {
222
108
  char problem = 0;
223
- unsigned int i, j;
224
109
  for (i=1; i<len; ++i) {
225
110
  for (j=0; j<i; ++j) {
226
111
  GEOSGeometry* igeom = geoms[i];
@@ -251,9 +136,10 @@ static VALUE create_geometry_collection(VALUE module, int type, VALUE factory, V
251
136
  // element geometries if it fails to create the collection, so we
252
137
  // are not doing that ourselves. If that turns out not to be the
253
138
  // case, this will be a memory leak.
254
- free(geoms);
255
139
  }
140
+ free(geoms);
256
141
  }
142
+
257
143
  return result;
258
144
  }
259
145
 
@@ -570,11 +456,6 @@ VALUE rgeo_geos_geometry_collections_eql(GEOSContextHandle_t context, const GEOS
570
456
  }
571
457
 
572
458
 
573
- #ifdef __cplusplus
574
- #if 0
575
- {
576
- #endif
577
- }
578
- #endif
459
+ RGEO_END_C
579
460
 
580
461
  #endif