rgeo 0.3.13 → 0.3.14

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 (51) hide show
  1. data/History.rdoc +8 -0
  2. data/README.rdoc +4 -4
  3. data/Version +1 -1
  4. data/ext/geos_c_impl/extconf.rb +1 -0
  5. data/ext/geos_c_impl/factory.c +118 -5
  6. data/ext/geos_c_impl/factory.h +24 -1
  7. data/ext/geos_c_impl/geometry.c +42 -53
  8. data/ext/geos_c_impl/geometry_collection.c +137 -54
  9. data/ext/geos_c_impl/geometry_collection.h +9 -0
  10. data/ext/geos_c_impl/line_string.c +88 -45
  11. data/ext/geos_c_impl/point.c +31 -17
  12. data/ext/geos_c_impl/polygon.c +50 -22
  13. data/ext/geos_c_impl/polygon.h +9 -0
  14. data/ext/geos_c_impl/preface.h +10 -0
  15. data/lib/rgeo/cartesian/factory.rb +9 -1
  16. data/lib/rgeo/coord_sys/cs/entities.rb +10 -1
  17. data/lib/rgeo/coord_sys/proj4.rb +1 -1
  18. data/lib/rgeo/feature/types.rb +29 -5
  19. data/lib/rgeo/geographic/factory.rb +5 -0
  20. data/lib/rgeo/geographic/projected_feature_classes.rb +3 -47
  21. data/lib/rgeo/geographic/projected_feature_methods.rb +69 -0
  22. data/lib/rgeo/geographic/spherical_feature_classes.rb +1 -74
  23. data/lib/rgeo/geographic/spherical_feature_methods.rb +84 -0
  24. data/lib/rgeo/geographic/spherical_math.rb +3 -3
  25. data/lib/rgeo/geos.rb +17 -9
  26. data/lib/rgeo/geos/{factory.rb → capi_factory.rb} +36 -15
  27. data/lib/rgeo/geos/{impl_additions.rb → capi_feature_classes.rb} +127 -16
  28. data/lib/rgeo/geos/ffi_factory.rb +55 -41
  29. data/lib/rgeo/geos/ffi_feature_classes.rb +168 -0
  30. data/lib/rgeo/geos/{ffi_classes.rb → ffi_feature_methods.rb} +56 -57
  31. data/lib/rgeo/geos/interface.rb +5 -5
  32. data/lib/rgeo/geos/utils.rb +7 -0
  33. data/lib/rgeo/geos/zm_factory.rb +40 -12
  34. data/lib/rgeo/geos/zm_feature_classes.rb +165 -0
  35. data/lib/rgeo/geos/{zm_impl.rb → zm_feature_methods.rb} +33 -52
  36. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +8 -0
  37. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +8 -0
  38. data/lib/rgeo/impl_helper/basic_point_methods.rb +5 -0
  39. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +8 -0
  40. data/test/common/factory_tests.rb +8 -2
  41. data/test/common/geometry_collection_tests.rb +23 -0
  42. data/test/common/line_string_tests.rb +25 -0
  43. data/test/common/multi_line_string_tests.rb +7 -0
  44. data/test/common/multi_point_tests.rb +7 -0
  45. data/test/common/multi_polygon_tests.rb +7 -0
  46. data/test/common/point_tests.rb +21 -0
  47. data/test/common/polygon_tests.rb +15 -0
  48. data/test/coord_sys/tc_proj4.rb +8 -1
  49. data/test/geos_capi/tc_misc.rb +1 -1
  50. data/test/tc_mixins.rb +1 -1
  51. metadata +9 -7
@@ -63,6 +63,15 @@ void rgeo_init_geos_geometry_collection(RGeo_Globals* globals);
63
63
  */
64
64
  VALUE rgeo_geos_geometry_collections_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z);
65
65
 
