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
data/History.rdoc CHANGED
@@ -1,3 +1,11 @@
1
+ === 0.3.14 / 2012-07-08
2
+
3
+ * Compatibility note: The class names for some of the factory and feature implementations, as well as the superclass relationships, have changed in this release. These class names and hierarchy are internal, and clients should not depend on them. That is, RGeo types are generally duck-types. If you need to interrogate type, see the documentation for the ::RGeo::Feature::Type module.
4
+ * The gemspec no longer includes the timestamp in the version, so that bundler can pull from github. (Reported by corneverbruggen)
5
+ * Mixins were not being added to GEOS features with both Z and M coordinate. Fixed.
6
+ * Mixins are added last to feature objects, so they should override anything added by other modules such as Enumerable. (Reported by Ben Hughes)
7
+ * Some object hashes were not consistent with equality. Fixed. Hashes should now be consistent with representational equivalence (i.e. the eql? method). Therefore, it should now be possible to use RGeo factories and features as hash keys.
8
+
1
9
  === 0.3.13 / 2012-05-04
2
10
 
3
11
  * The spherical factory and the simple cartesian factory now support buffers around points (but not around other types). Accordingly, those factories now take the :buffer_resolution property argument.
data/README.rdoc CHANGED
@@ -100,10 +100,10 @@ The RGeo suite of tools is evolving rapidly. The current to-do list for
100
100
  the core library includes:
101
101
 
102
102
  * Better error handling and reporting.
103
- * JRuby support for Proj4
103
+ * JRuby support for Proj4.
104
+ * GDAL integration including coordinate system interpretation.
104
105
  * Ellipsoidal geography implementation, possibly utilizing geographiclib.
105
106
  * Windows build support.
106
- * GDAL integration including coordinate system interpretation.
107
107
 
108
108
  Each of the current add-on modules also has its own feature roadmap, and
109
109
  we are planning on introducing more add-on modules, including:
@@ -111,12 +111,12 @@ we are planning on introducing more add-on modules, including:
111
111
  * Raster support via GDAL.
112
112
  * GeoRSS and KML format support.
113
113
  * Custom spatial indexes.
114
- * Possible additional ActiveRecord adapters (esp. JDBC adapters)
114
+ * Possible additional ActiveRecord adapters (esp. JDBC-based adapters).
115
115
  * Integration with third-party APIs.
116
116
 
117
117
  === Development and support
118
118
 
119
- Documentation is available at http://virtuoso.rubyforge.org/rgeo/README_rdoc.html
119
+ Documentation is available at http://dazuma.github.com/rgeo/rdoc
120
120
 
121
121
  Source code is hosted on Github at http://github.com/dazuma/rgeo
122
122
 
data/Version CHANGED
@@ -1 +1 @@
1
- 0.3.13
1
+ 0.3.14
@@ -79,6 +79,7 @@ else
79
79
  have_func('GEOSPreparedContains_r', 'geos_c.h')
80
80
  have_func('GEOSPreparedDisjoint_r', 'geos_c.h')
81
81
  have_func('GEOSWKTWriter_setOutputDimension_r', 'geos_c.h')
82
+ have_func('rb_memhash', 'ruby.h')
82
83
  end
83
84
  unless found_geos_
84
85
  puts "**** WARNING: Unable to find GEOS headers or GEOS version is too old."
@@ -577,6 +577,12 @@ static VALUE method_get_wkb_parser(VALUE self)
577
577
  }
578
578
 
579
579
 
580
+ static VALUE alloc_geometry(VALUE klass)
581
+ {
582
+ return rgeo_wrap_geos_geometry(Qnil, NULL, klass);
583
+ }
584
+
585
+
580
586
  /**** INITIALIZATION FUNCTION ****/
581
587
 
582
588
 
@@ -586,17 +592,32 @@ RGeo_Globals* rgeo_init_geos_factory()
586
592
  VALUE rgeo_module;
587
593
  VALUE geos_factory_class;
588
594
  VALUE wrapped_globals;
595
+ VALUE feature_module;
589
596
 
590
597
  globals = ALLOC(RGeo_Globals);
598
+
599
+ // Cache some modules so we don't have to look them up by name every time
591
600
  rgeo_module = rb_define_module("RGeo");
601
+ feature_module = rb_define_module_under(rgeo_module, "Feature");
602
+ globals->feature_module = feature_module;
592
603
  globals->geos_module = rb_define_module_under(rgeo_module, "Geos");
