rgeo-dschee 0.5.4

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 (176) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +29 -0
  3. data/ext/geos_c_impl/coordinates.c +65 -0
  4. data/ext/geos_c_impl/coordinates.h +2 -0
  5. data/ext/geos_c_impl/extconf.rb +43 -0
  6. data/ext/geos_c_impl/factory.c +995 -0
  7. data/ext/geos_c_impl/factory.h +238 -0
  8. data/ext/geos_c_impl/geometry.c +1093 -0
  9. data/ext/geos_c_impl/geometry.h +23 -0
  10. data/ext/geos_c_impl/geometry_collection.c +757 -0
  11. data/ext/geos_c_impl/geometry_collection.h +46 -0
  12. data/ext/geos_c_impl/line_string.c +675 -0
  13. data/ext/geos_c_impl/line_string.h +32 -0
  14. data/ext/geos_c_impl/main.c +40 -0
  15. data/ext/geos_c_impl/point.c +236 -0
  16. data/ext/geos_c_impl/point.h +30 -0
  17. data/ext/geos_c_impl/polygon.c +359 -0
  18. data/ext/geos_c_impl/polygon.h +43 -0
  19. data/ext/geos_c_impl/preface.h +38 -0
  20. data/ext/proj4_c_impl/extconf.rb +62 -0
  21. data/ext/proj4_c_impl/main.c +315 -0
  22. data/lib/rgeo.rb +89 -0
  23. data/lib/rgeo/cartesian.rb +25 -0
  24. data/lib/rgeo/cartesian/analysis.rb +77 -0
  25. data/lib/rgeo/cartesian/bounding_box.rb +398 -0
  26. data/lib/rgeo/cartesian/calculations.rb +113 -0
  27. data/lib/rgeo/cartesian/factory.rb +347 -0
  28. data/lib/rgeo/cartesian/feature_classes.rb +100 -0
  29. data/lib/rgeo/cartesian/feature_methods.rb +88 -0
  30. data/lib/rgeo/cartesian/interface.rb +135 -0
  31. data/lib/rgeo/coord_sys.rb +43 -0
  32. data/lib/rgeo/coord_sys/cs/entities.rb +1315 -0
  33. data/lib/rgeo/coord_sys/cs/factories.rb +148 -0
  34. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +272 -0
  35. data/lib/rgeo/coord_sys/proj4.rb +293 -0
  36. data/lib/rgeo/coord_sys/srs_database/interface.rb +115 -0
  37. data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +140 -0
  38. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +62 -0
  39. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +63 -0
  40. data/lib/rgeo/error.rb +27 -0
  41. data/lib/rgeo/feature.rb +54 -0
  42. data/lib/rgeo/feature/curve.rb +111 -0
  43. data/lib/rgeo/feature/factory.rb +278 -0
  44. data/lib/rgeo/feature/factory_generator.rb +96 -0
  45. data/lib/rgeo/feature/geometry.rb +624 -0
  46. data/lib/rgeo/feature/geometry_collection.rb +95 -0
  47. data/lib/rgeo/feature/line.rb +26 -0
  48. data/lib/rgeo/feature/line_string.rb +60 -0
  49. data/lib/rgeo/feature/linear_ring.rb +26 -0
  50. data/lib/rgeo/feature/mixins.rb +143 -0
  51. data/lib/rgeo/feature/multi_curve.rb +71 -0
  52. data/lib/rgeo/feature/multi_line_string.rb +26 -0
  53. data/lib/rgeo/feature/multi_point.rb +33 -0
  54. data/lib/rgeo/feature/multi_polygon.rb +57 -0
  55. data/lib/rgeo/feature/multi_surface.rb +73 -0
  56. data/lib/rgeo/feature/point.rb +84 -0
  57. data/lib/rgeo/feature/polygon.rb +97 -0
  58. data/lib/rgeo/feature/surface.rb +79 -0
  59. data/lib/rgeo/feature/types.rb +284 -0
  60. data/lib/rgeo/geographic.rb +40 -0
  61. data/lib/rgeo/geographic/factory.rb +450 -0
  62. data/lib/rgeo/geographic/interface.rb +489 -0
  63. data/lib/rgeo/geographic/proj4_projector.rb +58 -0
  64. data/lib/rgeo/geographic/projected_feature_classes.rb +107 -0
  65. data/lib/rgeo/geographic/projected_feature_methods.rb +212 -0
  66. data/lib/rgeo/geographic/projected_window.rb +383 -0
  67. data/lib/rgeo/geographic/simple_mercator_projector.rb +110 -0
  68. data/lib/rgeo/geographic/spherical_feature_classes.rb +100 -0
  69. data/lib/rgeo/geographic/spherical_feature_methods.rb +134 -0
  70. data/lib/rgeo/geographic/spherical_math.rb +188 -0
  71. data/lib/rgeo/geos.rb +89 -0
  72. data/lib/rgeo/geos/capi_factory.rb +470 -0
  73. data/lib/rgeo/geos/capi_feature_classes.rb +129 -0
  74. data/lib/rgeo/geos/ffi_factory.rb +592 -0
  75. data/lib/rgeo/geos/ffi_feature_classes.rb +83 -0
  76. data/lib/rgeo/geos/ffi_feature_methods.rb +574 -0
  77. data/lib/rgeo/geos/interface.rb +202 -0
  78. data/lib/rgeo/geos/utils.rb +74 -0
  79. data/lib/rgeo/geos/zm_factory.rb +405 -0
  80. data/lib/rgeo/geos/zm_feature_classes.rb +80 -0
  81. data/lib/rgeo/geos/zm_feature_methods.rb +344 -0
  82. data/lib/rgeo/impl_helper.rb +19 -0
  83. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +185 -0
  84. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +61 -0
  85. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +146 -0
  86. data/lib/rgeo/impl_helper/basic_point_methods.rb +104 -0
  87. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +87 -0
  88. data/lib/rgeo/impl_helper/math.rb +14 -0
  89. data/lib/rgeo/impl_helper/utils.rb +29 -0
  90. data/lib/rgeo/version.rb +3 -0
  91. data/lib/rgeo/wkrep.rb +37 -0
  92. data/lib/rgeo/wkrep/wkb_generator.rb +201 -0
  93. data/lib/rgeo/wkrep/wkb_parser.rb +251 -0
  94. data/lib/rgeo/wkrep/wkt_generator.rb +207 -0
  95. data/lib/rgeo/wkrep/wkt_parser.rb +415 -0
  96. data/lib/rgeo/yaml.rb +23 -0
  97. data/test/cartesian_analysis_test.rb +65 -0
  98. data/test/cartesian_bbox_test.rb +123 -0
  99. data/test/common/factory_tests.rb +78 -0
  100. data/test/common/geometry_collection_tests.rb +237 -0
  101. data/test/common/line_string_tests.rb +330 -0
  102. data/test/common/multi_line_string_tests.rb +182 -0
  103. data/test/common/multi_point_tests.rb +200 -0
  104. data/test/common/multi_polygon_tests.rb +191 -0
  105. data/test/common/point_tests.rb +370 -0
  106. data/test/common/polygon_tests.rb +261 -0
  107. data/test/coord_sys/ogc_cs_test.rb +342 -0
  108. data/test/coord_sys/proj4_srs_data_test.rb +41 -0
  109. data/test/coord_sys/proj4_test.rb +150 -0
  110. data/test/coord_sys/sr_org_test.rb +32 -0
  111. data/test/coord_sys/url_reader_test.rb +42 -0
  112. data/test/geos_capi/factory_test.rb +31 -0
  113. data/test/geos_capi/geometry_collection_test.rb +24 -0
  114. data/test/geos_capi/line_string_test.rb +24 -0
  115. data/test/geos_capi/misc_test.rb +116 -0
  116. data/test/geos_capi/multi_line_string_test.rb +24 -0
  117. data/test/geos_capi/multi_point_test.rb +24 -0
  118. data/test/geos_capi/multi_polygon_test.rb +39 -0
  119. data/test/geos_capi/parsing_unparsing_test.rb +40 -0
  120. data/test/geos_capi/point_test.rb +72 -0
  121. data/test/geos_capi/polygon_test.rb +154 -0
  122. data/test/geos_capi/zmfactory_test.rb +57 -0
  123. data/test/geos_ffi/factory_test.rb +31 -0
  124. data/test/geos_ffi/geometry_collection_test.rb +24 -0
  125. data/test/geos_ffi/line_string_test.rb +24 -0
  126. data/test/geos_ffi/misc_test.rb +63 -0
  127. data/test/geos_ffi/multi_line_string_test.rb +24 -0
  128. data/test/geos_ffi/multi_point_test.rb +24 -0
  129. data/test/geos_ffi/multi_polygon_test.rb +33 -0
  130. data/test/geos_ffi/parsing_unparsing_test.rb +41 -0
  131. data/test/geos_ffi/point_test.rb +77 -0
  132. data/test/geos_ffi/polygon_test.rb +46 -0
  133. data/test/geos_ffi/zmfactory_test.rb +58 -0
  134. data/test/mixins_test.rb +141 -0
  135. data/test/oneoff_test.rb +26 -0
  136. data/test/projected_geographic/factory_test.rb +25 -0
  137. data/test/projected_geographic/geometry_collection_test.rb +24 -0
  138. data/test/projected_geographic/line_string_test.rb +24 -0
  139. data/test/projected_geographic/multi_line_string_test.rb +26 -0
  140. data/test/projected_geographic/multi_point_test.rb +30 -0
  141. data/test/projected_geographic/multi_polygon_test.rb +25 -0
  142. data/test/projected_geographic/point_test.rb +51 -0
  143. data/test/projected_geographic/polygon_test.rb +24 -0
  144. data/test/simple_cartesian/calculations_test.rb +99 -0
  145. data/test/simple_cartesian/factory_test.rb +27 -0
  146. data/test/simple_cartesian/geometry_collection_test.rb +30 -0
  147. data/test/simple_cartesian/line_string_test.rb +31 -0
  148. data/test/simple_cartesian/multi_line_string_test.rb +28 -0
  149. data/test/simple_cartesian/multi_point_test.rb +31 -0
  150. data/test/simple_cartesian/multi_polygon_test.rb +31 -0
  151. data/test/simple_cartesian/point_test.rb +50 -0
  152. data/test/simple_cartesian/polygon_test.rb +28 -0
  153. data/test/simple_mercator/factory_test.rb +25 -0
  154. data/test/simple_mercator/geometry_collection_test.rb +24 -0
  155. data/test/simple_mercator/line_string_test.rb +24 -0
  156. data/test/simple_mercator/multi_line_string_test.rb +26 -0
  157. data/test/simple_mercator/multi_point_test.rb +29 -0
  158. data/test/simple_mercator/multi_polygon_test.rb +25 -0
  159. data/test/simple_mercator/point_test.rb +55 -0
  160. data/test/simple_mercator/polygon_test.rb +24 -0
  161. data/test/simple_mercator/window_test.rb +173 -0
  162. data/test/spherical_geographic/calculations_test.rb +167 -0
  163. data/test/spherical_geographic/factory_test.rb +27 -0
  164. data/test/spherical_geographic/geometry_collection_test.rb +31 -0
  165. data/test/spherical_geographic/line_string_test.rb +31 -0
  166. data/test/spherical_geographic/multi_line_string_test.rb +29 -0
  167. data/test/spherical_geographic/multi_point_test.rb +31 -0
  168. data/test/spherical_geographic/multi_polygon_test.rb +31 -0
  169. data/test/spherical_geographic/point_test.rb +78 -0
  170. data/test/spherical_geographic/polygon_test.rb +28 -0
  171. data/test/types_test.rb +42 -0
  172. data/test/wkrep/wkb_generator_test.rb +185 -0
  173. data/test/wkrep/wkb_parser_test.rb +293 -0
  174. data/test/wkrep/wkt_generator_test.rb +294 -0
  175. data/test/wkrep/wkt_parser_test.rb +412 -0
  176. metadata +386 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b770e3205397a190e8c9aca08639f72cbfe7d75