66
+ /*
67
+ A tool for building up hash values.
68
+ You must pass in the context, a geos geometry, and a seed hash.
69
+ Returns an updated hash.
70
+ This call is useful in sequence, and should be bracketed by calls to
71
+ rb_hash_start and rb_hash_end.
72
+ */
73
+ st_index_t rgeo_geos_geometry_collection_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash);
74
+
66
75
 
67
76
  RGEO_END_C
68
77
 
@@ -307,6 +307,54 @@ static VALUE method_line_string_eql(VALUE self, VALUE rhs)
307
307
  }
308
308
 
309
309
 
310
+ static VALUE method_line_string_hash(VALUE self)
311
+ {
312
+ st_index_t hash;
313
+ RGeo_GeometryData* self_data;
314
+ VALUE factory;
315
+
316
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
317
+ factory = self_data->factory;
318
+ hash = rb_hash_start(0);
319
+ hash = rgeo_geos_objbase_hash(factory,
320
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_line_string, hash);
321
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
322
+ return LONG2FIX(rb_hash_end(hash));
323
+ }
324
+
325
+
326
+ static VALUE method_linear_ring_hash(VALUE self)
327
+ {
328
+ st_index_t hash;
329
+ RGeo_GeometryData* self_data;
330
+ VALUE factory;
331
+
332
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
333
+ factory = self_data->factory;
334
+ hash = rb_hash_start(0);
335
+ hash = rgeo_geos_objbase_hash(factory,
336
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_linear_ring, hash);
337
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
338
+ return LONG2FIX(rb_hash_end(hash));
339
+ }
340
+
341
+
342
+ static VALUE method_line_hash(VALUE self)
343
+ {
344
+ st_index_t hash;
345
+ RGeo_GeometryData* self_data;
346
+ VALUE factory;
347
+
348
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
349
+ factory = self_data->factory;
350
+ hash = rb_hash_start(0);
351
+ hash = rgeo_geos_objbase_hash(factory,
352
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_line, hash);
353
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
354
+ return LONG2FIX(rb_hash_end(hash));
355
+ }
356
+
357
+
310
358
  static GEOSCoordSequence* coord_seq_from_array(VALUE factory, VALUE array, char close)
