rgeo 0.3.13 → 0.3.14

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