593
- globals->feature_module = rb_define_module_under(rgeo_module, "Feature");
594
- globals->global_mixins = rb_const_get_at(rb_const_get_at(globals->feature_module, rb_intern("MixinCollection")), rb_intern("GLOBAL"));
595
-
604
+ globals->feature_geometry = rb_const_get_at(feature_module, rb_intern("Geometry"));
605
+ globals->feature_point = rb_const_get_at(feature_module, rb_intern("Point"));
606
+ globals->feature_line_string = rb_const_get_at(feature_module, rb_intern("LineString"));
607
+ globals->feature_linear_ring = rb_const_get_at(feature_module, rb_intern("LinearRing"));
608
+ globals->feature_line = rb_const_get_at(feature_module, rb_intern("Line"));
609
+ globals->feature_polygon = rb_const_get_at(feature_module, rb_intern("Polygon"));
610
+ globals->feature_geometry_collection = rb_const_get_at(feature_module, rb_intern("GeometryCollection"));
611
+ globals->feature_multi_point = rb_const_get_at(feature_module, rb_intern("MultiPoint"));
612
+ globals->feature_multi_line_string = rb_const_get_at(feature_module, rb_intern("MultiLineString"));
613
+ globals->feature_multi_polygon = rb_const_get_at(feature_module, rb_intern("MultiPolygon"));
614
+
615
+ // Cache some commonly used names
596
616
  globals->id_cast = rb_intern("cast");
597
617
  globals->id_eql = rb_intern("eql?");
598
618
  globals->id_generate = rb_intern("generate");
599
619
  globals->id_enum_for = rb_intern("enum_for");
620
+ globals->id_hash = rb_intern("hash");
600
621
  globals->sym_force_new = ID2SYM(rb_intern("force_new"));
601
622
  globals->sym_keep_subtype = ID2SYM(rb_intern("keep_subtype"));
602
623
  #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
@@ -604,9 +625,8 @@ RGeo_Globals* rgeo_init_geos_factory()
604
625
  globals->marshal_wkb_generator = Qnil;
605
626
  #endif
606
627
 
607
-
608
628
  // Add C methods to the factory.
609
- geos_factory_class = rb_const_get_at(globals->geos_module, rb_intern("Factory"));
629
+ geos_factory_class = rb_define_class_under(globals->geos_module, "CAPIFactory", rb_cObject);
610
630
  rb_define_alloc_func(geos_factory_class, alloc_factory);
611
631
  rb_define_method(geos_factory_class, "initialize_copy", method_factory_initialize_copy, 1);
612
632
  rb_define_method(geos_factory_class, "_parse_wkt_impl", method_factory_parse_wkt, 1);
@@ -627,6 +647,28 @@ RGeo_Globals* rgeo_init_geos_factory()
627
647
  rb_define_method(geos_factory_class, "_write_for_psych", method_factory_write_for_psych, 1);
628
648
  rb_define_module_function(geos_factory_class, "_create", cmethod_factory_create, 7);
629
649
 
650
+ // Pre-define implementation classes and set up allocation methods
651
+ globals->geos_geometry = rb_define_class_under(globals->geos_module, "CAPIGeometryImpl", rb_cObject);
652
+ rb_define_alloc_func(globals->geos_geometry, alloc_geometry);
653
+ globals->geos_point = rb_define_class_under(globals->geos_module, "CAPIPointImpl", rb_cObject);
654
+ rb_define_alloc_func(globals->geos_point, alloc_geometry);
655
+ globals->geos_line_string = rb_define_class_under(globals->geos_module, "CAPILineStringImpl", rb_cObject);
656
+ rb_define_alloc_func(globals->geos_line_string, alloc_geometry);
657
+ globals->geos_linear_ring = rb_define_class_under(globals->geos_module, "CAPILinearRingImpl", rb_cObject);
658
+ rb_define_alloc_func(globals->geos_linear_ring, alloc_geometry);
659
+ globals->geos_line = rb_define_class_under(globals->geos_module, "CAPILineImpl", rb_cObject);
660
+ rb_define_alloc_func(globals->geos_line, alloc_geometry);
661
+ globals->geos_polygon = rb_define_class_under(globals->geos_module, "CAPIPolygonImpl", rb_cObject);
662
+ rb_define_alloc_func(globals->geos_polygon, alloc_geometry);
663
+ globals->geos_geometry_collection = rb_define_class_under(globals->geos_module, "CAPIGeometryCollectionImpl", rb_cObject);
664
+ rb_define_alloc_func(globals->geos_geometry_collection, alloc_geometry);
665
+ globals->geos_multi_point = rb_define_class_under(globals->geos_module, "CAPIMultiPointImpl", rb_cObject);
666
+ rb_define_alloc_func(globals->geos_multi_point, alloc_geometry);
667
+ globals->geos_multi_line_string = rb_define_class_under(globals->geos_module, "CAPIMultiLineStringImpl", rb_cObject);
668
+ rb_define_alloc_func(globals->geos_multi_line_string, alloc_geometry);
669
+ globals->geos_multi_polygon = rb_define_class_under(globals->geos_module, "CAPIMultiPolygonImpl", rb_cObject);
670
+ rb_define_alloc_func(globals->geos_multi_polygon, alloc_geometry);
671
+
630
672
  // Wrap the globals in a Ruby object and store it off so we have access