311
359
  {
312
360
  RGeo_FactoryData* factory_data;
@@ -543,51 +591,46 @@ static VALUE cmethod_linear_ring_copy_from(VALUE klass, VALUE factory, VALUE ori
543
591
 
544
592
  void rgeo_init_geos_line_string(RGeo_Globals* globals)
545
593
  {
546
- VALUE geos_line_string_class;
547
- VALUE geos_linear_ring_class;
548
- VALUE geos_line_class;
549
-
550
- geos_line_string_class = rb_define_class_under(globals->geos_module, "LineStringImpl", globals->geos_geometry);
551
- globals->geos_line_string = geos_line_string_class;
552
- globals->feature_line_string = rb_const_get_at(globals->feature_module, rb_intern("LineString"));
553
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
554
- rb_const_get_at(globals->feature_module, rb_intern("Curve")), geos_line_string_class);
555
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
556
- globals->feature_line_string, geos_line_string_class);
557
-
558
- geos_linear_ring_class = rb_define_class_under(globals->geos_module, "LinearRingImpl", geos_line_string_class);
559
- globals->geos_linear_ring = geos_linear_ring_class;
560
- globals->feature_linear_ring = rb_const_get_at(globals->feature_module, rb_intern("LinearRing"));
561
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
562
- globals->feature_linear_ring, geos_linear_ring_class);
563
-
564
- geos_line_class = rb_define_class_under(globals->geos_module, "LineImpl", geos_line_string_class);
565
- globals->geos_line = geos_line_class;
566
- globals->feature_line = rb_const_get_at(globals->feature_module, rb_intern("Line"));
567
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
568
- globals->feature_line, geos_line_class);
569
-
570
- rb_define_module_function(geos_line_string_class, "create", cmethod_create_line_string, 2);
571
- rb_define_module_function(geos_line_string_class, "_copy_from", cmethod_line_string_copy_from, 2);
572
- rb_define_method(geos_line_string_class, "rep_equals?", method_line_string_eql, 1);
573
- rb_define_method(geos_line_string_class, "eql?", method_line_string_eql, 1);
574
- rb_define_method(geos_line_string_class, "geometry_type", method_line_string_geometry_type, 0);
575
- rb_define_method(geos_line_string_class, "length", method_line_string_length, 0);
576
- rb_define_method(geos_line_string_class, "num_points", method_line_string_num_points, 0);
577
- rb_define_method(geos_line_string_class, "point_n", method_line_string_point_n, 1);
578
- rb_define_method(geos_line_string_class, "points", method_line_string_points, 0);
579
- rb_define_method(geos_line_string_class, "start_point", method_line_string_start_point, 0);
580
- rb_define_method(geos_line_string_class, "end_point", method_line_string_end_point, 0);
581
- rb_define_method(geos_line_string_class, "is_closed?", method_line_string_is_closed, 0);
582
- rb_define_method(geos_line_string_class, "is_ring?", method_line_string_is_ring, 0);
583
-
584
- rb_define_module_function(geos_linear_ring_class, "create", cmethod_create_linear_ring, 2);
585
- rb_define_module_function(geos_linear_ring_class, "_copy_from", cmethod_linear_ring_copy_from, 2);
586
- rb_define_method(geos_linear_ring_class, "geometry_type", method_linear_ring_geometry_type, 0);
587
-
588
- rb_define_module_function(geos_line_class, "create", cmethod_create_line, 3);
589
- rb_define_module_function(geos_line_class, "_copy_from", cmethod_line_copy_from, 2);
590
- rb_define_method(geos_line_class, "geometry_type", method_line_geometry_type, 0);
594
+ VALUE geos_line_string_methods;
595
+ VALUE geos_linear_ring_methods;
596
+ VALUE geos_line_methods;
597
+
598
+ // Class methods for CAPILineStringImpl
599
+ rb_define_module_function(globals->geos_line_string, "create", cmethod_create_line_string, 2);
600
+ rb_define_module_function(globals->geos_line_string, "_copy_from", cmethod_line_string_copy_from, 2);
601
+
602
+ // Class methods for CAPILinearRingImpl
603
+ rb_define_module_function(globals->geos_linear_ring, "create", cmethod_create_linear_ring, 2);
604
+ rb_define_module_function(globals->geos_linear_ring, "_copy_from", cmethod_linear_ring_copy_from, 2);
605
+
606
+ // Class methods for CAPILineImpl
607
+ rb_define_module_function(globals->geos_line, "create", cmethod_create_line, 3);
608
+ rb_define_module_function(globals->geos_line, "_copy_from", cmethod_line_copy_from, 2);
609
+
610
+ // CAPILineStringMethods module
611
+ geos_line_string_methods = rb_define_module_under(globals->geos_module, "CAPILineStringMethods");
612
+ rb_define_method(geos_line_string_methods, "rep_equals?", method_line_string_eql, 1);
613
+ rb_define_method(geos_line_string_methods, "eql?", method_line_string_eql, 1);
614
+ rb_define_method(geos_line_string_methods, "hash", method_line_string_hash, 0);
615
+ rb_define_method(geos_line_string_methods, "geometry_type", method_line_string_geometry_type, 0);
616
+ rb_define_method(geos_line_string_methods, "length", method_line_string_length, 0);
617
+ rb_define_method(geos_line_string_methods, "num_points", method_line_string_num_points, 0);
618
+ rb_define_method(geos_line_string_methods, "point_n", method_line_string_point_n, 1);
619
+ rb_define_method(geos_line_string_methods, "points", method_line_string_points, 0);
620
+ rb_define_method(geos_line_string_methods, "start_point", method_line_string_start_point, 0);
621
+ rb_define_method(geos_line_string_methods, "end_point", method_line_string_end_point, 0);
622
+ rb_define_method(geos_line_string_methods, "is_closed?", method_line_string_is_closed, 0);
623
+ rb_define_method(geos_line_string_methods, "is_ring?", method_line_string_is_ring, 0);
624
+
625
+ // CAPILinearRingMethods module
626
+ geos_linear_ring_methods = rb_define_module_under(globals->geos_module, "CAPILinearRingMethods");
627
+ rb_define_method(geos_linear_ring_methods, "geometry_type", method_linear_ring_geometry_type, 0);
628
+ rb_define_method(geos_linear_ring_methods, "hash", method_linear_ring_hash, 0);
629
+
630
+ // CAPILineMethods module
631
+ geos_line_methods = rb_define_module_under(globals->geos_module, "CAPILineMethods");
632
+ rb_define_method(geos_line_methods, "geometry_type", method_line_geometry_type, 0);
633
+ rb_define_method(geos_line_methods, "hash", method_line_hash, 0);
591
634
  }
