schleyfox-rgeo 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/History.rdoc +199 -0
  2. data/README.rdoc +172 -0
  3. data/Spatial_Programming_With_RGeo.rdoc +440 -0
  4. data/Version +1 -0
  5. data/ext/geos_c_impl/extconf.rb +84 -0
  6. data/ext/geos_c_impl/factory.c +468 -0
  7. data/ext/geos_c_impl/factory.h +224 -0
  8. data/ext/geos_c_impl/geometry.c +705 -0
  9. data/ext/geos_c_impl/geometry.h +55 -0
  10. data/ext/geos_c_impl/geometry_collection.c +482 -0
  11. data/ext/geos_c_impl/geometry_collection.h +69 -0
  12. data/ext/geos_c_impl/line_string.c +509 -0
  13. data/ext/geos_c_impl/line_string.h +64 -0
  14. data/ext/geos_c_impl/main.c +70 -0
  15. data/ext/geos_c_impl/point.c +193 -0
  16. data/ext/geos_c_impl/point.h +62 -0
  17. data/ext/geos_c_impl/polygon.c +265 -0
  18. data/ext/geos_c_impl/polygon.h +66 -0
  19. data/ext/geos_c_impl/preface.h +50 -0
  20. data/ext/proj4_c_impl/extconf.rb +88 -0
  21. data/ext/proj4_c_impl/main.c +271 -0
  22. data/lib/rgeo.rb +124 -0
  23. data/lib/rgeo/cartesian.rb +60 -0
  24. data/lib/rgeo/cartesian/analysis.rb +118 -0
  25. data/lib/rgeo/cartesian/bounding_box.rb +337 -0
  26. data/lib/rgeo/cartesian/calculations.rb +161 -0
  27. data/lib/rgeo/cartesian/factory.rb +209 -0
  28. data/lib/rgeo/cartesian/feature_classes.rb +173 -0
  29. data/lib/rgeo/cartesian/feature_methods.rb +106 -0
  30. data/lib/rgeo/cartesian/interface.rb +150 -0
  31. data/lib/rgeo/coord_sys.rb +79 -0
  32. data/lib/rgeo/coord_sys/cs/entities.rb +1524 -0
  33. data/lib/rgeo/coord_sys/cs/factories.rb +208 -0
  34. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +308 -0
  35. data/lib/rgeo/coord_sys/proj4.rb +312 -0
  36. data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +194 -0
  37. data/lib/rgeo/coord_sys/srs_database/interface.rb +165 -0
  38. data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +188 -0
  39. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +108 -0
  40. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +108 -0
  41. data/lib/rgeo/error.rb +63 -0
  42. data/lib/rgeo/feature.rb +88 -0
  43. data/lib/rgeo/feature/curve.rb +156 -0
  44. data/lib/rgeo/feature/factory.rb +332 -0
  45. data/lib/rgeo/feature/factory_generator.rb +138 -0
  46. data/lib/rgeo/feature/geometry.rb +614 -0
  47. data/lib/rgeo/feature/geometry_collection.rb +129 -0
  48. data/lib/rgeo/feature/line.rb +66 -0
  49. data/lib/rgeo/feature/line_string.rb +102 -0
  50. data/lib/rgeo/feature/linear_ring.rb +66 -0
  51. data/lib/rgeo/feature/multi_curve.rb +113 -0
  52. data/lib/rgeo/feature/multi_line_string.rb +66 -0
  53. data/lib/rgeo/feature/multi_point.rb +73 -0
  54. data/lib/rgeo/feature/multi_polygon.rb +97 -0
  55. data/lib/rgeo/feature/multi_surface.rb +116 -0
  56. data/lib/rgeo/feature/point.rb +120 -0
  57. data/lib/rgeo/feature/polygon.rb +141 -0
  58. data/lib/rgeo/feature/surface.rb +122 -0
  59. data/lib/rgeo/feature/types.rb +305 -0
  60. data/lib/rgeo/geographic.rb +75 -0
  61. data/lib/rgeo/geographic/factory.rb +287 -0
  62. data/lib/rgeo/geographic/interface.rb +410 -0
  63. data/lib/rgeo/geographic/proj4_projector.rb +98 -0
  64. data/lib/rgeo/geographic/projected_feature_classes.rb +213 -0
  65. data/lib/rgeo/geographic/projected_feature_methods.rb +228 -0
  66. data/lib/rgeo/geographic/projected_window.rb +467 -0
  67. data/lib/rgeo/geographic/simple_mercator_projector.rb +157 -0
  68. data/lib/rgeo/geographic/spherical_feature_classes.rb +212 -0
  69. data/lib/rgeo/geographic/spherical_feature_methods.rb +97 -0
  70. data/lib/rgeo/geographic/spherical_math.rb +206 -0
  71. data/lib/rgeo/geos.rb +72 -0
  72. data/lib/rgeo/geos/factory.rb +301 -0
  73. data/lib/rgeo/geos/impl_additions.rb +76 -0
  74. data/lib/rgeo/geos/interface.rb +139 -0
  75. data/lib/rgeo/geos/zm_factory.rb +275 -0
  76. data/lib/rgeo/geos/zm_impl.rb +432 -0
  77. data/lib/rgeo/impl_helper.rb +53 -0
  78. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +235 -0
  79. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +85 -0
  80. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +197 -0
  81. data/lib/rgeo/impl_helper/basic_point_methods.rb +138 -0
  82. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +121 -0
  83. data/lib/rgeo/impl_helper/math.rb +50 -0
  84. data/lib/rgeo/version.rb +52 -0
  85. data/lib/rgeo/wkrep.rb +72 -0
  86. data/lib/rgeo/wkrep/wkb_generator.rb +267 -0
  87. data/lib/rgeo/wkrep/wkb_parser.rb +315 -0
  88. data/lib/rgeo/wkrep/wkt_generator.rb +275 -0
  89. data/lib/rgeo/wkrep/wkt_parser.rb +496 -0
  90. data/test/common/geometry_collection_tests.rb +238 -0
  91. data/test/common/line_string_tests.rb +324 -0
  92. data/test/common/multi_line_string_tests.rb +209 -0
  93. data/test/common/multi_point_tests.rb +201 -0
  94. data/test/common/multi_polygon_tests.rb +208 -0
  95. data/test/common/point_tests.rb +331 -0
  96. data/test/common/polygon_tests.rb +232 -0
  97. data/test/coord_sys/tc_active_record_table.rb +102 -0
  98. data/test/coord_sys/tc_ogc_cs.rb +356 -0
  99. data/test/coord_sys/tc_proj4.rb +138 -0
  100. data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
  101. data/test/coord_sys/tc_sr_org.rb +70 -0
  102. data/test/coord_sys/tc_url_reader.rb +82 -0
  103. data/test/geos/tc_factory.rb +91 -0
  104. data/test/geos/tc_geometry_collection.rb +62 -0
  105. data/test/geos/tc_line_string.rb +62 -0
  106. data/test/geos/tc_misc.rb +72 -0
  107. data/test/geos/tc_multi_line_string.rb +62 -0
  108. data/test/geos/tc_multi_point.rb +62 -0
  109. data/test/geos/tc_multi_polygon.rb +63 -0
  110. data/test/geos/tc_point.rb +86 -0
  111. data/test/geos/tc_polygon.rb +86 -0
  112. data/test/geos/tc_zmfactory.rb +85 -0
  113. data/test/projected_geographic/tc_geometry_collection.rb +62 -0
  114. data/test/projected_geographic/tc_line_string.rb +62 -0
  115. data/test/projected_geographic/tc_multi_line_string.rb +62 -0
  116. data/test/projected_geographic/tc_multi_point.rb +62 -0
  117. data/test/projected_geographic/tc_multi_polygon.rb +63 -0
  118. data/test/projected_geographic/tc_point.rb +93 -0
  119. data/test/projected_geographic/tc_polygon.rb +62 -0
  120. data/test/simple_cartesian/tc_calculations.rb +145 -0
  121. data/test/simple_cartesian/tc_geometry_collection.rb +69 -0
  122. data/test/simple_cartesian/tc_line_string.rb +70 -0
  123. data/test/simple_cartesian/tc_multi_line_string.rb +67 -0
  124. data/test/simple_cartesian/tc_multi_point.rb +67 -0
  125. data/test/simple_cartesian/tc_multi_polygon.rb +70 -0
  126. data/test/simple_cartesian/tc_point.rb +91 -0
  127. data/test/simple_cartesian/tc_polygon.rb +67 -0
  128. data/test/simple_mercator/tc_geometry_collection.rb +62 -0
  129. data/test/simple_mercator/tc_line_string.rb +62 -0
  130. data/test/simple_mercator/tc_multi_line_string.rb +62 -0
  131. data/test/simple_mercator/tc_multi_point.rb +62 -0
  132. data/test/simple_mercator/tc_multi_polygon.rb +63 -0
  133. data/test/simple_mercator/tc_point.rb +93 -0
  134. data/test/simple_mercator/tc_polygon.rb +62 -0
  135. data/test/simple_mercator/tc_window.rb +219 -0
  136. data/test/spherical_geographic/tc_calculations.rb +203 -0
  137. data/test/spherical_geographic/tc_geometry_collection.rb +70 -0
  138. data/test/spherical_geographic/tc_line_string.rb +70 -0
  139. data/test/spherical_geographic/tc_multi_line_string.rb +67 -0
  140. data/test/spherical_geographic/tc_multi_point.rb +67 -0
  141. data/test/spherical_geographic/tc_multi_polygon.rb +70 -0
  142. data/test/spherical_geographic/tc_point.rb +100 -0
  143. data/test/spherical_geographic/tc_polygon.rb +67 -0
  144. data/test/tc_cartesian_analysis.rb +107 -0
  145. data/test/tc_oneoff.rb +63 -0
  146. data/test/wkrep/tc_wkb_generator.rb +249 -0
  147. data/test/wkrep/tc_wkb_parser.rb +353 -0
  148. data/test/wkrep/tc_wkt_generator.rb +362 -0
  149. data/test/wkrep/tc_wkt_parser.rb +480 -0
  150. metadata +267 -0