631
673
  // to it later. Each factory instance will reference it internally.
632
674
  wrapped_globals = Data_Wrap_Struct(rb_cObject, mark_globals_func, destroy_globals_func, globals);
@@ -891,6 +933,77 @@ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2)
891
933
  }
892
934
 
893
935
 
936
+ typedef struct {
937
+ st_index_t seed_hash;
938
+ double x;
939
+ double y;
940
+ double z;
941
+ } RGeo_Coordseq_Hash_Struct;
942
+
943
+ st_index_t rgeo_geos_coordseq_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash)
944
+ {
945
+ const GEOSCoordSequence* cs;
946
+ unsigned int len;
947
+ unsigned int i;
948
+ RGeo_Coordseq_Hash_Struct hash_struct;
949
+
950
+ if (geom) {
951
+ cs = GEOSGeom_getCoordSeq_r(context, geom);
952
+ if (cs) {
953
+ if (GEOSCoordSeq_getSize_r(context, cs, &len)) {
954
+ for (i=0; i<len; ++i) {
955
+ if (GEOSCoordSeq_getX_r(context, cs, i, &hash_struct.x)) {
956
+ if (GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.y)) {
957
+ if (!GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.z)) {
958
+ hash_struct.z = 0;
959
+ }
960
+ hash_struct.seed_hash = hash;
961
+ hash = rb_memhash(&hash_struct, sizeof(RGeo_Coordseq_Hash_Struct));
962
+ }
963
+ }
964
+ }
965
+ }
966
+ }
967
+ }
968
+ return hash;
969
+ }
970
+
971
+
972
+ typedef struct {
973
+ st_index_t seed_hash;
974
+ st_index_t h1;
975
+ st_index_t h2;
976
+ } RGeo_Objbase_Hash_Struct;
977
+
978
+ st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t hash)
979
+ {
980
+ ID hash_method;
981
+ RGeo_Objbase_Hash_Struct hash_struct;
982
+
983
+ hash_method = RGEO_FACTORY_DATA_PTR(factory)->globals->id_hash;
984
+ hash_struct.seed_hash = hash;
985
+ hash_struct.h1 = FIX2LONG(rb_funcall(factory, hash_method, 0));
986
+ hash_struct.h2 = FIX2LONG(rb_funcall(type_module, hash_method, 0));
987
+ return rb_memhash(&hash_struct, sizeof(RGeo_Objbase_Hash_Struct));
988
+ }
989
+
990
+
991
+ st_index_t rgeo_internal_memhash(const void* ptr, long len)
992
+ {
993
+ const char* bytes;
994
+ st_index_t hval;
995
+ long i;
996
+
997
+ bytes = (const char*)ptr;
998
+ hval = 0x811c9dc5;
999
+ for (i=0; i<len; ++i) {
1000
+ hval ^= (unsigned int)(*bytes++);
1001
+ hval *= 0x01000193;
1002
+ }
1003
+ return hval;
1004
+ }
1005
+
1006
+
894
1007
  RGEO_END_C
895
1008
 
896
1009
  #endif
@@ -52,7 +52,6 @@ RGEO_BEGIN_C
52
52
  */
53
53
  typedef struct {
54
54
  VALUE feature_module;
55
- VALUE global_mixins;
56
55
  VALUE feature_geometry;
57
56
  VALUE feature_point;
58
57
  VALUE feature_line_string;
@@ -78,6 +77,7 @@ typedef struct {
78
77
  ID id_eql;
79
78
  ID id_generate;
80
79
  ID id_enum_for;
80
+ ID id_hash;
81
81
  VALUE sym_force_new;
82
82
  VALUE sym_keep_subtype;
83
83
  #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
@@ -242,6 +242,29 @@ VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* g
242
242
  */
243
243
  VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2);
244
244
 
245
+ /*
246
+ A tool for building up hash values.
247
+ You must pass in the context, a geos geometry, and a seed hash.
248
+ Returns an updated hash.
249
+ This call is useful in sequence, and should be bracketed by calls to
250
+ rb_hash_start and rb_hash_end.
251
+ */
252
+ st_index_t rgeo_geos_coordseq_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash);
253
+
254
+ /*
255
+ A tool for building up hash values.
256
+ You must pass in a factory, a feature type module, and a seed hash.
257
+ Returns an updated hash.
258
+ This call is useful in sequence, and should be bracketed by calls to
259
+ rb_hash_start and rb_hash_end.
260
+ */
261
+ st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t hash);
262
+
263
+ /*
264
+ Internal tool for creating simple (FNV-1A 32 bit) hashes.
265
+ */
266
+ st_index_t rgeo_internal_memhash(const void* ptr, long len);
267
+
245
268
 
