rgeo 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
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