rgeo 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/History.rdoc +22 -0
  2. data/README.rdoc +124 -0
  3. data/Version +1 -0
  4. data/ext/geos_c_impl/extconf.rb +72 -0
  5. data/ext/geos_c_impl/factory.c +468 -0
  6. data/ext/geos_c_impl/factory.h +217 -0
  7. data/ext/geos_c_impl/geometry.c +644 -0
  8. data/ext/geos_c_impl/geometry.h +65 -0
  9. data/ext/geos_c_impl/geometry_collection.c +580 -0
  10. data/ext/geos_c_impl/geometry_collection.h +79 -0
  11. data/ext/geos_c_impl/globals.h +58 -0
  12. data/ext/geos_c_impl/line_string.c +468 -0
  13. data/ext/geos_c_impl/line_string.h +74 -0
  14. data/ext/geos_c_impl/main.c +65 -0
  15. data/ext/geos_c_impl/point.c +201 -0
  16. data/ext/geos_c_impl/point.h +77 -0
  17. data/ext/geos_c_impl/polygon.c +259 -0
  18. data/ext/geos_c_impl/polygon.h +76 -0
  19. data/ext/geos_c_impl/preface.h +42 -0
  20. data/lib/rgeo.rb +68 -0
  21. data/lib/rgeo/errors.rb +59 -0
  22. data/lib/rgeo/features.rb +89 -0
  23. data/lib/rgeo/features/curve.rb +155 -0
  24. data/lib/rgeo/features/factory.rb +191 -0
  25. data/lib/rgeo/features/geometry.rb +560 -0
  26. data/lib/rgeo/features/geometry_collection.rb +118 -0
  27. data/lib/rgeo/features/line.rb +65 -0
  28. data/lib/rgeo/features/line_string.rb +101 -0
  29. data/lib/rgeo/features/linear_ring.rb +65 -0
  30. data/lib/rgeo/features/multi_curve.rb +112 -0
  31. data/lib/rgeo/features/multi_line_string.rb +65 -0
  32. data/lib/rgeo/features/multi_point.rb +72 -0
  33. data/lib/rgeo/features/multi_polygon.rb +96 -0
  34. data/lib/rgeo/features/multi_surface.rb +115 -0
  35. data/lib/rgeo/features/point.rb +97 -0
  36. data/lib/rgeo/features/polygon.rb +141 -0
  37. data/lib/rgeo/features/surface.rb +121 -0
  38. data/lib/rgeo/geo_json.rb +58 -0
  39. data/lib/rgeo/geo_json/coder.rb +305 -0
  40. data/lib/rgeo/geo_json/entities.rb +284 -0
  41. data/lib/rgeo/geo_json/interface.rb +95 -0
  42. data/lib/rgeo/geography.rb +75 -0
  43. data/lib/rgeo/geography/common/geometry_collection_methods.rb +206 -0
  44. data/lib/rgeo/geography/common/geometry_methods.rb +92 -0
  45. data/lib/rgeo/geography/common/helper.rb +102 -0
  46. data/lib/rgeo/geography/common/line_string_methods.rb +187 -0
  47. data/lib/rgeo/geography/common/point_methods.rb +149 -0
  48. data/lib/rgeo/geography/common/polygon_methods.rb +122 -0
  49. data/lib/rgeo/geography/factories.rb +136 -0
  50. data/lib/rgeo/geography/factory.rb +246 -0
  51. data/lib/rgeo/geography/projected_window.rb +467 -0
  52. data/lib/rgeo/geography/simple_mercator/feature_classes.rb +320 -0
  53. data/lib/rgeo/geography/simple_mercator/feature_methods.rb +291 -0
  54. data/lib/rgeo/geography/simple_mercator/projector.rb +116 -0
  55. data/lib/rgeo/geography/simple_spherical/calculations.rb +70 -0
  56. data/lib/rgeo/geography/simple_spherical/geometry_collection_impl.rb +66 -0
  57. data/lib/rgeo/geography/simple_spherical/geometry_methods.rb +59 -0
  58. data/lib/rgeo/geography/simple_spherical/line_string_impl.rb +104 -0
  59. data/lib/rgeo/geography/simple_spherical/multi_line_string_impl.rb +67 -0
  60. data/lib/rgeo/geography/simple_spherical/multi_point_impl.rb +67 -0
  61. data/lib/rgeo/geography/simple_spherical/multi_polygon_impl.rb +67 -0
  62. data/lib/rgeo/geography/simple_spherical/point_impl.rb +85 -0
  63. data/lib/rgeo/geography/simple_spherical/polygon_impl.rb +66 -0
  64. data/lib/rgeo/geos.rb +72 -0
  65. data/lib/rgeo/geos/factory.rb +260 -0
  66. data/lib/rgeo/geos/impl_additions.rb +57 -0
  67. data/lib/rgeo/geos/interface.rb +74 -0
  68. data/lib/rgeo/version.rb +52 -0
  69. data/tests/geos/tc_factory.rb +91 -0
  70. data/tests/geos/tc_geometry_collection.rb +226 -0
  71. data/tests/geos/tc_line_string.rb +310 -0
  72. data/tests/geos/tc_misc.rb +72 -0
  73. data/tests/geos/tc_multi_line_string.rb +211 -0
  74. data/tests/geos/tc_multi_point.rb +202 -0
  75. data/tests/geos/tc_multi_polygon.rb +210 -0
  76. data/tests/geos/tc_point.rb +305 -0
  77. data/tests/geos/tc_polygon.rb +240 -0
  78. data/tests/simple_mercator/tc_point.rb +303 -0
  79. data/tests/simple_mercator/tc_window.rb +219 -0
  80. data/tests/tc_geojson.rb +230 -0
  81. data/tests/tc_oneoff.rb +61 -0
  82. metadata +162 -0