246
269
  RGEO_END_C
247
270
 
@@ -885,12 +885,6 @@ static VALUE method_geometry_sym_difference(VALUE self, VALUE rhs)
885
885
  }
886
886
 
887
887
 
888
- static VALUE alloc_geometry(VALUE klass)
889
- {
890
- return rgeo_wrap_geos_geometry(Qnil, NULL, klass);
891
- }
892
-
893
-
894
888
  static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
895
889
  {
896
890
  RGeo_GeometryData* self_data;
@@ -980,53 +974,48 @@ static VALUE method_geometry_steal(VALUE self, VALUE orig)
980
974
 
981
975
  void rgeo_init_geos_geometry(RGeo_Globals* globals)
982
976
  {
983
- VALUE geos_geometry_class;
984
-
985
- geos_geometry_class = rb_define_class_under(globals->geos_module, "GeometryImpl", rb_cObject);
986
- globals->geos_geometry = geos_geometry_class;
987
- globals->feature_geometry = rb_const_get_at(globals->feature_module, rb_intern("Geometry"));
988
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
989
- globals->feature_geometry, geos_geometry_class);
990
-
991
- rb_define_alloc_func(geos_geometry_class, alloc_geometry);
992
- rb_define_method(geos_geometry_class, "_set_factory", method_geometry_set_factory, 1);
993
- rb_define_method(geos_geometry_class, "initialize_copy", method_geometry_initialize_copy, 1);
994
- rb_define_method(geos_geometry_class, "_steal", method_geometry_steal, 1);
995
- rb_define_method(geos_geometry_class, "initialized?", method_geometry_initialized_p, 0);
996
- rb_define_method(geos_geometry_class, "factory", method_geometry_factory, 0);
997
- rb_define_method(geos_geometry_class, "prepared?", method_geometry_prepared_p, 0);
998
- rb_define_method(geos_geometry_class, "prepare!", method_geometry_prepare, 0);
999
- rb_define_method(geos_geometry_class, "dimension", method_geometry_dimension, 0);
1000
- rb_define_method(geos_geometry_class, "geometry_type", method_geometry_geometry_type, 0);
1001
- rb_define_method(geos_geometry_class, "srid", method_geometry_srid, 0);
1002
- rb_define_method(geos_geometry_class, "envelope", method_geometry_envelope, 0);
1003
- rb_define_method(geos_geometry_class, "boundary", method_geometry_boundary, 0);
1004
- rb_define_method(geos_geometry_class, "_as_text", method_geometry_as_text, 0);
1005
- rb_define_method(geos_geometry_class, "as_binary", method_geometry_as_binary, 0);
1006
- rb_define_method(geos_geometry_class, "is_empty?", method_geometry_is_empty, 0);
1007
- rb_define_method(geos_geometry_class, "is_simple?", method_geometry_is_simple, 0);
1008
- rb_define_method(geos_geometry_class, "equals?", method_geometry_equals, 1);
1009
- rb_define_method(geos_geometry_class, "==", method_geometry_equals, 1);
1010
- rb_define_method(geos_geometry_class, "rep_equals?", method_geometry_eql, 1);
1011
- rb_define_method(geos_geometry_class, "eql?", method_geometry_eql, 1);
1012
- rb_define_method(geos_geometry_class, "disjoint?", method_geometry_disjoint, 1);
1013
- rb_define_method(geos_geometry_class, "intersects?", method_geometry_intersects, 1);
1014
- rb_define_method(geos_geometry_class, "touches?", method_geometry_touches, 1);
1015
- rb_define_method(geos_geometry_class, "crosses?", method_geometry_crosses, 1);
1016
- rb_define_method(geos_geometry_class, "within?", method_geometry_within, 1);
1017
- rb_define_method(geos_geometry_class, "contains?", method_geometry_contains, 1);
1018
- rb_define_method(geos_geometry_class, "overlaps?", method_geometry_overlaps, 1);
1019
- rb_define_method(geos_geometry_class, "relate?", method_geometry_relate, 2);
1020
- rb_define_method(geos_geometry_class, "distance", method_geometry_distance, 1);
1021
- rb_define_method(geos_geometry_class, "buffer", method_geometry_buffer, 1);
1022
- rb_define_method(geos_geometry_class, "convex_hull", method_geometry_convex_hull, 0);
1023
- rb_define_method(geos_geometry_class, "intersection", method_geometry_intersection, 1);
1024
- rb_define_method(geos_geometry_class, "*", method_geometry_intersection, 1);
1025
- rb_define_method(geos_geometry_class, "union", method_geometry_union, 1);
1026
- rb_define_method(geos_geometry_class, "+", method_geometry_union, 1);
1027
- rb_define_method(geos_geometry_class, "difference", method_geometry_difference, 1);
1028
- rb_define_method(geos_geometry_class, "-", method_geometry_difference, 1);
1029
- rb_define_method(geos_geometry_class, "sym_difference", method_geometry_sym_difference, 1);
977
+ VALUE geos_geometry_methods;
978
+
979
+ geos_geometry_methods = rb_define_module_under(globals->geos_module, "CAPIGeometryMethods");
980
+
981
+ rb_define_method(geos_geometry_methods, "_set_factory", method_geometry_set_factory, 1);
982
+ rb_define_method(geos_geometry_methods, "initialize_copy", method_geometry_initialize_copy, 1);
983
+ rb_define_method(geos_geometry_methods, "_steal", method_geometry_steal, 1);
984
+ rb_define_method(geos_geometry_methods, "initialized?", method_geometry_initialized_p, 0);
985
+ rb_define_method(geos_geometry_methods, "factory", method_geometry_factory, 0);
986
+ rb_define_method(geos_geometry_methods, "prepared?", method_geometry_prepared_p, 0);
987
+ rb_define_method(geos_geometry_methods, "prepare!", method_geometry_prepare, 0);
988
+ rb_define_method(geos_geometry_methods, "dimension", method_geometry_dimension, 0);
989
+ rb_define_method(geos_geometry_methods, "geometry_type", method_geometry_geometry_type, 0);
990
+ rb_define_method(geos_geometry_methods, "srid", method_geometry_srid, 0);
991
+ rb_define_method(geos_geometry_methods, "envelope", method_geometry_envelope, 0);
992
+ rb_define_method(geos_geometry_methods, "boundary", method_geometry_boundary, 0);
993
+ rb_define_method(geos_geometry_methods, "_as_text", method_geometry_as_text, 0);
994
+ rb_define_method(geos_geometry_methods, "as_binary", method_geometry_as_binary, 0);
995
+ rb_define_method(geos_geometry_methods, "is_empty?", method_geometry_is_empty, 0);
996
+ rb_define_method(geos_geometry_methods, "is_simple?", method_geometry_is_simple, 0);
997
+ rb_define_method(geos_geometry_methods, "equals?", method_geometry_equals, 1);
998
+ rb_define_method(geos_geometry_methods, "==", method_geometry_equals, 1);
999
+ rb_define_method(geos_geometry_methods, "rep_equals?", method_geometry_eql, 1);
1000
+ rb_define_method(geos_geometry_methods, "eql?", method_geometry_eql, 1);
1001
+ rb_define_method(geos_geometry_methods, "disjoint?", method_geometry_disjoint, 1);
1002
+ rb_define_method(geos_geometry_methods, "intersects?", method_geometry_intersects, 1);
1003
+ rb_define_method(geos_geometry_methods, "touches?", method_geometry_touches, 1);
1004
+ rb_define_method(geos_geometry_methods, "crosses?", method_geometry_crosses, 1);
1005
+ rb_define_method(geos_geometry_methods, "within?", method_geometry_within, 1);
1006
+ rb_define_method(geos_geometry_methods, "contains?", method_geometry_contains, 1);
1007
+ rb_define_method(geos_geometry_methods, "overlaps?", method_geometry_overlaps, 1);
1008
+ rb_define_method(geos_geometry_methods, "relate?", method_geometry_relate, 2);
1009
+ rb_define_method(geos_geometry_methods, "distance", method_geometry_distance, 1);
1010
+ rb_define_method(geos_geometry_methods, "buffer", method_geometry_buffer, 1);
1011
+ rb_define_method(geos_geometry_methods, "convex_hull", method_geometry_convex_hull, 0);
1012
+ rb_define_method(geos_geometry_methods, "intersection", method_geometry_intersection, 1);
1013
+ rb_define_method(geos_geometry_methods, "*", method_geometry_intersection, 1);
1014
+ rb_define_method(geos_geometry_methods, "union", method_geometry_union, 1);
1015
+ rb_define_method(geos_geometry_methods, "+", method_geometry_union, 1);
1016
+ rb_define_method(geos_geometry_methods, "difference", method_geometry_difference, 1);
1017
+ rb_define_method(geos_geometry_methods, "-", method_geometry_difference, 1);
1018
+ rb_define_method(geos_geometry_methods, "sym_difference", method_geometry_sym_difference, 1);
1030
1019
  }