592
635
 
593
636
 
@@ -166,6 +166,22 @@ static VALUE method_point_eql(VALUE self, VALUE rhs)
166
166
  }
167
167
 
168
168
 
169
+ static VALUE method_point_hash(VALUE self)
170
+ {
171
+ st_index_t hash;
172
+ RGeo_GeometryData* self_data;
173
+ VALUE factory;
174
+
175
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
176
+ factory = self_data->factory;
177
+ hash = rb_hash_start(0);
178
+ hash = rgeo_geos_objbase_hash(factory,
179
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_point, hash);
180
+ hash = rgeo_geos_coordseq_hash(self_data->geos_context, self_data->geom, hash);
181
+ return LONG2FIX(rb_hash_end(hash));
182
+ }
183
+
184
+
169
185
  static VALUE cmethod_create(VALUE module, VALUE factory, VALUE x, VALUE y, VALUE z)
170
186
  {
171
187
  return rgeo_create_geos_point(factory, rb_num2dbl(x), rb_num2dbl(y),
@@ -175,23 +191,21 @@ static VALUE cmethod_create(VALUE module, VALUE factory, VALUE x, VALUE y, VALUE
175
191
 
176
192
  void rgeo_init_geos_point(RGeo_Globals* globals)
177
193
  {
178
- VALUE geos_point_class;
179
-
180
- geos_point_class = rb_define_class_under(globals->geos_module, "PointImpl", globals->geos_geometry);
181
- globals->geos_point = geos_point_class;
182
- globals->feature_point = rb_const_get_at(globals->feature_module, rb_intern("Point"));
183
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
184
- globals->feature_point, geos_point_class);
185
-
186
- rb_define_module_function(geos_point_class, "create", cmethod_create, 4);
187
-
188
- rb_define_method(geos_point_class, "rep_equals?", method_point_eql, 1);
189
- rb_define_method(geos_point_class, "eql?", method_point_eql, 1);
190
- rb_define_method(geos_point_class, "geometry_type", method_point_geometry_type, 0);
191
- rb_define_method(geos_point_class, "x", method_point_x, 0);
192
- rb_define_method(geos_point_class, "y", method_point_y, 0);
193
- rb_define_method(geos_point_class, "z", method_point_z, 0);
194
- rb_define_method(geos_point_class, "m", method_point_m, 0);
194
+ VALUE geos_point_methods;
195
+
196
+ // Class methods for CAPIPointImpl
197
+ rb_define_module_function(globals->geos_point, "create", cmethod_create, 4);
198
+
199
+ // CAPIPointMethods module
200
+ geos_point_methods = rb_define_module_under(globals->geos_module, "CAPIPointMethods");
201
+ rb_define_method(geos_point_methods, "rep_equals?", method_point_eql, 1);
202
+ rb_define_method(geos_point_methods, "eql?", method_point_eql, 1);
203
+ rb_define_method(geos_point_methods, "hash", method_point_hash, 0);
204
+ rb_define_method(geos_point_methods, "geometry_type", method_point_geometry_type, 0);
205
+ rb_define_method(geos_point_methods, "x", method_point_x, 0);
206
+ rb_define_method(geos_point_methods, "y", method_point_y, 0);
207
+ rb_define_method(geos_point_methods, "z", method_point_z, 0);
208
+ rb_define_method(geos_point_methods, "m", method_point_m, 0);
195
209
  }
196
210
 
197
211
 
@@ -64,6 +64,22 @@ static VALUE method_polygon_eql(VALUE self, VALUE rhs)
64
64
  }
65
65
 
66
66
 
67
+ static VALUE method_polygon_hash(VALUE self)
68
+ {
69
+ st_index_t hash;
70
+ RGeo_GeometryData* self_data;
71
+ VALUE factory;
72
+
73
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
74
+ factory = self_data->factory;
75
+ hash = rb_hash_start(0);
76
+ hash = rgeo_geos_objbase_hash(factory,
77
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_polygon, hash);
78
+ hash = rgeo_geos_polygon_hash(self_data->geos_context, self_data->geom, hash);
79
+ return LONG2FIX(rb_hash_end(hash));
80
+ }
81
+
82
+
67
83
  static VALUE method_polygon_geometry_type(VALUE self)
68
84
  {
69
85
  VALUE result;
@@ -272,28 +288,24 @@ static VALUE cmethod_create(VALUE module, VALUE factory, VALUE exterior, VALUE i
272
288
 
273
289
  void rgeo_init_geos_polygon(RGeo_Globals* globals)
274
290
  {
275
- VALUE geos_polygon_class;
276
-
277
- geos_polygon_class = rb_define_class_under(globals->geos_module, "PolygonImpl", globals->geos_geometry);
278
- globals->geos_polygon = geos_polygon_class;
279
- globals->feature_polygon = rb_const_get_at(globals->feature_module, rb_intern("Polygon"));
280
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
281
- rb_const_get_at(globals->feature_module, rb_intern("Surface")), geos_polygon_class);
282
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
283
- globals->feature_polygon, geos_polygon_class);
284
-
285
- rb_define_module_function(geos_polygon_class, "create", cmethod_create, 3);
286
-
287
- rb_define_method(geos_polygon_class, "rep_equals?", method_polygon_eql, 1);
288
- rb_define_method(geos_polygon_class, "eql?", method_polygon_eql, 1);
289
- rb_define_method(geos_polygon_class, "geometry_type", method_polygon_geometry_type, 0);
290
- rb_define_method(geos_polygon_class, "area", method_polygon_area, 0);
291
- rb_define_method(geos_polygon_class, "centroid", method_polygon_centroid, 0);
292
- rb_define_method(geos_polygon_class, "point_on_surface", method_polygon_point_on_surface, 0);
293
- rb_define_method(geos_polygon_class, "exterior_ring", method_polygon_exterior_ring, 0);
294
- rb_define_method(geos_polygon_class, "num_interior_rings", method_polygon_num_interior_rings, 0);
295
- rb_define_method(geos_polygon_class, "interior_ring_n", method_polygon_interior_ring_n, 1);
296
- rb_define_method(geos_polygon_class, "interior_rings", method_polygon_interior_rings, 0);
291
+ VALUE geos_polygon_methods;
292
+
293
+ // Class methods for CAPIPolygonImpl
294
+ rb_define_module_function(globals->geos_polygon, "create", cmethod_create, 3);
295
+
296
+ // CAPIPolygonMethods module
297
+ geos_polygon_methods = rb_define_module_under(globals->geos_module, "CAPIPolygonMethods");
298
+ rb_define_method(geos_polygon_methods, "rep_equals?", method_polygon_eql, 1);
299
+ rb_define_method(geos_polygon_methods, "eql?", method_polygon_eql, 1);
300
+ rb_define_method(geos_polygon_methods, "hash", method_polygon_hash, 0);
301
+ rb_define_method(geos_polygon_methods, "geometry_type", method_polygon_geometry_type, 0);
302
+ rb_define_method(geos_polygon_methods, "area", method_polygon_area, 0);
303
+ rb_define_method(geos_polygon_methods, "centroid", method_polygon_centroid, 0);
304
+ rb_define_method(geos_polygon_methods, "point_on_surface", method_polygon_point_on_surface, 0);
305
+ rb_define_method(geos_polygon_methods, "exterior_ring", method_polygon_exterior_ring, 0);
306
+ rb_define_method(geos_polygon_methods, "num_interior_rings", method_polygon_num_interior_rings, 0);
307
+ rb_define_method(geos_polygon_methods, "interior_ring_n", method_polygon_interior_ring_n, 1);
308
+ rb_define_method(geos_polygon_methods, "interior_rings", method_polygon_interior_rings, 0);
297
309
  }
298
310
 
299
311
 
@@ -332,6 +344,22 @@ VALUE rgeo_geos_polygons_eql(GEOSContextHandle_t context, const GEOSGeometry* ge
332
344
  }
333
345
 
334
346
 
347
+ st_index_t rgeo_geos_polygon_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash)
348
+ {
349
+ unsigned int len;
350
+ unsigned int i;
351
+
352
+ if (geom) {
353
+ hash = rgeo_geos_coordseq_hash(context, GEOSGetExteriorRing_r(context, geom), hash);
354
+ len = GEOSGetNumInteriorRings_r(context, geom);
355
+ for (i=0; i<len; ++i) {
356
+ hash = rgeo_geos_coordseq_hash(context, GEOSGetInteriorRingN_r(context, geom, i), hash);
357
+ }
358
+ }
359
+ return hash;
360
+ }
361
+
362
+
335
363
  RGEO_END_C