@@ -0,0 +1,224 @@
1
+ /*
2
+ -----------------------------------------------------------------------------
3
+
4
+ Factory and utility functions for GEOS wrapper
5
+
6
+ -----------------------------------------------------------------------------
7
+ Copyright 2010 Daniel Azuma
8
+
9
+ All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ * Redistributions of source code must retain the above copyright notice,
15
+ this list of conditions and the following disclaimer.
16
+ * Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+ * Neither the name of the copyright holder, nor the names of any other
20
+ contributors to this software, may be used to endorse or promote products
21
+ derived from this software without specific prior written permission.
22
+
23
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ POSSIBILITY OF SUCH DAMAGE.
34
+ -----------------------------------------------------------------------------
35
+ */
36
+
37
+
38
+ #ifndef RGEO_GEOS_FACTORY_INCLUDED
39
+ #define RGEO_GEOS_FACTORY_INCLUDED
40
+
41
+ #include <ruby.h>
42
+ #include <geos_c.h>
43
+
44
+ RGEO_BEGIN_C
45
+
46
+
47
+ /*
48
+ Per-interpreter globals.
49
+ Most of these are cached references to commonly used classes and modules
50
+ so we don't have to do a lot of constant lookups.
51
+ */
52
+ typedef struct {
53
+ VALUE feature_module;
54
+ VALUE feature_geometry;
55
+ VALUE feature_point;
56
+ VALUE feature_line_string;
57
+ VALUE feature_linear_ring;
58
+ VALUE feature_line;
59
+ VALUE feature_polygon;
60
+ VALUE feature_geometry_collection;
61
+ VALUE feature_multi_point;
62
+ VALUE feature_multi_line_string;
63
+ VALUE feature_multi_polygon;
64
+ VALUE geos_module;
65
+ VALUE geos_geometry;
66
+ VALUE geos_point;
67
+ VALUE geos_line_string;
68
+ VALUE geos_linear_ring;
69
+ VALUE geos_line;
70
+ VALUE geos_polygon;
71
+ VALUE geos_geometry_collection;
72
+ VALUE geos_multi_point;
73
+ VALUE geos_multi_line_string;
74
+ VALUE geos_multi_polygon;
75
+ } RGeo_Globals;
76
+
77
+
78
+ /*
79
+ Wrapped structure for Factory objects.
80
+ A factory encapsulates the GEOS context, and GEOS serializer settings.
81
+ It also stores the SRID for all geometries created by this factory,
82
+ and the resolution for buffers created for this factory's geometries.
83
+ Finally, it provides easy access to the globals.
84
+ */
85
+ typedef struct {
86
+ RGeo_Globals* globals;
87
+ GEOSContextHandle_t geos_context;
88
+ GEOSWKTReader* wkt_reader;
89
+ GEOSWKBReader* wkb_reader;
90
+ GEOSWKTWriter* wkt_writer;
91
+ GEOSWKBWriter* wkb_writer;
92
+ int flags;
93
+ int srid;
94
+ int buffer_resolution;
95
+ } RGeo_FactoryData;
96
+
97
+ #define RGEO_FACTORYFLAGS_LENIENT_MULTIPOLYGON 1
98
+ #define RGEO_FACTORYFLAGS_SUPPORTS_Z 2
99
+ #define RGEO_FACTORYFLAGS_SUPPORTS_M 4
100
+ #define RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M 6
101
+
102
+
103
+ /*
104
+ Wrapped structure for Geometry objects.
105
+ Includes a handle to the underlying GEOS geometry itself (which could
106
+ be null for an uninitialized geometry).
107
+ It also provides a handle to the factory that created this geometry.
108
+
109
+ The klasses object is used by geometry collections. Its value is
110
+ generally an array of the ruby classes for the colletion's elements,
111
+ so that we can reproduce the exact class for those elements in cases
112
+ where the class cannot be inferred directly from the GEOS type (as
113
+ in Line objects, which have no GEOS type). Any array element, or the
114
+ array itself, could be Qnil, indicating fall back to the default
115
+ inferred from the GEOS type.
116
+
117
+ The GEOS context handle is also included here. Ideally, it would be
118
+ available by following the factory reference and getting it from the
119
+ factory data. However, one use case is in the destroy_geometry_func
120
+ in factory.c, and Rubinius 1.1.1 seems to crash when you try to
121
+ evaluate a DATA_PTR from that function, so we copy the context handle
122
+ here so the destroy_geometry_func can get to it.
123
+ */
124
+ typedef struct {
125
+ GEOSGeometry* geom;
126
+ GEOSContextHandle_t geos_context;
127
+ VALUE factory;
128
+ VALUE klasses;
129
+ } RGeo_GeometryData;
130
+
131
+
132
+ // Returns the RGeo_FactoryData* given a ruby Factory object
133
+ #define RGEO_FACTORY_DATA_PTR(factory) ((RGeo_FactoryData*)DATA_PTR(factory))
134
+
135
+ // Returns the RGeo_GeometryData* given a ruby Geometry object
136
+ #define RGEO_GEOMETRY_DATA_PTR(geometry) ((RGeo_GeometryData*)DATA_PTR(geometry))
137
+
138
+
139
+ /*
140
+ Initializes the factory module. This should be called first in the
141
+ initialization process.
142
+ */
143
+ RGeo_Globals* rgeo_init_geos_factory();
144
+
145
+ /*
146
+ Given a GEOS geometry handle, wraps it in a ruby Geometry object of the
147
+ given klass. The geometry is then owned by the ruby object, so make sure
148
+ you clone the GEOS object first if something else thinks it owns it.
149
+ You may pass Qnil for the klass to have the klass auto-detected. (But
150
+ note that it cannot auto-detect the Line type because GEOS doesn't
151
+ explicitly represent that type-- it will come out as LineString.)
152
+ You may also pass a ruby Array for the klass if the geometry is a
153
+ collection of some sort. In this case, the array elements should be the
154
+ classes for the elements of the collection.
155
+ Returns Qnil if the wrapping failed for any reason.
156
+ */
157
+ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass);
158
+
159
+ /*
160
+ Same as rgeo_wrap_geos_geometry except that it wraps a clone of the
161
+ given geom, so the original geom doesn't change ownership.
162
+ */
163
+ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass);
164
+
165
+ /*
166
+ Gets the GEOS geometry for a given ruby Geometry object. If the given
167
+ ruby object is not a GEOS geometry implementation, it is converted to a
168
+ GEOS implementation first. You may also optionally cast it to a type,
169
+ specified by an appropriate feature module. Passing Qnil for the type
170
+ disables this auto-cast. The returned GEOS geometry is owned by rgeo,
171
+ and you should not dispose it or take ownership of it yourself.
172
+ */
173
+ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type);
174
+
175
+ /*
176
+ Gets a GEOS geometry for a given ruby Geometry object. You must provide
177
+ a GEOS factory for the geometry; the object is cast to that factory if
178
+ it is not already of it. You may also optionally cast it to a type,
179
+ specified by an appropriate feature module. Passing Qnil for the type
180
+ disables this auto-cast. The returned GEOS geometry is owned by the
181
+ caller-- that is, if the original ruby object is already of the desired
182
+ factory, the returned GEOS geometry is a clone of the original.
183
+
184
+ If the klasses parameter is not NULL, its referent is set to the
185
+ klasses saved in the original ruby Geometry object (if any), or else to
186
+ the class of the converted GEOS object. This is so that you can use the
187
+ result of this function to build a GEOS-backed clone of the original
188
+ geometry, or to include the given geometry in a collection while keeping
189
+ the klasses intact.
190
+ */
191
+ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, VALUE type, VALUE* klasses);
192
+
193
+ /*
194
+ Returns 1 if the given ruby object is a GEOS Geometry implementation,
195
+ or 0 if not.
196
+ */
197
+ char rgeo_is_geos_object(VALUE obj);
198
+
199
+ /*
200
+ Gets the underlying GEOS geometry for a given ruby object. Returns NULL
201
+ if the given ruby object is not a GEOS geometry wrapper.
202
+ */
203
+ const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj);
204
+
205
+ /*
206
+ Compares the coordinate sequences for two given GEOS geometries.
207
+ The two given geometries MUST be of types backed directly by
208
+ coordinate sequences-- i.e. points or line strings.
209
+ Returns Qtrue if the two coordinate sequences are equal, Qfalse
210
+ if they are inequal, or Qnil if an error occurs.
211
+ */
212
+ VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z);
213
+
214
+ /*
215
+ Compares the ruby classes and geometry factories of the two given ruby
216
+ objects. Returns Qtrue if everything is equal (that is, the two objects
217
+ are of the same type and factory), or Qfalse otherwise.
218
+ */
219
+ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2);
220
+
221
+
222
+ RGEO_END_C
223
+
224
+ #endif
@@ -0,0 +1,705 @@
1
+ /*
2
+ -----------------------------------------------------------------------------
3
+
4
+ Geometry base class methods for GEOS wrapper
5
+
6
+ -----------------------------------------------------------------------------
7
+ Copyright 2010 Daniel Azuma
8
+
9
+ All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ * Redistributions of source code must retain the above copyright notice,
15
+ this list of conditions and the following disclaimer.
16
+ * Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+ * Neither the name of the copyright holder, nor the names of any other
20
+ contributors to this software, may be used to endorse or promote products
21
+ derived from this software without specific prior written permission.
22
+
23
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ POSSIBILITY OF SUCH DAMAGE.
34
+ -----------------------------------------------------------------------------
35
+ */
36
+
37
+
38
+ #include "preface.h"
39
+
40
+ #ifdef RGEO_GEOS_SUPPORTED
41
+
42
+ #include <string.h>
43
+ #include <ruby.h>
44
+ #include <geos_c.h>
45
+
46
+ #include "factory.h"
47
+ #include "geometry.h"
48
+
49
+ RGEO_BEGIN_C
50
+
51
+
52
+ /**** INTERNAL UTILITY FUNCTIONS ****/
53
+
54
+
55
+ // Determine the dimension of the given geometry. Empty collections have dimension -1.
56
+ // Recursively checks collection elemenets.
57
+
58
+ static int compute_dimension(GEOSContextHandle_t context, const GEOSGeometry* geom)
59
+ {
60
+ int result = -1;
61
+ int size, i;
62
+ if (geom) {
63
+ switch (GEOSGeomTypeId_r(context, geom)) {
64
+ case GEOS_POINT:
65
+ result = 0;
66
+ break;
67
+ case GEOS_MULTIPOINT:
68
+ if (!GEOSisEmpty_r(context, geom)) {
69
+ result = 0;
70
+ }
71
+ break;
72
+ case GEOS_LINESTRING:
73
+ case GEOS_LINEARRING:
74
+ result = 1;
75
+ break;
76
+ case GEOS_MULTILINESTRING:
77
+ if (!GEOSisEmpty_r(context, geom)) {
78
+ result = 1;
79
+ }
80
+ break;
81
+ case GEOS_POLYGON:
82
+ result = 2;
83
+ break;
84
+ case GEOS_MULTIPOLYGON:
85
+ if (!GEOSisEmpty_r(context, geom)) {
86
+ result = 2;
87
+ }
88
+ break;
89
+ case GEOS_GEOMETRYCOLLECTION:
90
+ size = GEOSGetNumGeometries_r(context, geom);
91
+ for (i=0; i<size; ++i) {
92
+ int dim = compute_dimension(context, GEOSGetGeometryN_r(context, geom, i));
93
+ if (dim > result) {
94
+ result = dim;
95
+ }
96
+ }
97
+ break;
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+
103
+
104
+ /**** RUBY METHOD DEFINITIONS ****/
105
+
106
+
107
+ static VALUE method_geometry_initialized_p(VALUE self)
108
+ {
109
+ return RGEO_GEOMETRY_DATA_PTR(self)->geom ? Qtrue : Qfalse;
110
+ }
111
+
112
+
113
+ static VALUE method_geometry_factory(VALUE self)
114
+ {
115
+ return RGEO_GEOMETRY_DATA_PTR(self)->factory;
116
+ }
117
+
118
+
119
+ static VALUE method_geometry_set_factory(VALUE self, VALUE factory)
120
+ {
121
+ RGEO_GEOMETRY_DATA_PTR(self)->factory = factory;
122
+ return factory;
123
+ }
124
+
125
+
126
+ static VALUE method_geometry_dimension(VALUE self)
127
+ {
128
+ VALUE result = Qnil;
129
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
130
+ const GEOSGeometry* self_geom = self_data->geom;
131
+ if (self_geom) {
132
+ result = INT2NUM(compute_dimension(self_data->geos_context, self_geom));
133
+ }
134
+ return result;
135
+ }
136
+
137
+
138
+ static VALUE method_geometry_geometry_type(VALUE self)
139
+ {
140
+ VALUE result = Qnil;
141
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
142
+ const GEOSGeometry* self_geom = self_data->geom;
143
+ if (self_geom) {
144
+ result = RGEO_FACTORY_DATA_PTR(self_data->factory)->globals->feature_geometry;
145
+ }
146
+ return result;
147
+ }
148
+
149
+
150
+ static VALUE method_geometry_srid(VALUE self)
151
+ {
152
+ VALUE result = Qnil;
153
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
154
+ const GEOSGeometry* self_geom = self_data->geom;
155
+ if (self_geom) {
156
+ result = INT2NUM(GEOSGetSRID_r(self_data->geos_context, self_geom));
157
+ }
158
+ return result;
159
+ }
160
+
161
+
162
+ static VALUE method_geometry_envelope(VALUE self)
163
+ {
164
+ VALUE result = Qnil;
165
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
166
+ const GEOSGeometry* self_geom = self_data->geom;
167
+ if (self_geom) {
168
+ GEOSContextHandle_t geos_context = self_data->geos_context;
169
+ GEOSGeometry* envelope = GEOSEnvelope_r(geos_context, self_geom);
170
+ // GEOS returns an "empty" point for an empty collection's envelope.
171
+ // We don't allow that type, so we replace it with an empty collection.
172
+ if (!envelope ||
173
+ GEOSGeomTypeId_r(geos_context, envelope) == GEOS_POINT &&
174
+ GEOSGetNumCoordinates_r(geos_context, envelope) == 0) {
175
+ if (envelope) {
176
+ GEOSGeom_destroy_r(geos_context, envelope);
177
+ }
178
+ envelope = GEOSGeom_createCollection_r(geos_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
179
+ }
180
+ result = rgeo_wrap_geos_geometry(self_data->factory, envelope, Qnil);
181
+ }
182
+ return result;
183
+ }
184
+
185
+
186
+ static VALUE method_geometry_boundary(VALUE self)
187
+ {
188
+ VALUE result = Qnil;
189
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
190
+ const GEOSGeometry* self_geom = self_data->geom;
191
+ if (self_geom) {
192
+ GEOSContextHandle_t geos_context = self_data->geos_context;
193
+ GEOSGeometry* boundary = GEOSBoundary_r(geos_context, self_geom);
194
+ // GEOS returns NULL for the boundary of an empty collection.
195
+ // Replace that with an empty collection.
196
+ if (!boundary) {
197
+ boundary = GEOSGeom_createCollection_r(geos_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
198
+ }
199
+ result = rgeo_wrap_geos_geometry(self_data->factory, boundary, Qnil);
200
+ }
201
+ return result;
202
+ }
203
+
204
+
205
+ static VALUE method_geometry_as_text(VALUE self)
206
+ {
207
+ VALUE result = Qnil;
208
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
209
+ const GEOSGeometry* self_geom = self_data->geom;
210
+ if (self_geom) {
211
+ RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory);
212
+ GEOSWKTWriter* wkt_writer = factory_data->wkt_writer;
213
+ GEOSContextHandle_t geos_context = self_data->geos_context;
214
+ if (!wkt_writer) {
215
+ wkt_writer = GEOSWKTWriter_create_r(geos_context);
216
+ factory_data->wkt_writer = wkt_writer;
217
+ }
218
+ char* str = GEOSWKTWriter_write_r(geos_context, wkt_writer, self_geom);
219
+ if (str) {
220
+ result = rb_str_new2(str);
221
+ GEOSFree_r(geos_context, str);
222
+ }
223
+ }
224
+ return result;
225
+ }
226
+
227
+
228
+ static VALUE method_geometry_as_binary(VALUE self)
229
+ {
230
+ VALUE result = Qnil;
231
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
232
+ const GEOSGeometry* self_geom = self_data->geom;
233
+ if (self_geom) {
234
+ RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory);
235
+ GEOSWKBWriter* wkb_writer = factory_data->wkb_writer;
236
+ GEOSContextHandle_t geos_context = self_data->geos_context;
237
+ if (!wkb_writer) {
238
+ wkb_writer = GEOSWKBWriter_create_r(geos_context);
239
+ factory_data->wkb_writer = wkb_writer;
240
+ }
241
+ size_t size;
242
+ char* str = (char*)GEOSWKBWriter_write_r(geos_context, wkb_writer, self_geom, &size);
243
+ if (str) {
244
+ result = rb_str_new(str, size);
245
+ GEOSFree_r(geos_context, str);
246
+ }
247
+ }
248
+ return result;
249
+ }
250
+
251
+
252
+ static VALUE method_geometry_is_empty(VALUE self)
253
+ {
254
+ VALUE result = Qnil;
255
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
256
+ const GEOSGeometry* self_geom = self_data->geom;
257
+ if (self_geom) {
258
+ char val = GEOSisEmpty_r(self_data->geos_context, self_geom);
259
+ if (val == 0) {
260
+ result = Qfalse;
261
+ }
262
+ else if (val == 1) {
263
+ result = Qtrue;
264
+ }
265
+ }
266
+ return result;
267
+ }
268
+
269
+
270
+ static VALUE method_geometry_is_simple(VALUE self)
271
+ {
272
+ VALUE result = Qnil;
273
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
274
+ const GEOSGeometry* self_geom = self_data->geom;
275
+ if (self_geom) {
276
+ char val = GEOSisSimple_r(self_data->geos_context, self_geom);
277
+ if (val == 0) {
278
+ result = Qfalse;
279
+ }
280
+ else if (val == 1) {
281
+ result = Qtrue;
282
+ }
283
+ }
284
+ return result;
285
+ }
286
+
287
+
288
+ static VALUE method_geometry_equals(VALUE self, VALUE rhs)
289
+ {
290
+ VALUE result = Qnil;
291
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
292
+ const GEOSGeometry* self_geom = self_data->geom;
293
+ if (self_geom) {
294
+ const GEOSGeometry* rhs_geom = rgeo_get_geos_geometry_safe(rhs);
295
+ if (rhs_geom) {
296
+ GEOSContextHandle_t self_context = self_data->geos_context;
297
+ // GEOS has a bug where empty geometries are not spatially equal
298
+ // to each other. Work around this case first.
299
+ if (GEOSisEmpty_r(self_context, self_geom) == 1 &&
300
+ GEOSisEmpty_r(RGEO_GEOMETRY_DATA_PTR(rhs)->geos_context, rhs_geom) == 1) {
301
+ result = Qtrue;
302
+ }
303
+ else {
304
+ char val = GEOSEquals_r(self_context, self_geom, rhs_geom);
305
+ if (val == 0) {
306
+ result = Qfalse;
307
+ }
308
+ else if (val == 1) {
309
+ result = Qtrue;
310
+ }
311
+ }
312
+ }
313
+ }
314
+ return result;
315
+ }
316
+
317
+
318
+ static VALUE method_geometry_eql(VALUE self, VALUE rhs)
319
+ {
320
+ // This should be overridden by the subclass.
321
+ return self == rhs ? Qtrue : Qfalse;
322
+ }
323
+
324
+
325
+ static VALUE method_geometry_disjoint(VALUE self, VALUE rhs)
326
+ {
327
+ VALUE result = Qnil;
328
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
329
+ const GEOSGeometry* self_geom = self_data->geom;
330
+ if (self_geom) {
331
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
332
+ if (rhs_geom) {
333
+ char val = GEOSDisjoint_r(self_data->geos_context, self_geom, rhs_geom);
334
+ if (val == 0) {
335
+ result = Qfalse;
336
+ }
337
+ else if (val == 1) {
338
+ result = Qtrue;
339
+ }
340
+ }
341
+ }
342
+ return result;
343
+ }
344
+
345
+
346
+ static VALUE method_geometry_intersects(VALUE self, VALUE rhs)
347
+ {
348
+ VALUE result = Qnil;
349
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
350
+ const GEOSGeometry* self_geom = self_data->geom;
351
+ if (self_geom) {
352
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
353
+ if (rhs_geom) {
354
+ char val = GEOSIntersects_r(self_data->geos_context, self_geom, rhs_geom);
355
+ if (val == 0) {
356
+ result = Qfalse;
357
+ }
358
+ else if (val == 1) {
359
+ result = Qtrue;
360
+ }
361
+ }
362
+ }
363
+ return result;
364
+ }
365
+
366
+
367
+ static VALUE method_geometry_touches(VALUE self, VALUE rhs)
368
+ {
369
+ VALUE result = Qnil;
370
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
371
+ const GEOSGeometry* self_geom = self_data->geom;
372
+ if (self_geom) {
373
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
374
+ if (rhs_geom) {
375
+ char val = GEOSTouches_r(self_data->geos_context, self_geom, rhs_geom);
376
+ if (val == 0) {
377
+ result = Qfalse;
378
+ }
379
+ else if (val == 1) {
380
+ result = Qtrue;
381
+ }
382
+ }
383
+ }
384
+ return result;
385
+ }
386
+
387
+
388
+ static VALUE method_geometry_crosses(VALUE self, VALUE rhs)
389
+ {
390
+ VALUE result = Qnil;
391
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
392
+ const GEOSGeometry* self_geom = self_data->geom;
393
+ if (self_geom) {
394
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
395
+ if (rhs_geom) {
396
+ char val = GEOSCrosses_r(self_data->geos_context, self_geom, rhs_geom);
397
+ if (val == 0) {
398
+ result = Qfalse;
399
+ }
400
+ else if (val == 1) {
401
+ result = Qtrue;
402
+ }
403
+ }
404
+ }
405
+ return result;
406
+ }
407
+
408
+
409
+ static VALUE method_geometry_within(VALUE self, VALUE rhs)
410
+ {
411
+ VALUE result = Qnil;
412
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
413
+ const GEOSGeometry* self_geom = self_data->geom;
414
+ if (self_geom) {
415
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
416
+ if (rhs_geom) {
417
+ char val = GEOSWithin_r(self_data->geos_context, self_geom, rhs_geom);
418
+ if (val == 0) {
419
+ result = Qfalse;
420
+ }
421
+ else if (val == 1) {
422
+ result = Qtrue;
423
+ }
424
+ }
425
+ }
426
+ return result;
427
+ }
428
+
429
+
430
+ static VALUE method_geometry_contains(VALUE self, VALUE rhs)
431
+ {
432
+ VALUE result = Qnil;
433
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
434
+ const GEOSGeometry* self_geom = self_data->geom;
435
+ if (self_geom) {
436
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
437
+ if (rhs_geom) {
438
+ char val = GEOSContains_r(self_data->geos_context, self_geom, rhs_geom);
439
+ if (val == 0) {
440
+ result = Qfalse;
441
+ }
442
+ else if (val == 1) {
443
+ result = Qtrue;
444
+ }
445
+ }
446
+ }
447
+ return result;
448
+ }
449
+
450
+
451
+ static VALUE method_geometry_overlaps(VALUE self, VALUE rhs)
452
+ {
453
+ VALUE result = Qnil;
454
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
455
+ const GEOSGeometry* self_geom = self_data->geom;
456
+ if (self_geom) {
457
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
458
+ if (rhs_geom) {
459
+ char val = GEOSOverlaps_r(self_data->geos_context, self_geom, rhs_geom);
460
+ if (val == 0) {
461
+ result = Qfalse;
462
+ }
463
+ else if (val == 1) {
464
+ result = Qtrue;
465
+ }
466
+ }
467
+ }
468
+ return result;
469
+ }
470
+
471
+
472
+ static VALUE method_geometry_relate(VALUE self, VALUE rhs, VALUE pattern)
473
+ {
474
+ VALUE result = Qnil;
475
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
476
+ const GEOSGeometry* self_geom = self_data->geom;
477
+ if (self_geom) {
478
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
479
+ if (rhs_geom) {
480
+ char val = GEOSRelatePattern_r(self_data->geos_context, self_geom, rhs_geom, StringValuePtr(pattern));
481
+ if (val == 0) {
482
+ result = Qfalse;
483
+ }
484
+ else if (val == 1) {
485
+ result = Qtrue;
486
+ }
487
+ }
488
+ }
489
+ return result;
490
+ }
491
+
492
+
493
+ static VALUE method_geometry_distance(VALUE self, VALUE rhs)
494
+ {
495
+ VALUE result = Qnil;
496
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
497
+ const GEOSGeometry* self_geom = self_data->geom;
498
+ if (self_geom) {
499
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(self_data->factory, rhs, Qnil);
500
+ if (rhs_geom) {
501
+ double dist;
502
+ if (GEOSDistance_r(self_data->geos_context, self_geom, rhs_geom, &dist)) {
503
+ result = rb_float_new(dist);
504
+ }
505
+ }
506
+ }
507
+ return result;
508
+ }
509
+
510
+
511
+ static VALUE method_geometry_buffer(VALUE self, VALUE distance)
512
+ {
513
+ VALUE result = Qnil;
514
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
515
+ const GEOSGeometry* self_geom = self_data->geom;
516
+ if (self_geom) {
517
+ VALUE factory = self_data->factory;
518
+ int resolution = NUM2INT(RGEO_FACTORY_DATA_PTR(factory)->buffer_resolution);
519
+ result = rgeo_wrap_geos_geometry(factory, GEOSBuffer_r(self_data->geos_context, self_geom, rb_num2dbl(distance), resolution), Qnil);
520
+ }
521
+ return result;
522
+ }
523
+
524
+
525
+ static VALUE method_geometry_convex_hull(VALUE self)
526
+ {
527
+ VALUE result = Qnil;
528
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
529
+ const GEOSGeometry* self_geom = self_data->geom;
530
+ if (self_geom) {
531
+ result = rgeo_wrap_geos_geometry(self_data->factory, GEOSConvexHull_r(self_data->geos_context, self_geom), Qnil);
532
+ }
533
+ return result;
534
+ }
535
+
536
+
537
+ static VALUE method_geometry_intersection(VALUE self, VALUE rhs)
538
+ {
539
+ VALUE result = Qnil;
540
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
541
+ const GEOSGeometry* self_geom = self_data->geom;
542
+ if (self_geom) {
543
+ VALUE factory = self_data->factory;
544
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
545
+ if (rhs_geom) {
546
+ result = rgeo_wrap_geos_geometry(factory, GEOSIntersection_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
547
+ }
548
+ }
549
+ return result;
550
+ }
551
+
552
+
553
+ static VALUE method_geometry_union(VALUE self, VALUE rhs)
554
+ {
555
+ VALUE result = Qnil;
556
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
557
+ const GEOSGeometry* self_geom = self_data->geom;
558
+ if (self_geom) {
559
+ VALUE factory = self_data->factory;
560
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
561
+ if (rhs_geom) {
562
+ result = rgeo_wrap_geos_geometry(factory, GEOSUnion_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
563
+ }
564
+ }
565
+ return result;
566
+ }
567
+
568
+
569
+ static VALUE method_geometry_difference(VALUE self, VALUE rhs)
570
+ {
571
+ VALUE result = Qnil;
572
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
573
+ const GEOSGeometry* self_geom = self_data->geom;
574
+ if (self_geom) {
575
+ VALUE factory = self_data->factory;
576
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
577
+ if (rhs_geom) {
578
+ result = rgeo_wrap_geos_geometry(factory, GEOSDifference_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
579
+ }
580
+ }
581
+ return result;
582
+ }
583
+
584
+
585
+ static VALUE method_geometry_sym_difference(VALUE self, VALUE rhs)
586
+ {
587
+ VALUE result = Qnil;
588
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
589
+ const GEOSGeometry* self_geom = self_data->geom;
590
+ if (self_geom) {
591
+ VALUE factory = self_data->factory;
592
+ const GEOSGeometry* rhs_geom = rgeo_convert_to_geos_geometry(factory, rhs, Qnil);
593
+ if (rhs_geom) {
594
+ result = rgeo_wrap_geos_geometry(factory, GEOSSymDifference_r(self_data->geos_context, self_geom, rhs_geom), Qnil);
595
+ }
596
+ }
597
+ return result;
598
+ }
599
+
600
+ static VALUE method_geometry_polygonize(VALUE self)
601
+ {
602
+ VALUE result = Qnil;
603
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
604
+ const GEOSGeometry* self_geom = self_data->geom;
605
+ if(self_geom) {
606
+ GEOSGeometry const *vgeoms[1];
607
+ GEOSContextHandle_t geos_context = self_data->geos_context;
608
+ GEOSGeometry *geos_result;
609
+ vgeoms[0] = self_geom;
610
+
611
+ geos_result = GEOSPolygonize_r(geos_context, vgeoms, 1);
612
+ result = rgeo_wrap_geos_geometry(self_data->factory, geos_result, Qnil);
613
+ }
614
+ return result;
615
+ }
616
+
617
+ static VALUE alloc_geometry(VALUE klass)
618
+ {
619
+ return rgeo_wrap_geos_geometry(Qnil, NULL, klass);
620
+ }
621
+
622
+
623
+ static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
624
+ {
625
+ // Clear out any existing value
626
+ RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
627
+ GEOSGeometry* self_geom = self_data->geom;
628
+ if (self_geom) {
629
+ GEOSGeom_destroy_r(self_data->geos_context, self_geom);
630
+ self_data->geom = NULL;
631
+ self_data->geos_context = NULL;
632
+ self_data->factory = Qnil;
633
+ self_data->klasses = Qnil;
634
+ }
635
+
636
+ // Copy value from orig
637
+ const GEOSGeometry* geom = rgeo_get_geos_geometry_safe(orig);
638
+ if (geom) {
639
+ RGeo_GeometryData* orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
640
+ GEOSContextHandle_t orig_context = orig_data->geos_context;
641
+ GEOSGeometry* clone_geom = GEOSGeom_clone_r(orig_context, geom);
642
+ if (clone_geom) {
643
+ GEOSSetSRID_r(orig_context, clone_geom, GEOSGetSRID_r(orig_context, geom));
644
+ self_data->geom = clone_geom;
645
+ self_data->geos_context = orig_context;
646
+ self_data->factory = orig_data->factory;
647
+ self_data->klasses = orig_data->klasses;
648
+ }
649
+ }
650
+ return self;
651
+ }
652
+
653
+
654
+ /**** INITIALIZATION FUNCTION ****/
655
+
656
+
657
+ void rgeo_init_geos_geometry(RGeo_Globals* globals)
658
+ {
659
+ VALUE geos_geometry_class = rb_define_class_under(globals->geos_module, "GeometryImpl", rb_cObject);
660
+ globals->geos_geometry = geos_geometry_class;
661
+ globals->feature_geometry = rb_const_get_at(globals->feature_module, rb_intern("Geometry"));
662
+
663
+ rb_define_alloc_func(geos_geometry_class, alloc_geometry);
664
+ rb_define_method(geos_geometry_class, "_set_factory", method_geometry_set_factory, 1);
665
+ rb_define_method(geos_geometry_class, "initialize_copy", method_geometry_initialize_copy, 1);
666
+ rb_define_method(geos_geometry_class, "initialized?", method_geometry_initialized_p, 0);
667
+ rb_define_method(geos_geometry_class, "factory", method_geometry_factory, 0);
668
+ rb_define_method(geos_geometry_class, "dimension", method_geometry_dimension, 0);
669
+ rb_define_method(geos_geometry_class, "geometry_type", method_geometry_geometry_type, 0);
670
+ rb_define_method(geos_geometry_class, "srid", method_geometry_srid, 0);
671
+ rb_define_method(geos_geometry_class, "envelope", method_geometry_envelope, 0);
672
+ rb_define_method(geos_geometry_class, "boundary", method_geometry_boundary, 0);
673
+ rb_define_method(geos_geometry_class, "as_text", method_geometry_as_text, 0);
674
+ rb_define_method(geos_geometry_class, "to_s", method_geometry_as_text, 0);
675
+ rb_define_method(geos_geometry_class, "as_binary", method_geometry_as_binary, 0);
676
+ rb_define_method(geos_geometry_class, "is_empty?", method_geometry_is_empty, 0);
677
+ rb_define_method(geos_geometry_class, "is_simple?", method_geometry_is_simple, 0);
678
+ rb_define_method(geos_geometry_class, "equals?", method_geometry_equals, 1);
679
+ rb_define_method(geos_geometry_class, "==", method_geometry_equals, 1);
680
+ rb_define_method(geos_geometry_class, "eql?", method_geometry_eql, 1);
681
+ rb_define_method(geos_geometry_class, "disjoint?", method_geometry_disjoint, 1);
682
+ rb_define_method(geos_geometry_class, "intersects?", method_geometry_intersects, 1);
683
+ rb_define_method(geos_geometry_class, "touches?", method_geometry_touches, 1);
684
+ rb_define_method(geos_geometry_class, "crosses?", method_geometry_crosses, 1);
685
+ rb_define_method(geos_geometry_class, "within?", method_geometry_within, 1);
686
+ rb_define_method(geos_geometry_class, "contains?", method_geometry_contains, 1);
687
+ rb_define_method(geos_geometry_class, "overlaps?", method_geometry_overlaps, 1);
688
+ rb_define_method(geos_geometry_class, "relate?", method_geometry_relate, 2);
689
+ rb_define_method(geos_geometry_class, "distance", method_geometry_distance, 1);
690
+ rb_define_method(geos_geometry_class, "buffer", method_geometry_buffer, 1);
691
+ rb_define_method(geos_geometry_class, "convex_hull", method_geometry_convex_hull, 0);
692
+ rb_define_method(geos_geometry_class, "intersection", method_geometry_intersection, 1);
693
+ rb_define_method(geos_geometry_class, "*", method_geometry_intersection, 1);
694
+ rb_define_method(geos_geometry_class, "union", method_geometry_union, 1);
695
+ rb_define_method(geos_geometry_class, "+", method_geometry_union, 1);
696
+ rb_define_method(geos_geometry_class, "difference", method_geometry_difference, 1);
697
+ rb_define_method(geos_geometry_class, "-", method_geometry_difference, 1);
698
+ rb_define_method(geos_geometry_class, "sym_difference", method_geometry_sym_difference, 1);
699
+ rb_define_method(geos_geometry_class, "polygonize", method_geometry_polygonize, 0);
700
+ }
701
+
702
+
703
+ RGEO_END_C
704
+
705
+ #endif