1031
1020
 
1032
1021
 
@@ -177,6 +177,22 @@ static VALUE method_geometry_collection_eql(VALUE self, VALUE rhs)
177
177
  }
178
178
 
179
179
 
180
+ static VALUE method_geometry_collection_hash(VALUE self)
181
+ {
182
+ st_index_t hash;
183
+ RGeo_GeometryData* self_data;
184
+ VALUE factory;
185
+
186
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
187
+ factory = self_data->factory;
188
+ hash = rb_hash_start(0);
189
+ hash = rgeo_geos_objbase_hash(factory,
190
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_geometry_collection, hash);
191
+ hash = rgeo_geos_geometry_collection_hash(self_data->geos_context, self_data->geom, hash);
192
+ return LONG2FIX(rb_hash_end(hash));
193
+ }
194
+
195
+
180
196
  static VALUE method_geometry_collection_geometry_type(VALUE self)
181
197
  {
182
198
  VALUE result;
@@ -301,6 +317,22 @@ static VALUE method_multi_point_geometry_type(VALUE self)
301
317
  }
302
318
 
303
319
 
320
+ static VALUE method_multi_point_hash(VALUE self)
321
+ {
322
+ st_index_t hash;
323
+ RGeo_GeometryData* self_data;
324
+ VALUE factory;
325
+
326
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
327
+ factory = self_data->factory;
328
+ hash = rb_hash_start(0);
329
+ hash = rgeo_geos_objbase_hash(factory,
330
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_multi_point, hash);
331
+ hash = rgeo_geos_geometry_collection_hash(self_data->geos_context, self_data->geom, hash);
332
+ return LONG2FIX(rb_hash_end(hash));
333
+ }
334
+
335
+
304
336
  static VALUE method_multi_line_string_geometry_type(VALUE self)