4
+ data.tar.gz: 3ec50f8005b59c5210d1fa3157a2d7e1630f8a0d
5
+ SHA512:
6
+ metadata.gz: 5a394e4246058cd2e5027eed2f129776b2ea0613928f08662c40476bcf1d43a786ca5bedf7a756848496401bd276266f1bf48ef8da8a452abe446071b23f5ff9
7
+ data.tar.gz: 4945f5d4eba7790b5a8865e2906053e8c172c11b13cabd8d42a32a9e20470c4515b2a12f2f68ad0deb28aa00b6a3dd3dba4982cd5b649d833f2f312ed4ae0447
data/LICENSE.txt ADDED
@@ -0,0 +1,29 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright 2012 Daniel Azuma
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ # * Neither the name of the copyright holder, nor the names of any other
15
+ # contributors to this software, may be used to endorse or promote products
16
+ # derived from this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ # POSSIBILITY OF SUCH DAMAGE.
29
+ # -----------------------------------------------------------------------------
@@ -0,0 +1,65 @@
1
+ #include <ruby.h>
2
+ #include <geos_c.h>
3
+
4
+
5
+ VALUE extract_points_from_coordinate_sequence(GEOSContextHandle_t context, const GEOSCoordSequence* coord_sequence, int zCoordinate)
6
+ {
7
+ VALUE result = Qnil;
8
+ VALUE point;
9
+ unsigned int count;
10
+ unsigned int i;
11
+ double val;
12
+
13
+ if(GEOSCoordSeq_getSize_r(context, coord_sequence, &count)) {
14
+ result = rb_ary_new2(count);
15
+ for(i = 0; i < count; ++i) {
16
+ if(zCoordinate) {
17
+ point = rb_ary_new2(3);
18
+ } else {
19
+ point = rb_ary_new2(2);
20
+ }
21
+ GEOSCoordSeq_getX_r(context, coord_sequence, i, &val);
22
+ rb_ary_push(point, rb_float_new(val));
23
+ GEOSCoordSeq_getY_r(context, coord_sequence, i, &val);
24
+ rb_ary_push(point, rb_float_new(val));
25
+ if(zCoordinate) {
26
+ GEOSCoordSeq_getZ_r(context, coord_sequence, i, &val);
27
+ rb_ary_push(point, rb_float_new(val));
28
+ }
29
+ rb_ary_push(result, point);
30
+ }
31
+ }
32
+
33
+ return result;
34
+ }
35
+
36
+ VALUE extract_points_from_polygon(GEOSContextHandle_t context, const GEOSGeometry* polygon, int zCoordinate)
37
+ {
38
+ VALUE result = Qnil;
39
+
40
+ const GEOSGeometry* ring;
41
+ const GEOSCoordSequence* coord_sequence;
42
+ unsigned int interior_ring_count;
43
+ unsigned int i;
44
+
45
+ if (polygon) {
46
+ ring = GEOSGetExteriorRing_r(context, polygon);
47
+ coord_sequence = GEOSGeom_getCoordSeq_r(context, ring);
48
+
49
+ if(coord_sequence) {
50
+ interior_ring_count = GEOSGetNumInteriorRings_r(context, polygon);
51
+ result = rb_ary_new2(interior_ring_count + 1); // exterior + inner rings
52
+
53
+ rb_ary_push(result, extract_points_from_coordinate_sequence(context, coord_sequence, zCoordinate));
54
+
55
+ for(i = 0; i < interior_ring_count; ++i) {
56
+ ring = GEOSGetInteriorRingN_r(context, polygon, i);
57
+ coord_sequence = GEOSGeom_getCoordSeq_r(context, ring);
58
+ if(coord_sequence) {
59
+ rb_ary_push(result, extract_points_from_coordinate_sequence(context, coord_sequence, zCoordinate));
60
+ }
61
+ }
62
+ }
63
+ }
64
+ return result;
65
+ }
@@ -0,0 +1,2 @@
1
+ VALUE extract_points_from_coordinate_sequence(GEOSContextHandle_t context, const GEOSCoordSequence* coord_sequence, int zCoordinate);
2
+ VALUE extract_points_from_polygon(GEOSContextHandle_t context, const GEOSGeometry* polygon, int zCoordinate);
@@ -0,0 +1,43 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Makefile builder for GEOS wrapper
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ def create_dummy_makefile
7
+ ::File.open("Makefile", "w") { |f_| f_.write(".PHONY: install\ninstall:\n") }
8
+ end
9
+
10
+ if ::RUBY_DESCRIPTION =~ /^jruby\s/
11
+ create_dummy_makefile
12
+ else
13
+ require "mkmf"
14
+
15
+ geosconfig = with_config("geos-config") || find_executable("geos-config")
16
+
17
+ if geosconfig
18
+ puts "Using GEOS compile configuration from %s" [geosconfig]
19
+ $INCFLAGS << " " << `#{geosconfig} --cflags`.strip
20
+ geos_libs = `#{geosconfig} --clibs`.tr("\n", " ")
21
+ geos_libs.split(/\s+/).each do |flag|
22
+ $libs << " " + flag unless $libs.include?(flag)
23
+ end
24
+ end
25
+
26
+ found_geos_ = false
27
+ if have_header("geos_c.h")
28
+ found_geos_ = true if have_func("GEOSSetSRID_r", "geos_c.h")
29
+ have_func("GEOSPreparedContains_r", "geos_c.h")
30
+ have_func("GEOSPreparedDisjoint_r", "geos_c.h")
31
+ have_func("rb_memhash", "ruby.h")
32
+ end
33
+
34
+ if found_geos_
35
+ create_makefile("rgeo/geos/geos_c_impl")
36
+ else
37
+ puts "**** WARNING: Unable to find GEOS headers or libraries."
38
+ puts "**** Ensure that 'geos-config' is in your PATH or provide that full path via --with-geos-config"
39
+ puts "**** Compiling without GEOS support."
40
+
41
+ create_dummy_makefile
42
+ end
43
+ end
@@ -0,0 +1,995 @@
1
+ /*
2
+ Factory and utility functions for GEOS wrapper
3
+ */
4
+
5
+
6
+ #include "preface.h"
7
+
8
+ #ifdef RGEO_GEOS_SUPPORTED
9
+
10
+ #include <ruby.h>
11
+ #include <geos_c.h>
12
+
13
+ #include "factory.h"
14
+ #include "geometry.h"
15
+ #include "point.h"
16
+ #include "line_string.h"
17
+ #include "polygon.h"
18
+ #include "geometry_collection.h"
19
+
20
+ RGEO_BEGIN_C
21
+
22
+
23
+ /**** RUBY AND GEOS CALLBACKS ****/
24
+
25
+
26
+ // NOP message handler. GEOS requires that a message handler be set
27
+ // for every context handle.
28
+
29
+ static void message_handler(const char* fmt, ...)
30
+ {
31
+ }
32
+
33
+
34
+ // Destroy function for factory data. We destroy any serialization
35
+ // objects that have been created for the factory, and then destroy
36
+ // the GEOS context, before freeing the factory data itself.
37
+
38
+ static void destroy_factory_func(RGeo_FactoryData* data)
39
+ {
40
+ GEOSContextHandle_t context;
41
+
42
+ context = data->geos_context;
43
+ if (data->wkt_reader) {
44
+ GEOSWKTReader_destroy_r(context, data->wkt_reader);
45
+ }
46
+ if (data->wkb_reader) {
47
+ GEOSWKBReader_destroy_r(context, data->wkb_reader);
48
+ }
49
+ if (data->wkt_writer) {
50
+ GEOSWKTWriter_destroy_r(context, data->wkt_writer);
51
+ }
52
+ if (data->wkb_writer) {
53
+ GEOSWKBWriter_destroy_r(context, data->wkb_writer);
54
+ }
55
+ if (data->psych_wkt_reader) {
56
+ GEOSWKTReader_destroy_r(context, data->psych_wkt_reader);
57
+ }
58
+ if (data->marshal_wkb_reader) {
59
+ GEOSWKBReader_destroy_r(context, data->marshal_wkb_reader);
60
+ }
61
+ if (data->psych_wkt_writer) {
62
+ GEOSWKTWriter_destroy_r(context, data->psych_wkt_writer);
63
+ }
64
+ if (data->marshal_wkb_writer) {
65
+ GEOSWKBWriter_destroy_r(context, data->marshal_wkb_writer);
66
+ }
67
+ finishGEOS_r(context);
68
+ free(data);
69
+ }
70
+
71
+
72
+ // Destroy function for geometry data. We destroy the internal
73
+ // GEOS geometry (if present) before freeing the data itself.
74
+
75
+ static void destroy_geometry_func(RGeo_GeometryData* data)
76
+ {
77
+ const GEOSPreparedGeometry* prep;
78
+
79
+ if (data->geom) {
80
+ GEOSGeom_destroy_r(data->geos_context, data->geom);
81
+ }
82
+ prep = data->prep;
83
+ if (prep && prep != (const GEOSPreparedGeometry*)1 && prep != (const GEOSPreparedGeometry*)2 &&
84
+ prep != (const GEOSPreparedGeometry*)3)
85
+ {
86
+ GEOSPreparedGeom_destroy_r(data->geos_context, prep);
87
+ }
88
+ free(data);
89
+ }
90
+
91
+
92
+ // Mark function for factory data. This marks the wkt and wkb generator
93
+ // handles so they don't get collected.
94
+
95
+ static void mark_factory_func(RGeo_FactoryData* data)
96
+ {
97
+ if (!NIL_P(data->wkrep_wkt_generator)) {
98
+ rb_gc_mark(data->wkrep_wkt_generator);
99
+ }
100
+ if (!NIL_P(data->wkrep_wkb_generator)) {
101
+ rb_gc_mark(data->wkrep_wkb_generator);
102
+ }
103
+ if (!NIL_P(data->wkrep_wkt_parser)) {
104
+ rb_gc_mark(data->wkrep_wkt_parser);
105
+ }
106
+ if (!NIL_P(data->wkrep_wkb_parser)) {
107
+ rb_gc_mark(data->wkrep_wkb_parser);
108
+ }
109
+ if (!NIL_P(data->proj4_obj)) {
110
+ rb_gc_mark(data->proj4_obj);
111
+ }
112
+ if (!NIL_P(data->coord_sys_obj)) {
113
+ rb_gc_mark(data->coord_sys_obj);
114
+ }
115
+ }
116
+
117
+
118
+ // Mark function for geometry data. This marks the factory and klasses
119
+ // held by the geometry so those don't get collected.
120
+
121
+ static void mark_geometry_func(RGeo_GeometryData* data)
122
+ {
123
+ if (!NIL_P(data->factory)) {
124
+ rb_gc_mark(data->factory);
125
+ }
126
+ if (!NIL_P(data->klasses)) {
127
+ rb_gc_mark(data->klasses);
128
+ }
129
+ }
130
+
131
+
132
+ // Destroy function for globals data. We don't need to destroy any
133
+ // auxiliary data for now...
134
+
135
+ static void destroy_globals_func(RGeo_Globals* data)
136
+ {
137
+ free(data);
138
+ }
139
+
140
+
141
+ // Mark function for globals data. This should mark any globals that
142
+ // need to be held through garbage collection (none at the moment.)
143
+
144
+ static void mark_globals_func(RGeo_Globals* data)
145
+ {
146
+ }
147
+
148
+
149
+ /**** RUBY METHOD DEFINITIONS ****/
150
+
151
+
152
+ static VALUE method_factory_srid(VALUE self)
153
+ {
154
+ return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->srid);
155
+ }
156
+
157
+
158
+ static VALUE method_factory_buffer_resolution(VALUE self)
159
+ {
160
+ return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->buffer_resolution);
161
+ }
162
+
163
+
164
+ static VALUE method_factory_flags(VALUE self)
165
+ {
166
+ return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->flags);
167
+ }
168
+
169
+
170
+ static VALUE method_factory_parse_wkt(VALUE self, VALUE str)
171
+ {
172
+ RGeo_FactoryData* self_data;
173
+ GEOSContextHandle_t self_context;
174
+ GEOSWKTReader* wkt_reader;
175
+ VALUE result;
176
+ GEOSGeometry* geom;
177
+
178
+ Check_Type(str, T_STRING);
179
+ self_data = RGEO_FACTORY_DATA_PTR(self);
180
+ self_context = self_data->geos_context;
181
+ wkt_reader = self_data->wkt_reader;
182
+ if (!wkt_reader) {
183
+ wkt_reader = GEOSWKTReader_create_r(self_context);
184
+ self_data->wkt_reader = wkt_reader;
185
+ }
186
+ result = Qnil;
187
+ if (wkt_reader) {
188
+ geom = GEOSWKTReader_read_r(self_context, wkt_reader, RSTRING_PTR(str));
189
+ if (geom) {
190
+ result = rgeo_wrap_geos_geometry(self, geom, Qnil);
191
+ }
192
+ }
193
+ return result;
194
+ }
195
+
196
+
197
+ static VALUE method_factory_parse_wkb(VALUE self, VALUE str)
198
+ {
199
+ RGeo_FactoryData* self_data;
200
+ GEOSContextHandle_t self_context;
201
+ GEOSWKBReader* wkb_reader;
202
+ VALUE result;
203
+ GEOSGeometry* geom;
204
+
205
+ Check_Type(str, T_STRING);
206
+ self_data = RGEO_FACTORY_DATA_PTR(self);
207
+ self_context = self_data->geos_context;
208
+ wkb_reader = self_data->wkb_reader;
209
+ if (!wkb_reader) {
210
+ wkb_reader = GEOSWKBReader_create_r(self_context);
211
+ self_data->wkb_reader = wkb_reader;
212
+ }
213
+ result = Qnil;
214
+ if (wkb_reader) {
215
+ geom = GEOSWKBReader_read_r(self_context, wkb_reader, (unsigned char*)RSTRING_PTR(str), (size_t)RSTRING_LEN(str));
216
+ if (geom) {
217
+ result = rgeo_wrap_geos_geometry(self, geom, Qnil);
218
+ }
219
+ }
220
+ return result;
221
+ }
222
+
223
+
224
+ static VALUE method_factory_read_for_marshal(VALUE self, VALUE str)
225
+ {
226
+ RGeo_FactoryData* self_data;
227
+ GEOSContextHandle_t self_context;
228
+ GEOSWKBReader* wkb_reader;
229
+ VALUE result;
230
+ GEOSGeometry* geom;
231
+
232
+ Check_Type(str, T_STRING);
233
+ self_data = RGEO_FACTORY_DATA_PTR(self);
234
+ self_context = self_data->geos_context;
235
+ wkb_reader = self_data->marshal_wkb_reader;
236
+ if (!wkb_reader) {
237
+ wkb_reader = GEOSWKBReader_create_r(self_context);
238
+ self_data->marshal_wkb_reader = wkb_reader;
239
+ }
240
+ result = Qnil;
241
+ if (wkb_reader) {
242
+ geom = GEOSWKBReader_read_r(self_context, wkb_reader, (unsigned char*)RSTRING_PTR(str), (size_t)RSTRING_LEN(str));
243
+ if (geom) {
244
+ result = rgeo_wrap_geos_geometry(self, geom, Qnil);
245
+ }
246
+ }
247
+ return result;
248
+ }
249
+
250
+
251
+ static VALUE method_factory_read_for_psych(VALUE self, VALUE str)
252
+ {
253
+ RGeo_FactoryData* self_data;
254
+ GEOSContextHandle_t self_context;
255
+ GEOSWKTReader* wkt_reader;
256
+ VALUE result;
257
+ GEOSGeometry* geom;
258
+
259
+ Check_Type(str, T_STRING);
260
+ self_data = RGEO_FACTORY_DATA_PTR(self);
261
+ self_context = self_data->geos_context;
262
+ wkt_reader = self_data->psych_wkt_reader;
263
+ if (!wkt_reader) {
264
+ wkt_reader = GEOSWKTReader_create_r(self_context);
265
+ self_data->psych_wkt_reader = wkt_reader;
266
+ }
267
+ result = Qnil;
268
+ if (wkt_reader) {
269
+ geom = GEOSWKTReader_read_r(self_context, wkt_reader, RSTRING_PTR(str));
270
+ if (geom) {
271
+ result = rgeo_wrap_geos_geometry(self, geom, Qnil);
272
+ }
273
+ }
274
+ return result;
275
+ }
276
+
277
+
278
+ static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
279
+ {
280
+ RGeo_FactoryData* self_data;
281
+ GEOSContextHandle_t self_context;
282
+ GEOSWKBWriter* wkb_writer;
283
+ const GEOSGeometry* geom;
284
+ VALUE result;
285
+ char* str;
286
+ size_t size;
287
+ char has_3d;
288
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
289
+ RGeo_Globals* globals;
290
+ VALUE wkb_generator;
291
+ #endif
292
+
293
+ self_data = RGEO_FACTORY_DATA_PTR(self);
294
+ self_context = self_data->geos_context;
295
+ has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
296
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
297
+ if (has_3d) {
298
+ globals = self_data->globals;
299
+ wkb_generator = globals->marshal_wkb_generator;
300
+ if (NIL_P(wkb_generator)) {
301
+ wkb_generator = rb_funcall(
302
+ rb_const_get_at(globals->geos_module, rb_intern("Utils")),
303
+ rb_intern("marshal_wkb_generator"), 0);
304
+ globals->marshal_wkb_generator = wkb_generator;
305
+ }
306
+ return rb_funcall(wkb_generator, globals->id_generate, 1, obj);
307
+ }
308
+ #endif
309
+ wkb_writer = self_data->marshal_wkb_writer;
310
+ if (!wkb_writer) {
311
+ wkb_writer = GEOSWKBWriter_create_r(self_context);
312
+ if (has_3d) {
313
+ GEOSWKBWriter_setOutputDimension_r(self_context, wkb_writer, 3);
314
+ }
315
+ self_data->marshal_wkb_writer = wkb_writer;
316
+ }
317
+ result = Qnil;
318
+ if (wkb_writer) {
319
+ geom = rgeo_get_geos_geometry_safe(obj);
320
+ if (geom) {
321
+ str = (char*)GEOSWKBWriter_write_r(self_context, wkb_writer, geom, &size);
322
+ if (str) {
323
+ result = rb_str_new(str, size);
324
+ GEOSFree_r(self_context, str);
325
+ }
326
+ }
327
+ }
328
+ return result;
329
+ }
330
+
331
+
332
+ static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
333
+ {
334
+ RGeo_FactoryData* self_data;
335
+ GEOSContextHandle_t self_context;
336
+ GEOSWKTWriter* wkt_writer;
337
+ const GEOSGeometry* geom;
338
+ VALUE result;
339
+ char* str;
340
+ size_t size;
341
+ char has_3d;
342
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
343
+ RGeo_Globals* globals;
344
+ VALUE wkt_generator;
345
+ #endif
346
+
347
+ self_data = RGEO_FACTORY_DATA_PTR(self);
348
+ self_context = self_data->geos_context;
349
+ has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
350
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
351
+ if (has_3d) {
352
+ globals = self_data->globals;
353
+ wkt_generator = globals->psych_wkt_generator;
354
+ if (NIL_P(wkt_generator)) {
355
+ wkt_generator = rb_funcall(
356
+ rb_const_get_at(globals->geos_module, rb_intern("Utils")),
357
+ rb_intern("psych_wkt_generator"), 0);
358
+ globals->psych_wkt_generator = wkt_generator;
359
+ }
360
+ return rb_funcall(wkt_generator, globals->id_generate, 1, obj);
361
+ }
362
+ #endif
363
+ wkt_writer = self_data->psych_wkt_writer;
364
+ if (!wkt_writer) {
365
+ wkt_writer = GEOSWKTWriter_create_r(self_context);
366
+ if (has_3d) {
367
+ GEOSWKTWriter_setOutputDimension_r(self_context, wkt_writer, 3);
368
+ }
369
+ self_data->psych_wkt_writer = wkt_writer;
370
+ }
371
+ result = Qnil;
372
+ if (wkt_writer) {
373
+ geom = rgeo_get_geos_geometry_safe(obj);
374
+ if (geom) {
375
+ str = GEOSWKTWriter_write_r(self_context, wkt_writer, geom);
376
+ if (str) {
377
+ result = rb_str_new2(str);
378
+ GEOSFree_r(self_context, str);
379
+ }
380
+ }
381
+ }
382
+ return result;
383
+ }
384
+
385
+
386
+ static VALUE cmethod_factory_geos_version(VALUE klass)
387
+ {
388
+ return rb_str_new2(GEOS_VERSION);
389
+ }
390
+
391
+
392
+ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE buffer_resolution,
393
+ VALUE wkt_generator, VALUE wkb_generator, VALUE proj4_obj, VALUE coord_sys_obj)
394
+ {
395
+ VALUE result;
396
+ RGeo_FactoryData* data;
397
+ GEOSContextHandle_t context;
398
+ VALUE wrapped_globals;
399
+
400
+ result = Qnil;
401
+ data = ALLOC(RGeo_FactoryData);
402
+ if (data) {
403
+ context = initGEOS_r(message_handler, message_handler);
404
+ if (context) {
405
+ wrapped_globals = rb_const_get_at(klass, rb_intern("INTERNAL_CGLOBALS"));
406
+ data->globals = (RGeo_Globals*)DATA_PTR(wrapped_globals);
407
+ data->geos_context = context;
408
+ data->flags = NUM2INT(flags);
409
+ data->srid = NUM2INT(srid);
410
+ data->buffer_resolution = NUM2INT(buffer_resolution);
411
+ data->wkt_reader = NULL;
412
+ data->wkb_reader = NULL;
413
+ data->wkt_writer = NULL;
414
+ data->wkb_writer = NULL;
415
+ data->psych_wkt_reader = NULL;
416
+ data->marshal_wkb_reader = NULL;
417
+ data->psych_wkt_writer = NULL;
418
+ data->marshal_wkb_writer = NULL;
419
+ data->wkrep_wkt_generator = wkt_generator;
420
+ data->wkrep_wkb_generator = wkb_generator;
421
+ data->wkrep_wkt_parser = Qnil;
422
+ data->wkrep_wkb_parser = Qnil;
423
+ data->proj4_obj = proj4_obj;
424
+ data->coord_sys_obj = coord_sys_obj;
425
+ result = Data_Wrap_Struct(klass, mark_factory_func, destroy_factory_func, data);
426
+ }
427
+ else {
428
+ free(data);
429
+ }
430
+ }
431
+ return result;
432
+ }
433
+
434
+
435
+ static VALUE alloc_factory(VALUE klass)
436
+ {
437
+ return cmethod_factory_create(klass, INT2NUM(0), INT2NUM(0), INT2NUM(0), Qnil, Qnil, Qnil, Qnil);
438
+ }
439
+
440
+
441
+ static VALUE method_factory_initialize_copy(VALUE self, VALUE orig)
442
+ {
443
+ RGeo_FactoryData* self_data;
444
+ RGeo_FactoryData* orig_data;
445
+ GEOSContextHandle_t context;
446
+
447
+ // Clear out existing data
448
+ self_data = RGEO_FACTORY_DATA_PTR(self);
449
+ context = self_data->geos_context;
450
+ if (self_data->wkt_reader) {
451
+ GEOSWKTReader_destroy_r(context, self_data->wkt_reader);
452
+ self_data->wkt_reader = NULL;
453
+ }
454
+ if (self_data->wkb_reader) {
455
+ GEOSWKBReader_destroy_r(context, self_data->wkb_reader);
456
+ self_data->wkb_reader = NULL;
457
+ }
458
+ if (self_data->wkt_writer) {
459
+ GEOSWKTWriter_destroy_r(context, self_data->wkt_writer);
460
+ self_data->wkt_writer = NULL;
461
+ }
462
+ if (self_data->wkb_writer) {
463
+ GEOSWKBWriter_destroy_r(context, self_data->wkb_writer);
464
+ self_data->wkb_writer = NULL;
465
+ }
466
+ if (self_data->psych_wkt_reader) {
467
+ GEOSWKTReader_destroy_r(context, self_data->psych_wkt_reader);
468
+ self_data->psych_wkt_reader = NULL;
469
+ }
470
+ if (self_data->marshal_wkb_reader) {
471
+ GEOSWKBReader_destroy_r(context, self_data->marshal_wkb_reader);
472
+ self_data->marshal_wkb_reader = NULL;
473
+ }
474
+ if (self_data->psych_wkt_writer) {
475
+ GEOSWKTWriter_destroy_r(context, self_data->psych_wkt_writer);
476
+ self_data->psych_wkt_writer = NULL;
477
+ }
478
+ if (self_data->marshal_wkb_writer) {
479
+ GEOSWKBWriter_destroy_r(context, self_data->marshal_wkb_writer);
480
+ self_data->marshal_wkb_writer = NULL;
481
+ }
482
+ self_data->wkrep_wkt_generator = Qnil;
483
+ self_data->wkrep_wkb_generator = Qnil;
484
+ self_data->wkrep_wkt_parser = Qnil;
485
+ self_data->wkrep_wkb_parser = Qnil;
486
+ self_data->proj4_obj = Qnil;
487
+ self_data->coord_sys_obj = Qnil;
488
+
489
+ // Copy new data from original object
490
+ if (TYPE(orig) == T_DATA && RDATA(orig)->dfree == (RUBY_DATA_FUNC)destroy_factory_func) {
491
+ orig_data = RGEO_FACTORY_DATA_PTR(orig);
492
+ self_data->flags = orig_data->flags;
493
+ self_data->srid = orig_data->srid;
494
+ self_data->buffer_resolution = orig_data->buffer_resolution;
495
+ self_data->wkrep_wkt_generator = orig_data->wkrep_wkt_generator;
496
+ self_data->wkrep_wkb_generator = orig_data->wkrep_wkb_generator;
497
+ self_data->wkrep_wkt_parser = orig_data->wkrep_wkt_parser;
498
+ self_data->wkrep_wkb_parser = orig_data->wkrep_wkb_parser;
499
+ self_data->proj4_obj = orig_data->proj4_obj;
500
+ self_data->coord_sys_obj = orig_data->coord_sys_obj;
501
+ }
502
+ return self;
503
+ }
504
+
505
+
506
+ static VALUE method_set_wkrep_parsers(VALUE self, VALUE wkt_parser, VALUE wkb_parser)
507
+ {
508
+ RGeo_FactoryData* self_data;
509
+
510
+ self_data = RGEO_FACTORY_DATA_PTR(self);
511
+ self_data->wkrep_wkt_parser = wkt_parser;
512
+ self_data->wkrep_wkb_parser = wkb_parser;
513
+
514
+ return self;
515
+ }
516
+
517
+
518
+ static VALUE method_get_proj4(VALUE self)
519
+ {
520
+ return RGEO_FACTORY_DATA_PTR(self)->proj4_obj;
521
+ }
522
+
523
+
524
+ static VALUE method_get_coord_sys(VALUE self)
525
+ {
526
+ return RGEO_FACTORY_DATA_PTR(self)->coord_sys_obj;
527
+ }
528
+
529
+
530
+ static VALUE method_get_wkt_generator(VALUE self)
531
+ {
532
+ return RGEO_FACTORY_DATA_PTR(self)->wkrep_wkt_generator;
533
+ }
534
+
535
+
536
+ static VALUE method_get_wkb_generator(VALUE self)
537
+ {
538
+ return RGEO_FACTORY_DATA_PTR(self)->wkrep_wkb_generator;
539
+ }
540
+
541
+
542
+ static VALUE method_get_wkt_parser(VALUE self)
543
+ {
544
+ return RGEO_FACTORY_DATA_PTR(self)->wkrep_wkt_parser;
545
+ }
546
+
547
+
548
+ static VALUE method_get_wkb_parser(VALUE self)
549
+ {
550
+ return RGEO_FACTORY_DATA_PTR(self)->wkrep_wkb_parser;
551
+ }
552
+
553
+
554
+ static VALUE alloc_geometry(VALUE klass)
555
+ {
556
+ return rgeo_wrap_geos_geometry(Qnil, NULL, klass);
557
+ }
558
+
559
+
560
+ /**** INITIALIZATION FUNCTION ****/
561
+
562
+
563
+ RGeo_Globals* rgeo_init_geos_factory()
564
+ {
565
+ RGeo_Globals* globals;
566
+ VALUE rgeo_module;
567
+ VALUE geos_factory_class;
568
+ VALUE wrapped_globals;
569
+ VALUE feature_module;
570
+
571
+ globals = ALLOC(RGeo_Globals);
572
+
573
+ // Cache some modules so we don't have to look them up by name every time
574
+ rgeo_module = rb_define_module("RGeo");
575
+ feature_module = rb_define_module_under(rgeo_module, "Feature");
576
+ globals->feature_module = feature_module;
577
+ globals->geos_module = rb_define_module_under(rgeo_module, "Geos");
578
+ globals->feature_geometry = rb_const_get_at(feature_module, rb_intern("Geometry"));
579
+ globals->feature_point = rb_const_get_at(feature_module, rb_intern("Point"));
580
+ globals->feature_line_string = rb_const_get_at(feature_module, rb_intern("LineString"));
581
+ globals->feature_linear_ring = rb_const_get_at(feature_module, rb_intern("LinearRing"));
582
+ globals->feature_line = rb_const_get_at(feature_module, rb_intern("Line"));
583
+ globals->feature_polygon = rb_const_get_at(feature_module, rb_intern("Polygon"));
584
+ globals->feature_geometry_collection = rb_const_get_at(feature_module, rb_intern("GeometryCollection"));
585
+ globals->feature_multi_point = rb_const_get_at(feature_module, rb_intern("MultiPoint"));
586
+ globals->feature_multi_line_string = rb_const_get_at(feature_module, rb_intern("MultiLineString"));
587
+ globals->feature_multi_polygon = rb_const_get_at(feature_module, rb_intern("MultiPolygon"));
588
+
589
+ // Cache some commonly used names
590
+ globals->id_cast = rb_intern("cast");
591
+ globals->id_eql = rb_intern("eql?");
592
+ globals->id_generate = rb_intern("generate");
593
+ globals->id_enum_for = rb_intern("enum_for");
594
+ globals->id_hash = rb_intern("hash");
595
+ globals->sym_force_new = ID2SYM(rb_intern("force_new"));
596
+ globals->sym_keep_subtype = ID2SYM(rb_intern("keep_subtype"));
597
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
598
+ globals->psych_wkt_generator = Qnil;
599
+ globals->marshal_wkb_generator = Qnil;
600
+ #endif
601
+
602
+ // Add C methods to the factory.
603
+ geos_factory_class = rb_define_class_under(globals->geos_module, "CAPIFactory", rb_cObject);
604
+ rb_define_alloc_func(geos_factory_class, alloc_factory);
605
+ rb_define_method(geos_factory_class, "initialize_copy", method_factory_initialize_copy, 1);
606
+ rb_define_method(geos_factory_class, "_parse_wkt_impl", method_factory_parse_wkt, 1);
607
+ rb_define_method(geos_factory_class, "_parse_wkb_impl", method_factory_parse_wkb, 1);
608
+ rb_define_method(geos_factory_class, "_srid", method_factory_srid, 0);
609
+ rb_define_method(geos_factory_class, "_buffer_resolution", method_factory_buffer_resolution, 0);
610
+ rb_define_method(geos_factory_class, "_flags", method_factory_flags, 0);
611
+ rb_define_method(geos_factory_class, "_set_wkrep_parsers", method_set_wkrep_parsers, 2);
612
+ rb_define_method(geos_factory_class, "_proj4", method_get_proj4, 0);
613
+ rb_define_method(geos_factory_class, "_coord_sys", method_get_coord_sys, 0);
614
+ rb_define_method(geos_factory_class, "_wkt_generator", method_get_wkt_generator, 0);
615
+ rb_define_method(geos_factory_class, "_wkb_generator", method_get_wkb_generator, 0);
616
+ rb_define_method(geos_factory_class, "_wkt_parser", method_get_wkt_parser, 0);
617
+ rb_define_method(geos_factory_class, "_wkb_parser", method_get_wkb_parser, 0);
618
+ rb_define_method(geos_factory_class, "_read_for_marshal", method_factory_read_for_marshal, 1);
619
+ rb_define_method(geos_factory_class, "_write_for_marshal", method_factory_write_for_marshal, 1);
620
+ rb_define_method(geos_factory_class, "_read_for_psych", method_factory_read_for_psych, 1);
621
+ rb_define_method(geos_factory_class, "_write_for_psych", method_factory_write_for_psych, 1);
622
+ rb_define_module_function(geos_factory_class, "_create", cmethod_factory_create, 7);
623
+ rb_define_module_function(geos_factory_class, "_geos_version", cmethod_factory_geos_version, 0);
624
+
625
+ // Pre-define implementation classes and set up allocation methods
626
+ globals->geos_geometry = rb_define_class_under(globals->geos_module, "CAPIGeometryImpl", rb_cObject);
627
+ rb_define_alloc_func(globals->geos_geometry, alloc_geometry);
628
+ globals->geos_point = rb_define_class_under(globals->geos_module, "CAPIPointImpl", rb_cObject);
629
+ rb_define_alloc_func(globals->geos_point, alloc_geometry);
630
+ globals->geos_line_string = rb_define_class_under(globals->geos_module, "CAPILineStringImpl", rb_cObject);
631
+ rb_define_alloc_func(globals->geos_line_string, alloc_geometry);
632
+ globals->geos_linear_ring = rb_define_class_under(globals->geos_module, "CAPILinearRingImpl", rb_cObject);
633
+ rb_define_alloc_func(globals->geos_linear_ring, alloc_geometry);
634
+ globals->geos_line = rb_define_class_under(globals->geos_module, "CAPILineImpl", rb_cObject);
635
+ rb_define_alloc_func(globals->geos_line, alloc_geometry);
636
+ globals->geos_polygon = rb_define_class_under(globals->geos_module, "CAPIPolygonImpl", rb_cObject);
637
+ rb_define_alloc_func(globals->geos_polygon, alloc_geometry);
638
+ globals->geos_geometry_collection = rb_define_class_under(globals->geos_module, "CAPIGeometryCollectionImpl", rb_cObject);
639
+ rb_define_alloc_func(globals->geos_geometry_collection, alloc_geometry);
640
+ globals->geos_multi_point = rb_define_class_under(globals->geos_module, "CAPIMultiPointImpl", rb_cObject);
641
+ rb_define_alloc_func(globals->geos_multi_point, alloc_geometry);
642
+ globals->geos_multi_line_string = rb_define_class_under(globals->geos_module, "CAPIMultiLineStringImpl", rb_cObject);
643
+ rb_define_alloc_func(globals->geos_multi_line_string, alloc_geometry);
644
+ globals->geos_multi_polygon = rb_define_class_under(globals->geos_module, "CAPIMultiPolygonImpl", rb_cObject);
645
+ rb_define_alloc_func(globals->geos_multi_polygon, alloc_geometry);
646
+
647
+ // Wrap the globals in a Ruby object and store it off so we have access
648
+ // to it later. Each factory instance will reference it internally.
649
+ wrapped_globals = Data_Wrap_Struct(rb_cObject, mark_globals_func, destroy_globals_func, globals);
650
+ rb_define_const(geos_factory_class, "INTERNAL_CGLOBALS", wrapped_globals);
651
+
652
+ return globals;
653
+ }
654
+
655
+
656
+ /**** OTHER PUBLIC FUNCTIONS ****/
657
+
658
+
659
+ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
660
+ {
661
+ VALUE result;
662
+ RGeo_FactoryData* factory_data;
663
+ GEOSContextHandle_t factory_context;
664
+ VALUE klasses;
665
+ RGeo_Globals* globals;
666
+ VALUE inferred_klass;
667
+ char is_collection;
668
+ RGeo_GeometryData* data;
669
+
670
+ result = Qnil;
671
+ if (geom || !NIL_P(klass)) {
672
+ factory_data = NIL_P(factory) ? NULL : RGEO_FACTORY_DATA_PTR(factory);
673
+ factory_context = factory_data ? factory_data->geos_context : NULL;
674
+ globals = factory_data ? factory_data->globals : NULL;
675
+
676
+ // We don't allow "empty" points, so replace such objects with
677
+ // an empty collection.
678
+ if (geom && factory) {
679
+ if (GEOSGeomTypeId_r(factory_context, geom) == GEOS_POINT && GEOSGetNumCoordinates_r(factory_context, geom) == 0) {
680
+ GEOSGeom_destroy_r(factory_context, geom);
681
+ geom = GEOSGeom_createCollection_r(factory_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
682
+ klass = globals->geos_geometry_collection;
683
+ }
684
+ }
685
+
686
+ klasses = Qnil;
687
+ if (TYPE(klass) != T_CLASS) {
688
+ inferred_klass = Qnil;
689
+ is_collection = 0;
690
+ switch (GEOSGeomTypeId_r(factory_context, geom)) {
691
+ case GEOS_POINT:
692
+ inferred_klass = globals->geos_point;
693
+ break;
694
+ case GEOS_LINESTRING:
695
+ inferred_klass = globals->geos_line_string;
696
+ break;
697
+ case GEOS_LINEARRING:
698
+ inferred_klass = globals->geos_linear_ring;
699
+ break;
700
+ case GEOS_POLYGON:
701
+ inferred_klass = globals->geos_polygon;
702
+ break;
703
+ case GEOS_MULTIPOINT:
704
+ inferred_klass = globals->geos_multi_point;
705
+ is_collection = 1;
706
+ break;
707
+ case GEOS_MULTILINESTRING:
708
+ inferred_klass = globals->geos_multi_line_string;
709
+ is_collection = 1;
710
+ break;
711
+ case GEOS_MULTIPOLYGON:
712
+ inferred_klass = globals->geos_multi_polygon;
713
+ is_collection = 1;
714
+ break;
715
+ case GEOS_GEOMETRYCOLLECTION:
716
+ inferred_klass = globals->geos_geometry_collection;
717
+ is_collection = 1;
718
+ break;
719
+ default:
720
+ inferred_klass = globals->geos_geometry;
721
+ break;
722
+ }
723
+ if (TYPE(klass) == T_ARRAY && is_collection) {
724
+ klasses = klass;
725
+ }
726
+ klass = inferred_klass;
727
+ }
728
+ data = ALLOC(RGeo_GeometryData);
729
+ if (data) {
730
+ if (geom) {
731
+ GEOSSetSRID_r(factory_context, geom, factory_data->srid);
732
+ }
733
+ data->geos_context = factory_context;
734
+ data->geom = geom;
735
+ data->prep = factory_data && ((factory_data->flags & RGEO_FACTORYFLAGS_PREPARE_HEURISTIC) != 0) ?
736
+ (GEOSPreparedGeometry*)1 : NULL;
737
+ data->factory = factory;
738
+ data->klasses = klasses;
739
+ result = Data_Wrap_Struct(klass, mark_geometry_func, destroy_geometry_func, data);
740
+ }
741
+ }
742
+ return result;
743
+ }
744
+
745
+
746
+ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass)
747
+ {
748
+ VALUE result;
749
+ GEOSGeometry* clone_geom;
750
+
751
+ result = Qnil;
752
+ if (geom) {
753
+ clone_geom = GEOSGeom_clone_r(RGEO_FACTORY_DATA_PTR(factory)->geos_context, geom);
754
+ if (clone_geom) {
755
+ result = rgeo_wrap_geos_geometry(factory, clone_geom, klass);
756
+ }
757
+ }
758
+ return result;
759
+ }
760
+
761
+
762
+ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type)
763
+ {
764
+ VALUE object;
765
+ const GEOSGeometry* geom;
766
+ RGeo_Globals* globals;
767
+
768
+ if (NIL_P(type) && TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func && RGEO_GEOMETRY_DATA_PTR(obj)->factory == factory) {
769
+ object = obj;
770
+ }
771
+ else {
772
+ globals = RGEO_FACTORY_DATA_PTR(factory)->globals;
773
+ object = rb_funcall(globals->feature_module, globals->id_cast, 3, obj, factory, type);
774
+ }
775
+ geom = NULL;
776
+ if (!NIL_P(object)) {
777
+ geom = RGEO_GEOMETRY_DATA_PTR(object)->geom;
778
+ }
779
+ return geom;
780
+ }
781
+
782
+
783
+ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, VALUE type, VALUE* klasses)
784
+ {
785
+ VALUE object;
786
+ GEOSGeometry* geom;
787
+ RGeo_GeometryData* object_data;
788
+ const GEOSPreparedGeometry* prep;
789
+ RGeo_Globals* globals;
790
+
791
+ if (klasses) {
792
+ *klasses = Qnil;
793
+ }
794
+ globals = RGEO_FACTORY_DATA_PTR(factory)->globals;
795
+ object = rb_funcall(globals->feature_module, globals->id_cast, 5, obj, factory, type, globals->sym_force_new, globals->sym_keep_subtype);
796
+ geom = NULL;
797
+ if (!NIL_P(object)) {
798
+ object_data = RGEO_GEOMETRY_DATA_PTR(object);
799
+ geom = object_data->geom;
800
+ if (klasses) {
801
+ *klasses = object_data->klasses;
802
+ if (NIL_P(*klasses)) {
803
+ *klasses = CLASS_OF(object);
804
+ }
805
+ }
806
+ prep = object_data->prep;
807
+ if (prep && prep != (GEOSPreparedGeometry*)1 && prep != (GEOSPreparedGeometry*)2) {
808
+ GEOSPreparedGeom_destroy_r(object_data->geos_context, prep);
809
+ }
810
+ object_data->geos_context = NULL;
811
+ object_data->geom = NULL;
812
+ object_data->prep = NULL;
813
+ object_data->factory = Qnil;
814
+ object_data->klasses = Qnil;
815
+ }
816
+ return geom;
817
+ }
818
+
819
+
820
+ char rgeo_is_geos_object(VALUE obj)
821
+ {
822
+ return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? 1 : 0;
823
+ }
824
+
825
+
826
+ const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj)
827
+ {
828
+ return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? (const GEOSGeometry*)(RGEO_GEOMETRY_DATA_PTR(obj)->geom) : NULL;
829
+ }
830
+
831
+
832
+ VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z)
833
+ {
834
+ VALUE result;
835
+ const GEOSCoordSequence* cs1;
836
+ const GEOSCoordSequence* cs2;
837
+ unsigned int len1;
838
+ unsigned int len2;
839
+ unsigned int i;
840
+ double val1, val2;
841
+
842
+ result = Qnil;
843
+ if (geom1 && geom2) {
844
+ cs1 = GEOSGeom_getCoordSeq_r(context, geom1);
845
+ cs2 = GEOSGeom_getCoordSeq_r(context, geom2);
846
+ if (cs1 && cs2) {
847
+ len1 = 0;
848
+ len2 = 0;
849
+ if (GEOSCoordSeq_getSize_r(context, cs1, &len1) && GEOSCoordSeq_getSize_r(context, cs2, &len2)) {
850
+ if (len1 == len2) {
851
+ result = Qtrue;
852
+ for (i=0; i<len1; ++i) {
853
+ if (GEOSCoordSeq_getX_r(context, cs1, i, &val1) && GEOSCoordSeq_getX_r(context, cs2, i, &val2)) {
854
+ if (val1 == val2) {
855
+ if (GEOSCoordSeq_getY_r(context, cs1, i, &val1) && GEOSCoordSeq_getY_r(context, cs2, i, &val2)) {
856
+ if (val1 == val2) {
857
+ if (check_z) {
858
+ val1 = 0;
859
+ if (!GEOSCoordSeq_getZ_r(context, cs1, i, &val1)) {
860
+ result = Qnil;
861
+ break;
862
+ }
863
+ val2 = 0;
864
+ if (!GEOSCoordSeq_getZ_r(context, cs2, i, &val2)) {
865
+ result = Qnil;
866
+ break;
867
+ }
868
+ if (val1 != val2) {
869
+ result = Qfalse;
870
+ break;
871
+ }
872
+ }
873
+ }
874
+ else { // Y coords are different
875
+ result = Qfalse;
876
+ break;
877
+ }
878
+ }
879
+ else { // Failed to get Y coords
880
+ result = Qnil;
881
+ break;
882
+ }
883
+ }
884
+ else { // X coords are different
885
+ result = Qfalse;
886
+ break;
887
+ }
888
+ }
889
+ else { // Failed to get X coords
890
+ result = Qnil;
891
+ break;
892
+ }
893
+ } // Iteration over coords
894
+ }
895
+ else { // Lengths are different
896
+ result = Qfalse;
897
+ }
898
+ }
899
+ }
900
+ }
901
+ return result;
902
+ }
903
+
904
+
905
+ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2)
906
+ {
907
+ VALUE result;
908
+ VALUE factory;
909
+
910
+ result = Qnil;
911
+ if (rb_obj_class(obj1) != rb_obj_class(obj2)) {
912
+ result = Qfalse;
913
+ }
914
+ else {
915
+ factory = RGEO_GEOMETRY_DATA_PTR(obj1)->factory;
916
+ result = rb_funcall(factory, RGEO_FACTORY_DATA_PTR(factory)->globals->id_eql, 1, RGEO_GEOMETRY_DATA_PTR(obj2)->factory);
917
+ }
918
+ return result;
919
+ }
920
+
921
+
922
+ typedef struct {
923
+ st_index_t seed_hash;
924
+ double x;
925
+ double y;
926
+ double z;
927
+ } RGeo_Coordseq_Hash_Struct;
928
+
929
+ st_index_t rgeo_geos_coordseq_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash)
930
+ {
931
+ const GEOSCoordSequence* cs;
932
+ unsigned int len;
933
+ unsigned int i;
934
+ RGeo_Coordseq_Hash_Struct hash_struct;
935
+
936
+ if (geom) {
937
+ cs = GEOSGeom_getCoordSeq_r(context, geom);
938
+ if (cs) {
939
+ if (GEOSCoordSeq_getSize_r(context, cs, &len)) {
940
+ for (i=0; i<len; ++i) {
941
+ if (GEOSCoordSeq_getX_r(context, cs, i, &hash_struct.x)) {
942
+ if (GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.y)) {
943
+ if (!GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.z)) {
944
+ hash_struct.z = 0;
945
+ }
946
+ hash_struct.seed_hash = hash;
947
+ hash = rb_memhash(&hash_struct, sizeof(RGeo_Coordseq_Hash_Struct));
948
+ }
949
+ }
950
+ }
951
+ }
952
+ }
953
+ }
954
+ return hash;
955
+ }
956
+
957
+
958
+ typedef struct {
959
+ st_index_t seed_hash;
960
+ st_index_t h1;
961
+ st_index_t h2;
962
+ } RGeo_Objbase_Hash_Struct;
963
+
964
+ st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t hash)
965
+ {
966
+ ID hash_method;
967
+ RGeo_Objbase_Hash_Struct hash_struct;
968
+
969
+ hash_method = RGEO_FACTORY_DATA_PTR(factory)->globals->id_hash;
970
+ hash_struct.seed_hash = hash;
971
+ hash_struct.h1 = FIX2LONG(rb_funcall(factory, hash_method, 0));
972
+ hash_struct.h2 = FIX2LONG(rb_funcall(type_module, hash_method, 0));
973
+ return rb_memhash(&hash_struct, sizeof(RGeo_Objbase_Hash_Struct));
974
+ }
975
+
976
+
977
+ st_index_t rgeo_internal_memhash(const void* ptr, long len)
978
+ {
979
+ const char* bytes;
980
+ st_index_t hval;
981
+ long i;
982
+
983
+ bytes = (const char*)ptr;
984
+ hval = 0x811c9dc5;
985
+ for (i=0; i<len; ++i) {
986
+ hval ^= (unsigned int)(*bytes++);
987
+ hval *= 0x01000193;
988
+ }
989
+ return hval;
990
+ }
991
+
992
+
993
+ RGEO_END_C
994
+
995
+ #endif