data/History.rdoc ADDED
@@ -0,0 +1,22 @@
1
+ === 0.1.10 / 2010-10-19
2
+
3
+ Initial public release. This release is considered pre-alpha quality and is being released for experimentation and feedback. We are using it in production in a limited capacity at GeoPage, but we do not yet recommend general production deployment because there are a number of known bugs and incomplete areas, and many features and APIs are still in flux.
4
+
5
+ Status:
6
+
7
+ * GEOS-based Cartesian implementation is tested and should be fairly stable.
8
+ * GeoJSON parsers and generators are tested and should be fairly stable.
9
+ * Parts of SimpleMercator implementation are fairly stable, but test coverage of more advanced features is still lacking.
10
+ * SimpleSpherical implementation is under construction and not yet available.
11
+ * Rails (ActiveRecord or ActiveModel) integration is pending.
12
+ * Several other integration features, including possible SimpleGeo integration, are pending.
13
+
14
+ Changes since 0.1.9:
15
+
16
+ * Eliminated a few (harmless) compiler warnings when compiling the GEOS bridge under Ruby 1.9.2 on Snow Leopard.
17
+ * Modified file headers, copyright notices, and README files for public release.
18
+ * Changed name from "gp_rgeo" to "rgeo" for public release.
19
+
20
+ === 0.1.9
21
+
22
+ This and earlier versions were tested internally at GeoPage, Inc. but not publicly released.
data/README.rdoc ADDED
@@ -0,0 +1,124 @@
1
+ == RGeo
2
+
3
+ RGeo is a spatial data library for Ruby.
4
+
5
+ It provides an implementation of the Open Geospatial Consortium's Simple
6
+ Features Specification, used by most standard spatial/geographic data
7
+ storage systems such as PostGIS. It also provides a suite of useful tools
8
+ for writing location-based applications using Ruby-based frameworks such
9
+ as Ruby On Rails.
10
+
11
+ === Summary
12
+
13
+ RGeo is a core component for writing location-based applications in the
14
+ Ruby programming language. It provides the basic tools for modeling
15
+ location data and communicating with geolocation-aware storage systems
16
+ and location-based services.
17
+
18
+ Use RGeo to:
19
+
20
+ * Represent spatial and geolocation data objects such as points, lines,
21
+ and polygons in your Ruby application.
22
+ * Perform standard spatial analysis operations such as finding
23
+ intersections, creating buffers, and computing lengths and areas.
24
+ * Correctly handle spherical geometry, and compute projections for
25
+ geographic data analysis.
26
+ * Store and retrieve spatial data in industry standard spatial storage
27
+ systems such as PostGIS.
28
+ * Generate and interpret GeoJSON data for communication with common
29
+ location-based services.
30
+ * Extend Ruby On Rails to handle location data in a web application.
31
+ * Write spatial applications following the latest open standards from
32
+ the Open Geospatial Consortium.
33
+
34
+ === Requirements
35
+
36
+ RGeo has the following prerequisites:
37
+
38
+ * Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred.
39
+ * GEOS 3.2 or later. This C/C++ library may be available via your
40
+ operating system's package manager, or you can download it from
41
+ http://trac.osgeo.org/geos/
42
+
43
+ === Installation
44
+
45
+ Install RGeo as a gem:
46
+
47
+ gem install rgeo
48
+
49
+ Note: By default, the gem installation looks for the required GEOS
50
+ library in the following locations:
51
+
52
+ * /usr/local
53
+ * /usr/local/geos
54
+ * /opt/local
55
+ * /usr
56
+
57
+ If GEOS has been installed in a different location, you must provide its
58
+ installation prefix directory using the "--with-geos-dir" option.
59
+ For example:
60
+
61
+ gem install rgeo -- --with-geos-dir=/var/local
62
+
63
+ === Known issues and to-do items
64
+
65
+ RGeo is currently under development and several planned features are not
66
+ yet complete. These include:
67
+
68
+ * Test coverage of the SimpleMercator implementation.
69
+ * The spherical geometry data objects.
70
+ * Rails (ActiveRecord or ActiveModel) integration.
71
+ * Other third-party integration, including possibly SimpleGeo.
72
+ * JRuby support via JTS.
73
+ * Rubinius support.
74
+
75
+ Additionally, not all implemented features are well-tested yet. In
76
+ general, we currently consider this library to be "pre-alpha" quality,
77
+ intended for experimentation and feedback but not production. It has been
78
+ deployed in production at GeoPage, but only in a limited capacity.
79
+
80
+ === Development and support
81
+
82
+ Documentation is available at http://virtuoso.rubyforge.org/rgeo/README_rdoc.html
83
+
84
+ Source code is hosted on Github at http://github.com/dazuma/rgeo
85
+
86
+ Report bugs on Github issues at http://github.org/dazuma/rgeo/issues
87
+
88
+ Contact the author at dazuma at gmail dot com.
89
+
90
+ === Acknowledgments
91
+
92
+ RGeo is written by Daniel Azuma (http://www.daniel-azuma.com/).
93
+
94
+ Development of RGeo is sponsored by GeoPage, Inc. (http://www.geopage.com/).
95
+
96
+ === License
97
+
98
+ Copyright 2010 Daniel Azuma
99
+
100
+ All rights reserved.
101
+
102
+ Redistribution and use in source and binary forms, with or without
103
+ modification, are permitted provided that the following conditions are met:
104
+
105
+ * Redistributions of source code must retain the above copyright notice,
106
+ this list of conditions and the following disclaimer.
107
+ * Redistributions in binary form must reproduce the above copyright notice,
108
+ this list of conditions and the following disclaimer in the documentation
109
+ and/or other materials provided with the distribution.
110
+ * Neither the name of the copyright holder, nor the names of any other
111
+ contributors to this software, may be used to endorse or promote products
112
+ derived from this software without specific prior written permission.
113
+
114
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
115
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
116
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
117
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
118
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
119
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
120
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
121
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
122
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
123
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
124
+ POSSIBILITY OF SUCH DAMAGE.
data/Version ADDED
@@ -0,0 +1 @@
1
+ 0.1.10
@@ -0,0 +1,72 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Makefile builder for GEOS wrapper
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ require 'mkmf'
38
+
39
+ header_dirs_ =
40
+ [
41
+ '/usr/local/include',
42
+ '/usr/local/geos/include',
43
+ '/opt/local/include',
44
+ ::Config::CONFIG['includedir'],
45
+ '/usr/include',
46
+ ]
47
+ lib_dirs_ =
48
+ [
49
+ '/usr/local/lib',
50
+ '/usr/local/geos/lib',
51
+ '/opt/local/lib',
52
+ ::Config::CONFIG['libdir'],
53
+ '/usr/lib',
54
+ ]
55
+ header_dirs_.delete_if{ |path_| !::File.directory?(path_) }
56
+ lib_dirs_.delete_if{ |path_| !::File.directory?(path_) }
57
+
58
+ found_geos_ = false
59
+ header_dirs_, lib_dirs_ = dir_config('geos', header_dirs_, lib_dirs_)
60
+ if have_header('geos_c.h')
61
+ $libs << ' -lgeos -lgeos_c'
62
+ if have_func('initGEOS_r', 'geos_c.h')
63
+ found_geos_ = true
64
+ else
65
+ $libs.gsub!(' -lgeos -lgeos_c', '')
66
+ end
67
+ end
68
+ unless found_geos_
69
+ puts "**** WARNING: Unable to find GEOS headers or GEOS version is too old."
70
+ puts "**** Compiling without GEOS support."
71
+ end
72
+ create_makefile('rgeo/geos/geos_c_impl')
@@ -0,0 +1,468 @@
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
+ #include "preface.h"
39
+
40
+ #ifdef RGEO_GEOS_SUPPORTED
41
+
42
+ #include <ruby.h>
43
+ #include <geos_c.h>
44
+
45
+ #include "factory.h"
46
+ #include "geometry.h"
47
+ #include "point.h"
48
+ #include "line_string.h"
49
+ #include "polygon.h"
50
+ #include "geometry_collection.h"
51
+
52
+ #ifdef __cplusplus
53
+ extern "C" {
54
+ #if 0
55
+ }
56
+ #endif
57
+ #endif
58
+
59
+
60
+ /**** RUBY AND GEOS CALLBACKS ****/
61
+
62
+
63
+ // NOP message handler. GEOS requires that a message handler be set
64
+ // for every context handle.
65
+
66
+ static void message_handler(const char* fmt, ...)
67
+ {
68
+ }
69
+
70
+
71
+ // Destroy function for factory data. We destroy any serialization
72
+ // objects that have been created for the factory, and then destroy
73
+ // the GEOS context, before freeing the factory data itself.
74
+
75
+ static void destroy_factory_func(RGeo_FactoryData* data)
76
+ {
77
+ if (data->wkt_reader) {
78
+ GEOSWKTReader_destroy_r(data->geos_context, data->wkt_reader);
79
+ }
80
+ if (data->wkb_reader) {
81
+ GEOSWKBReader_destroy_r(data->geos_context, data->wkb_reader);
82
+ }
83
+ if (data->wkt_writer) {
84
+ GEOSWKTWriter_destroy_r(data->geos_context, data->wkt_writer);
85
+ }
86
+ if (data->wkb_writer) {
87
+ GEOSWKBWriter_destroy_r(data->geos_context, data->wkb_writer);
88
+ }
89
+ finishGEOS_r(data->geos_context);
90
+ free(data);
91
+ }
92
+
93
+
94
+ // Destroy function for geometry data. We destroy the internal
95
+ // GEOS geometry (if present) before freeing the data itself.
96
+
97
+ static void destroy_geometry_func(RGeo_GeometryData* data)
98
+ {
99
+ if (data->geom) {
100
+ GEOSGeom_destroy_r(RGEO_CONTEXT_FROM_FACTORY(data->factory), data->geom);
101
+ }
102
+ free(data);
103
+ }
104
+
105
+
106
+ // Mark function for geometry data. This marks the factory and klasses
107
+ // held by the geometry so those don't get collected.
108
+
109
+ static void mark_geometry_func(RGeo_GeometryData* data)
110
+ {
111
+ if (!NIL_P(data->factory)) {
112
+ rb_gc_mark(data->factory);
113
+ }
114
+ if (!NIL_P(data->klasses)) {
115
+ rb_gc_mark(data->klasses);
116
+ }
117
+ }
118
+
119
+
120
+ // Destroy function for globals data. We don't need to destroy any
121
+ // auxiliary data for now...
122
+
123
+ static void destroy_globals_func(RGeo_Globals* data)
124
+ {
125
+ free(data);
126
+ }
127
+
128
+
129
+ // Mark function for globals data. This marks the default factory held
130
+ // by the globals so it doesn't get collected.
131
+
132
+ static void mark_globals_func(RGeo_Globals* data)
133
+ {
134
+ rb_gc_mark(data->default_factory);
135
+ }
136
+
137
+
138
+ /**** RUBY METHOD DEFINITIONS ****/
139
+
140
+
141
+ static VALUE method_factory_srid(VALUE self)
142
+ {
143
+ return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->srid);
144
+ }
145
+
146
+
147
+ static VALUE method_factory_buffer_resolution(VALUE self)
148
+ {
149
+ return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->buffer_resolution);
150
+ }
151
+
152
+
153
+ static VALUE method_factory_flags(VALUE self)
154
+ {
155
+ return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->flags);
156
+ }
157
+
158
+
159
+ static VALUE method_factory_parse_wkt(VALUE self, VALUE str)
160
+ {
161
+ Check_Type(str, T_STRING);
162
+ GEOSWKTReader* wkt_reader = RGEO_FACTORY_DATA_PTR(self)->wkt_reader;
163
+ if (!wkt_reader) {
164
+ wkt_reader = GEOSWKTReader_create_r(RGEO_CONTEXT_FROM_FACTORY(self));
165
+ RGEO_FACTORY_DATA_PTR(self)->wkt_reader = wkt_reader;
166
+ }
167
+ VALUE result = Qnil;
168
+ if (wkt_reader) {
169
+ GEOSGeometry* geom = GEOSWKTReader_read_r(RGEO_CONTEXT_FROM_FACTORY(self), wkt_reader, RSTRING_PTR(str));
170
+ if (geom) {
171
+ result = rgeo_wrap_geos_geometry(self, geom, Qnil);
172
+ }
173
+ }
174
+ return result;
175
+ }
176
+
177
+
178
+ static VALUE method_factory_parse_wkb(VALUE self, VALUE str)
179
+ {
180
+ Check_Type(str, T_STRING);
181
+ GEOSWKBReader* wkb_reader = RGEO_FACTORY_DATA_PTR(self)->wkb_reader;
182
+ if (!wkb_reader) {
183
+ wkb_reader = GEOSWKBReader_create_r(RGEO_CONTEXT_FROM_FACTORY(self));
184
+ RGEO_FACTORY_DATA_PTR(self)->wkb_reader = wkb_reader;
185
+ }
186
+ VALUE result = Qnil;
187
+ if (wkb_reader) {
188
+ GEOSGeometry* geom = GEOSWKBReader_read_r(RGEO_CONTEXT_FROM_FACTORY(self), wkb_reader, (unsigned char*)RSTRING_PTR(str), (size_t)RSTRING_LEN(str));
189
+ if (geom) {
190
+ result = rgeo_wrap_geos_geometry(self, geom, Qnil);
191
+ }
192
+ }
193
+ return result;
194
+ }
195
+
196
+
197
+ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE buffer_resolution)
198
+ {
199
+ VALUE result = Qnil;
200
+ RGeo_FactoryData* data = ALLOC(RGeo_FactoryData);
201
+ if (data) {
202
+ GEOSContextHandle_t context = initGEOS_r(message_handler, message_handler);
203
+ if (context) {
204
+ VALUE wrapped_globals = rb_const_get_at(klass, rb_intern("INTERNAL_CGLOBALS"));
205
+ data->globals = (RGeo_Globals*)DATA_PTR(wrapped_globals);
206
+ data->geos_context = context;
207
+ data->flags = NUM2INT(flags);
208
+ data->srid = NUM2INT(srid);
209
+ data->buffer_resolution = NUM2INT(buffer_resolution);
210
+ data->wkt_reader = NULL;
211
+ data->wkb_reader = NULL;
212
+ data->wkt_writer = NULL;
213
+ data->wkb_writer = NULL;
214
+ result = Data_Wrap_Struct(klass, NULL, destroy_factory_func, data);
215
+ }
216
+ else {
217
+ free(data);
218
+ }
219
+ }
220
+ return result;
221
+ }
222
+
223
+
224
+ /**** INITIALIZATION FUNCTION ****/
225
+
226
+
227
+ RGeo_Globals* rgeo_init_geos_factory()
228
+ {
229
+ RGeo_Globals* globals = ALLOC(RGeo_Globals);
230
+ VALUE rgeo_module = rb_define_module("RGeo");
231
+ globals->geos_module = rb_define_module_under(rgeo_module, "Geos");
232
+ globals->features_module = rb_define_module_under(rgeo_module, "Features");
233
+ globals->default_factory = Qnil;
234
+
235
+ // Add C methods to the factory.
236
+ VALUE geos_factory_class = rb_const_get_at(globals->geos_module, rb_intern("Factory"));
237
+ rb_define_method(geos_factory_class, "_parse_wkt_impl", method_factory_parse_wkt, 1);
238
+ rb_define_method(geos_factory_class, "_parse_wkb_impl", method_factory_parse_wkb, 1);
239
+ rb_define_method(geos_factory_class, "_srid", method_factory_srid, 0);
240
+ rb_define_method(geos_factory_class, "_buffer_resolution", method_factory_buffer_resolution, 0);
241
+ rb_define_method(geos_factory_class, "_flags", method_factory_flags, 0);
242
+ rb_define_module_function(geos_factory_class, "_create", cmethod_factory_create, 3);
243
+
244
+ // Wrap the globals in a Ruby object and store it off so we have access
245
+ // to it later. Each factory instance will reference it internally.
246
+ VALUE wrapped_globals = Data_Wrap_Struct(rb_cObject, mark_globals_func, destroy_globals_func, globals);
247
+ rb_define_const(geos_factory_class, "INTERNAL_CGLOBALS", wrapped_globals);
248
+
249
+ // Default factory used internally.
250
+ globals->default_factory = rb_funcall(geos_factory_class, rb_intern("create"), 0);
251
+
252
+ return globals;
253
+ }
254
+
255
+
256
+ /**** OTHER PUBLIC FUNCTIONS ****/
257
+
258
+
259
+ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
260
+ {
261
+ VALUE result = Qnil;
262
+ if (geom || !NIL_P(klass)) {
263
+ VALUE klasses = Qnil;
264
+ if (TYPE(klass) != T_CLASS) {
265
+ const char* klass_name = NULL;
266
+ char is_collection = 0;
267
+ switch (GEOSGeomTypeId_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom)) {
268
+ case GEOS_POINT:
269
+ klass_name = "PointImpl";
270
+ break;
271
+ case GEOS_LINESTRING:
272
+ klass_name = "LineStringImpl";
273
+ break;
274
+ case GEOS_LINEARRING:
275
+ klass_name = "LinearRingImpl";
276
+ break;
277
+ case GEOS_POLYGON:
278
+ klass_name = "PolygonImpl";
279
+ break;
280
+ case GEOS_MULTIPOINT:
281
+ klass_name = "MultiPointImpl";
282
+ is_collection = 1;
283
+ break;
284
+ case GEOS_MULTILINESTRING:
285
+ klass_name = "MultiLineStringImpl";
286
+ is_collection = 1;
287
+ break;
288
+ case GEOS_MULTIPOLYGON:
289
+ klass_name = "MultiPolygonImpl";
290
+ is_collection = 1;
291
+ break;
292
+ case GEOS_GEOMETRYCOLLECTION:
293
+ klass_name = "GeometryCollectionImpl";
294
+ is_collection = 1;
295
+ break;
296
+ default:
297
+ klass_name = "GeometryImpl";
298
+ break;
299
+ }
300
+ if (TYPE(klass) == T_ARRAY && is_collection) {
301
+ klasses = klass;
302
+ }
303
+ klass = rb_const_get_at(RGEO_GLOBALS_FROM_FACTORY(factory)->geos_module, rb_intern(klass_name));
304
+ }
305
+ RGeo_GeometryData* data = ALLOC(RGeo_GeometryData);
306
+ if (data) {
307
+ if (geom) {
308
+ GEOSSetSRID_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom, RGEO_FACTORY_DATA_PTR(factory)->srid);
309
+ }
310
+ data->geom = geom;
311
+ data->factory = factory;
312
+ data->klasses = klasses;
313
+ result = Data_Wrap_Struct(klass, mark_geometry_func, destroy_geometry_func, data);
314
+ }
315
+ }
316
+ return result;
317
+ }
318
+
319
+
320
+ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass)
321
+ {
322
+ VALUE result = Qnil;
323
+ if (geom) {
324
+ GEOSGeometry* clone_geom = GEOSGeom_clone_r(RGEO_CONTEXT_FROM_FACTORY(factory), geom);
325
+ if (clone_geom) {
326
+ result = rgeo_wrap_geos_geometry(factory, clone_geom, klass);
327
+ }
328
+ }
329
+ return result;
330
+ }
331
+
332
+
333
+ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj)
334
+ {
335
+ VALUE object = rb_funcall(factory, rb_intern("convert"), 1, obj);
336
+ const GEOSGeometry* geom = NULL;
337
+ if (!NIL_P(object)) {
338
+ geom = RGEO_GET_GEOS_GEOMETRY(object);
339
+ }
340
+ return geom;
341
+ }
342
+
343
+
344
+ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(RGeo_Globals* globals, VALUE obj, VALUE* klasses)
345
+ {
346
+ if (klasses) {
347
+ *klasses = Qnil;
348
+ }
349
+ VALUE object = rb_funcall(globals->default_factory, rb_intern("convert"), 2, obj, Qtrue);
350
+ GEOSGeometry* geom = NULL;
351
+ if (!NIL_P(object)) {
352
+ geom = RGEO_GEOMETRY_DATA_PTR(object)->geom;
353
+ RGEO_GEOMETRY_DATA_PTR(object)->geom = NULL;
354
+ RGEO_GEOMETRY_DATA_PTR(object)->factory = Qnil;
355
+ RGEO_GEOMETRY_DATA_PTR(object)->klasses = Qnil;
356
+ if (klasses) {
357
+ *klasses = rgeo_is_geos_object(obj) ? RGEO_KLASSES_FROM_GEOMETRY(obj) : Qnil;
358
+ }
359
+ }
360
+ return geom;
361
+ }
362
+
363
+
364
+ char rgeo_is_geos_object(VALUE obj)
365
+ {
366
+ return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? 1 : 0;
367
+ }
368
+
369
+
370
+ const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj)
371
+ {
372
+ return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? RGEO_GET_GEOS_GEOMETRY(obj) : NULL;
373
+ }
374
+
375
+
376
+ VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2)
377
+ {
378
+ VALUE result = Qnil;
379
+ if (geom1 && geom2) {
380
+ const GEOSCoordSequence* cs1 = GEOSGeom_getCoordSeq_r(context, geom1);
381
+ const GEOSCoordSequence* cs2 = GEOSGeom_getCoordSeq_r(context, geom2);
382
+ if (cs1 && cs2) {
383
+ char hasz1 = GEOSHasZ_r(context, geom1);
384
+ char hasz2 = GEOSHasZ_r(context, geom2);
385
+ if (hasz1 != 2 && hasz2 != 2) {
386
+ if (hasz1 == hasz2) {
387
+ unsigned int len1 = 0;
388
+ unsigned int len2 = 0;
389
+ if (GEOSCoordSeq_getSize_r(context, cs1, &len1) && GEOSCoordSeq_getSize_r(context, cs2, &len2)) {
390
+ if (len1 == len2) {
391
+ result = Qtrue;
392
+ unsigned int i;
393
+ double val1, val2;
394
+ for (i=0; i<len1; ++i) {
395
+ if (GEOSCoordSeq_getX_r(context, cs1, i, &val1) && GEOSCoordSeq_getX_r(context, cs2, i, &val2)) {
396
+ if (val1 == val2) {
397
+ if (GEOSCoordSeq_getY_r(context, cs1, i, &val1) && GEOSCoordSeq_getY_r(context, cs2, i, &val2)) {
398
+ if (val1 == val2) {
399
+ if (hasz1) {
400
+ if (GEOSCoordSeq_getZ_r(context, cs1, i, &val1) && GEOSCoordSeq_getZ_r(context, cs2, i, &val2)) {
401
+ if (val1 != val2) {
402
+ result = Qfalse;
403
+ break;
404
+ }
405
+ }
406
+ else { // Failed to get Z coords
407
+ result = Qnil;
408
+ break;
409
+ }
410
+ }
411
+ }
412
+ else { // Y coords are different
413
+ result = Qfalse;
414
+ break;
415
+ }
416
+ }
417
+ else { // Failed to get Y coords
418
+ result = Qnil;
419
+ break;
420
+ }
421
+ }
422
+ else { // X coords are different
423
+ result = Qfalse;
424
+ break;
425
+ }
426
+ }
427
+ else { // Failed to get X coords
428
+ result = Qnil;
429
+ break;
430
+ }
431
+ } // Iteration over coords
432
+ }
433
+ else { // Lengths are different
434
+ result = Qfalse;
435
+ }
436
+ }
437
+ }
438
+ else { // Z coord existence is different
439
+ result = Qfalse;
440
+ }
441
+ }
442
+ }
443
+ }
444
+ return result;
445
+ }
446
+
447
+
448
+ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2)
449
+ {
450
+ VALUE result = Qnil;
451
+ if (rb_obj_class(obj1) != rb_obj_class(obj2)) {
452
+ result = Qfalse;
453
+ }
454
+ else {
455
+ result = rb_funcall(RGEO_FACTORY_FROM_GEOMETRY(obj1), rb_intern("eql?"), 1, RGEO_FACTORY_FROM_GEOMETRY(obj2));
456
+ }
457
+ return result;
458
+ }
459
+
460
+
461
+ #ifdef __cplusplus
462
+ #if 0
463
+ {
464
+ #endif
465
+ }
466
+ #endif
467
+
468
+ #endif