305
337
  {
306
338
  VALUE result;
@@ -315,6 +347,22 @@ static VALUE method_multi_line_string_geometry_type(VALUE self)
315
347
  }
316
348
 
317
349
 
350
+ static VALUE method_multi_line_string_hash(VALUE self)
351
+ {
352
+ st_index_t hash;
353
+ RGeo_GeometryData* self_data;
354
+ VALUE factory;
355
+
356
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
357
+ factory = self_data->factory;
358
+ hash = rb_hash_start(0);
359
+ hash = rgeo_geos_objbase_hash(factory,
360
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_multi_line_string, hash);
361
+ hash = rgeo_geos_geometry_collection_hash(self_data->geos_context, self_data->geom, hash);
362
+ return LONG2FIX(rb_hash_end(hash));
363
+ }
364
+
365
+
318
366
  static VALUE method_multi_line_string_length(VALUE self)
319
367
  {
320
368
  VALUE result;
@@ -381,6 +429,22 @@ static VALUE method_multi_polygon_geometry_type(VALUE self)
381
429
  }
382
430
 
383
431
 
432
+ static VALUE method_multi_polygon_hash(VALUE self)
433
+ {
434
+ st_index_t hash;
435
+ RGeo_GeometryData* self_data;
436
+ VALUE factory;
437
+
438
+ self_data = RGEO_GEOMETRY_DATA_PTR(self);
439
+ factory = self_data->factory;
440
+ hash = rb_hash_start(0);
441
+ hash = rgeo_geos_objbase_hash(factory,
442
+ RGEO_FACTORY_DATA_PTR(factory)->globals->feature_multi_polygon, hash);
443
+ hash = rgeo_geos_geometry_collection_hash(self_data->geos_context, self_data->geom, hash);
444
+ return LONG2FIX(rb_hash_end(hash));
445
+ }
446
+
447
+
384
448
  static VALUE method_multi_polygon_area(VALUE self)