336
364
 
337
365
  #endif
@@ -60,6 +60,15 @@ void rgeo_init_geos_polygon(RGeo_Globals* globals);
60
60
  */
61
61
  VALUE rgeo_geos_polygons_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z);
62
62
 
63
+ /*
64
+ A tool for building up hash values.
65
+ You must pass in the context, a geos geometry, and a seed hash.
66
+ Returns an updated hash.
67
+ This call is useful in sequence, and should be bracketed by calls to
68
+ rb_hash_start and rb_hash_end.
69
+ */
70
+ st_index_t rgeo_geos_polygon_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash);
71
+
63
72
 
64
73
  RGEO_END_C
65
74
 
@@ -50,6 +50,16 @@
50
50
  #ifdef HAVE_GEOSWKTWWRITER_SETOUTPUTDIMENSION_R
51
51
  #define RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
52
52
  #endif
53
+ #ifdef HAVE_RB_MEMHASH
54
+ #define RGEO_SUPPORTS_NEW_HASHING
55
+ #endif
56
+
57
+ #ifndef RGEO_SUPPORTS_NEW_HASHING
58
+ #define st_index_t int
59
+ #define rb_memhash(x,y) rgeo_internal_memhash(x,y)
60
+ #define rb_hash_start(x) ((st_index_t)(x ^ 0xdeadbeef))
61
+ #define rb_hash_end(x) ((st_index_t)(x ^ 0xbeefdead))
62
+ #endif
53
63
 
54
64
  #ifdef __cplusplus
55
65
  #define RGEO_BEGIN_C extern "C" {
@@ -114,11 +114,19 @@ module RGeo
114
114
  # Equivalence test.
115
115
 
116
116
  def eql?(rhs_)
117
- rhs_.is_a?(self.class) && @srid == rhs_.srid && @has_z == rhs_.property(:has_z_coordinate) && @has_m == rhs_.property(:has_m_coordinate)
117
+ rhs_.is_a?(self.class) && @srid == rhs_.srid &&
118
+ @has_z == rhs_.property(:has_z_coordinate) &&
119
+ @has_m == rhs_.property(:has_m_coordinate) &&
120
+ @proj4.eql?(rhs_.proj4)
118
121
  end
119
122
  alias_method :==, :eql?
120
123
 
121
124
 
125
+ def hash
126
+ @hash ||= [@srid, @has_z, @has_m, @proj4].hash
127
+ end
128
+
129
+
122
130
  # Marshal support
123
131
 
124
132
  def marshal_dump # :nodoc:
@@ -192,6 +192,11 @@ module RGeo
192
192
  alias_method :==, :eql?
193
193
 
194
194
 
195
+ def hash
196
+ @hash ||= self.to_wkt.hash
197
+ end
198
+
199
+
195
200
  # Returns the default WKT representation.