385
449
  {
386
450
  VALUE result;
@@ -461,68 +525,48 @@ static VALUE cmethod_multi_polygon_create(VALUE module, VALUE factory, VALUE arr
461
525
 
462
526
  void rgeo_init_geos_geometry_collection(RGeo_Globals* globals)
463
527
  {
464
- VALUE geos_geometry_collection_class;
465
- VALUE geos_multi_point_class;
466
- VALUE geos_multi_line_string_class;
467
- VALUE geos_multi_polygon_class;
468
-
469
- // Create implementation classes
470
- geos_geometry_collection_class = rb_define_class_under(globals->geos_module, "GeometryCollectionImpl", globals->geos_geometry);
471
- globals->geos_geometry_collection = geos_geometry_collection_class;
472
- globals->feature_geometry_collection = rb_const_get_at(globals->feature_module, rb_intern("GeometryCollection"));
473
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
474
- globals->feature_geometry_collection, geos_geometry_collection_class);
475
-
476
- geos_multi_point_class = rb_define_class_under(globals->geos_module, "MultiPointImpl", geos_geometry_collection_class);
477
- globals->geos_multi_point = geos_multi_point_class;
478
- globals->feature_multi_point = rb_const_get_at(globals->feature_module, rb_intern("MultiPoint"));
479
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
480
- globals->feature_multi_point, geos_multi_point_class);
481
-
482
- geos_multi_line_string_class = rb_define_class_under(globals->geos_module, "MultiLineStringImpl", geos_geometry_collection_class);
483
- globals->geos_multi_line_string = geos_multi_line_string_class;
484
- globals->feature_multi_line_string = rb_const_get_at(globals->feature_module, rb_intern("MultiLineString"));
485
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
486
- rb_const_get_at(globals->feature_module, rb_intern("MultiCurve")), geos_multi_line_string_class);
487
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
488
- globals->feature_multi_line_string, geos_multi_line_string_class);
489
-
490
- geos_multi_polygon_class = rb_define_class_under(globals->geos_module, "MultiPolygonImpl", geos_geometry_collection_class);
491
- globals->geos_multi_polygon = geos_multi_polygon_class;
492
- globals->feature_multi_polygon = rb_const_get_at(globals->feature_module, rb_intern("MultiPolygon"));
493
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
494
- rb_const_get_at(globals->feature_module, rb_intern("MultiSurface")), geos_multi_polygon_class);
495
- rb_funcall(globals->global_mixins, rb_intern("include_in_class"), 2,
496
- globals->feature_multi_polygon, geos_multi_polygon_class);
528
+ VALUE geos_geometry_collection_methods;
529
+ VALUE geos_multi_point_methods;
530
+ VALUE geos_multi_line_string_methods;
531
+ VALUE geos_multi_polygon_methods;
532
+
533
+ // Class methods for geometry collection classes
534
+ rb_define_module_function(globals->geos_geometry_collection, "create", cmethod_geometry_collection_create, 2);
535
+ rb_define_module_function(globals->geos_multi_point, "create", cmethod_multi_point_create, 2);
536
+ rb_define_module_function(globals->geos_multi_line_string, "create", cmethod_multi_line_string_create, 2);
537
+ rb_define_module_function(globals->geos_multi_polygon, "create", cmethod_multi_polygon_create, 2);
497
538
 
498
539
  // Methods for GeometryCollectionImpl
499
- rb_define_module_function(geos_geometry_collection_class, "create", cmethod_geometry_collection_create, 2);
500
- rb_include_module(geos_geometry_collection_class, rb_define_module("Enumerable"));
501
- rb_define_method(geos_geometry_collection_class, "rep_equals?", method_geometry_collection_eql, 1);
502
- rb_define_method(geos_geometry_collection_class, "eql?", method_geometry_collection_eql, 1);
503
- rb_define_method(geos_geometry_collection_class, "geometry_type", method_geometry_collection_geometry_type, 0);
504
- rb_define_method(geos_geometry_collection_class, "num_geometries", method_geometry_collection_num_geometries, 0);
505
- rb_define_method(geos_geometry_collection_class, "size", method_geometry_collection_num_geometries, 0);
506
- rb_define_method(geos_geometry_collection_class, "geometry_n", method_geometry_collection_geometry_n, 1);
507
- rb_define_method(geos_geometry_collection_class, "[]", method_geometry_collection_brackets, 1);
508
- rb_define_method(geos_geometry_collection_class, "each", method_geometry_collection_each, 0);
540
+ geos_geometry_collection_methods = rb_define_module_under(globals->geos_module, "CAPIGeometryCollectionMethods");
541
+ rb_define_method(geos_geometry_collection_methods, "rep_equals?", method_geometry_collection_eql, 1);
542
+ rb_define_method(geos_geometry_collection_methods, "eql?", method_geometry_collection_eql, 1);
543
+ rb_define_method(geos_geometry_collection_methods, "hash", method_geometry_collection_hash, 0);
544
+ rb_define_method(geos_geometry_collection_methods, "geometry_type", method_geometry_collection_geometry_type, 0);
545
+ rb_define_method(geos_geometry_collection_methods, "num_geometries", method_geometry_collection_num_geometries, 0);
546
+ rb_define_method(geos_geometry_collection_methods, "size", method_geometry_collection_num_geometries, 0);
547
+ rb_define_method(geos_geometry_collection_methods, "geometry_n", method_geometry_collection_geometry_n, 1);
548
+ rb_define_method(geos_geometry_collection_methods, "[]", method_geometry_collection_brackets, 1);
549
+ rb_define_method(geos_geometry_collection_methods, "each", method_geometry_collection_each, 0);
509
550
 
510
551
  // Methods for MultiPointImpl
511
- rb_define_module_function(geos_multi_point_class, "create", cmethod_multi_point_create, 2);
512
- rb_define_method(geos_multi_point_class, "geometry_type", method_multi_point_geometry_type, 0);
552
+ geos_multi_point_methods = rb_define_module_under(globals->geos_module, "CAPIMultiPointMethods");
553
+ rb_define_method(geos_multi_point_methods, "geometry_type", method_multi_point_geometry_type, 0);
554
+ rb_define_method(geos_multi_point_methods, "hash", method_multi_point_hash, 0);
513
555
 
514
556
  // Methods for MultiLineStringImpl
515
- rb_define_module_function(geos_multi_line_string_class, "create", cmethod_multi_line_string_create, 2);
516
- rb_define_method(geos_multi_line_string_class, "geometry_type", method_multi_line_string_geometry_type, 0);
517
- rb_define_method(geos_multi_line_string_class, "length", method_multi_line_string_length, 0);
518
- rb_define_method(geos_multi_line_string_class, "is_closed?", method_multi_line_string_is_closed, 0);
557
+ geos_multi_line_string_methods = rb_define_module_under(globals->geos_module, "CAPIMultiLineStringMethods");
558
+ rb_define_method(geos_multi_line_string_methods, "geometry_type", method_multi_line_string_geometry_type, 0);
559
+ rb_define_method(geos_multi_line_string_methods, "length", method_multi_line_string_length, 0);
560
+ rb_define_method(geos_multi_line_string_methods, "is_closed?", method_multi_line_string_is_closed, 0);
561
+ rb_define_method(geos_multi_line_string_methods, "hash", method_multi_line_string_hash, 0);
519
562
 
520
563
  // Methods for MultiPolygonImpl
521
- rb_define_module_function(geos_multi_polygon_class, "create", cmethod_multi_polygon_create, 2);
522
- rb_define_method(geos_multi_polygon_class, "geometry_type", method_multi_polygon_geometry_type, 0);
523
- rb_define_method(geos_multi_polygon_class, "area", method_multi_polygon_area, 0);
524
- rb_define_method(geos_multi_polygon_class, "centroid", method_multi_polygon_centroid, 0);
525
- rb_define_method(geos_multi_polygon_class, "point_on_surface", method_multi_polygon_point_on_surface, 0);
564
+ geos_multi_polygon_methods = rb_define_module_under(globals->geos_module, "CAPIMultiPolygonMethods");
565
+ rb_define_method(geos_multi_polygon_methods, "geometry_type", method_multi_polygon_geometry_type, 0);
566
+ rb_define_method(geos_multi_polygon_methods, "area", method_multi_polygon_area, 0);
567
+ rb_define_method(geos_multi_polygon_methods, "centroid", method_multi_polygon_centroid, 0);
568
+ rb_define_method(geos_multi_polygon_methods, "point_on_surface", method_multi_polygon_point_on_surface, 0);
569
+ rb_define_method(geos_multi_polygon_methods, "hash", method_multi_polygon_hash, 0);
526
570
  }
527
571
 
528
572
 
@@ -603,6 +647,45 @@ VALUE rgeo_geos_geometry_collections_eql(GEOSContextHandle_t context, const GEOS
603
647
  }
604
648
 
605
649
 
650
+ st_index_t rgeo_geos_geometry_collection_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash)
651
+ {
652
+ const GEOSGeometry* sub_geom;
653
+ int type;
654
+ unsigned int len;
655
+ unsigned int i;
656
+
657
+ if (geom) {
658
+ len = GEOSGetNumGeometries_r(context, geom);
659
+ for (i=0; i<len; ++i) {
660
+ sub_geom = GEOSGetGeometryN_r(context, geom, i);
661
+ if (sub_geom) {
662
+ type = GEOSGeomTypeId_r(context, sub_geom);
663
+ if (type >= 0) {
664
+ hash = hash ^ type;
665
+ switch (type) {
666
+ case GEOS_POINT:
667
+ case GEOS_LINESTRING:
668
+ case GEOS_LINEARRING:
669
+ hash = rgeo_geos_coordseq_hash(context, sub_geom, hash);
670
+ break;
671
+ case GEOS_POLYGON:
672
+ hash = rgeo_geos_polygon_hash(context, sub_geom, hash);
673
+ break;
674
+ case GEOS_GEOMETRYCOLLECTION:
675
+ case GEOS_MULTIPOINT:
676
+ case GEOS_MULTILINESTRING:
677
+ case GEOS_MULTIPOLYGON:
678
+ hash = rgeo_geos_geometry_collection_hash(context, sub_geom, hash);
679
+ break;
680
+ }
681
+ }
682
+ }
683
+ }
684
+ }
685
+ return hash;
686
+ }
687
+
688
+
606
689
  RGEO_END_C
607
690
 
608
691
  #endif