196
201
 
197
202
  def to_s
@@ -206,7 +211,11 @@ module RGeo
206
211
  # brackets. Default is false.
207
212
 
208
213
  def to_wkt(opts_={})
209
- opts_[:standard_brackets] ? _to_wkt('(', ')') : _to_wkt('[', ']')
214
+ if opts_[:standard_brackets]
215
+ @standard_wkt ||= _to_wkt('(', ')')
216
+ else
217
+ @square_wkt ||= _to_wkt('[', ']')
218
+ end
210
219
  end
211
220
 
212
221
 
@@ -64,7 +64,7 @@ module RGeo
64
64
 
65
65
 
66
66
  def hash # :nodoc:
67
- canonical_hash.hash
67
+ @hash ||= canonical_hash.hash
68
68
  end
69
69
 
70
70
 
@@ -47,20 +47,40 @@ module RGeo
47
47
  end
48
48
 
49
49
 
50
- # These methods are available as module methods (not instance methods)
51
- # of the various feature types.
50
+ # This module provides the API for geometry type objects. Technically
51
+ # these objects are modules (such as ::RGeo::Feature::Point), but as
52
+ # objects they respond to the methods documented here.
53
+ #
52
54
  # For example, you may determine whether a feature object is a
53
55
  # point by calling:
54
56
  #
55
57
  # ::RGeo::Feature::Point.check_type(object)
56
58
  #
57
59
  # A corresponding === operator is provided so you can use the type
58
- # modules in a case-when clause.
60
+ # modules in a case-when clause:
61
+ #
62
+ # case object
63
+ # when ::RGeo::Feature::Point
64
+ # # do stuff here...
65
+ #
66
+ # However, a feature object may not actually include the point module
67
+ # itself; hence, the following will *not* work:
68
+ #
69
+ # object.is_a?(::RGeo::Feature::Point) # DON'T DO THIS-- DOES NOT WORK
70
+ #
71
+ # You may obtain the type of a feature object by calling its
72
+ # geometry_type method. You may then use the methods in this module to
73
+ # interrogate that type.
74
+ #
75
+ # # supppose object is a Point
76
+ # type = object.geometry_type # ::RGeo::Feature::Point
77
+ # type.type_name # "Point"
78
+ # type.supertype # ::RGeo::Feature::Geometry
59
79
  #
60
80
  # You may also use the presence of this module to determine whether
61
81
  # a particular object is a feature type:
62
82
  #
63
- # object.kind_of?(::RGeo::Feature::Type)
83
+ # ::RGeo::Feature::Type === object.geometry_type # true
64
84
 
65
85
  module Type
66
86
 
@@ -74,6 +94,7 @@ module RGeo
74
94
  # this type or a subtype thereof.
75
95
  #
76
96
  # Note that feature objects need not actually include this module.
97
+ # Therefore, the is_a? method will generally not work.
77
98
 
78
99
  def check_type(rhs_)
79
100
  rhs_ = rhs_.geometry_type if rhs_.kind_of?(Feature::Instance)
@@ -105,11 +126,14 @@ module RGeo
105
126
  end
106
127
 
107
128
 
108
- # Returns the OpenGIS type name of this type.
129
+ # Returns the OpenGIS type name of this type. For example:
130
+ #
131
+ # ::RGeo::Feature::Point.type_name # "Point"
109
132
 
110
133
  def type_name
111
134
  self.name.sub('RGeo::Feature::', '')
112
135
  end
136
+ alias_method :to_s, :type_name
113
137
 
114
138
 
115
139
  def _add_subtype(type_) # :nodoc: