schleyfox-rgeo 0.2.5

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 (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,75 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Geographic data for RGeo
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
+ module RGeo
38
+
39
+
40
+ # The Geographic implementation actually comprises a suite of
41
+ # implementations with one common feature: they represent geographic
42
+ # latitude/longitude coordinates measured in degrees. The "x"
43
+ # coordinate corresponds to longitude, and the "y" coordinate to
44
+ # latitude. Thus, coordinates are often expressed in reverse
45
+ # (i.e. long-lat) order. e.g.
46
+ #
47
+ # location = geographic_factory.point(long, lat)
48
+ #
49
+ # Some geographic implementations include a secondary factory that
50
+ # represents a projection. For these implementations, you can quickly
51
+ # transform data between lat/long coordinates and the projected
52
+ # coordinate system, and most calculations are done in the projected
53
+ # coordinate system. For implementations that do not include this
54
+ # secondary projection factory, calculations are done on the sphereoid.
55
+ # See the various class methods of Geographic for more information on
56
+ # the behaviors of the factories they generate.
57
+
58
+ module Geographic
59
+ end
60
+
61
+
62
+ end
63
+
64
+
65
+ # Implementation files.
66
+ require 'rgeo/geographic/factory'
67
+ require 'rgeo/geographic/projected_window'
68
+ require 'rgeo/geographic/interface'
69
+ require 'rgeo/geographic/spherical_math'
70
+ require 'rgeo/geographic/spherical_feature_methods'
71
+ require 'rgeo/geographic/spherical_feature_classes'
72
+ require 'rgeo/geographic/proj4_projector'
73
+ require 'rgeo/geographic/simple_mercator_projector'
74
+ require 'rgeo/geographic/projected_feature_methods'
75
+ require 'rgeo/geographic/projected_feature_classes'
@@ -0,0 +1,287 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Geographic data factory implementation
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
+ module RGeo
38
+
39
+ module Geographic
40
+
41
+
42
+ # This class implements the various factories for geography features.
43
+ # See methods of the RGeo::Geographic module for the API for creating
44
+ # geography factories.
45
+
46
+ class Factory
47
+
48
+ include Feature::Factory::Instance
49
+
50
+
51
+ def initialize(impl_prefix_, opts_={}) # :nodoc:
52
+ @impl_prefix = impl_prefix_
53
+ @point_class = Geographic.const_get("#{impl_prefix_}PointImpl")
54
+ @line_string_class = Geographic.const_get("#{impl_prefix_}LineStringImpl")
55
+ @linear_ring_class = Geographic.const_get("#{impl_prefix_}LinearRingImpl")
56
+ @line_class = Geographic.const_get("#{impl_prefix_}LineImpl")
57
+ @polygon_class = Geographic.const_get("#{impl_prefix_}PolygonImpl")
58
+ @geometry_collection_class = Geographic.const_get("#{impl_prefix_}GeometryCollectionImpl")
59
+ @multi_point_class = Geographic.const_get("#{impl_prefix_}MultiPointImpl")
60
+ @multi_line_string_class = Geographic.const_get("#{impl_prefix_}MultiLineStringImpl")
61
+ @multi_polygon_class = Geographic.const_get("#{impl_prefix_}MultiPolygonImpl")
62
+ @support_z = opts_[:has_z_coordinate] ? true : false
63
+ @support_m = opts_[:has_m_coordinate] ? true : false
64
+ @srid = opts_[:srid] || 4326
65
+ @proj4 = opts_[:proj4]
66
+ if CoordSys::Proj4.supported?
67
+ if @proj4.kind_of?(::String) || @proj4.kind_of?(::Hash)
68
+ @proj4 = CoordSys::Proj4.create(@proj4)
69
+ end
70
+ else
71
+ @proj4 = nil
72
+ end
73
+ @coord_sys = opts_[:coord_sys]
74
+ if @coord_sys.kind_of?(::String)
75
+ @coord_sys = CoordSys::CS.create_from_wkt(@coord_sys) rescue nil
76
+ end
77
+ end
78
+
79
+
80
+ def _set_projector(projector_) # :nodoc:
81
+ @projector = projector_
82
+ end
83
+
84
+
85
+ # Equivalence test.
86
+
87
+ def eql?(rhs_)
88
+ rhs_.is_a?(Geographic::Factory) &&
89
+ @impl_prefix == rhs_.instance_variable_get(:@impl_prefix) &&
90
+ @support_z == rhs_.instance_variable_get(:@support_z) &&
91
+ @support_m == rhs_.instance_variable_get(:@support_m) &&
92
+ @proj4 == rhs_.instance_variable_get(:@proj4)
93
+ end
94
+ alias_method :==, :eql?
95
+
96
+
97
+ # Returns the srid reported by this factory.
98
+
99
+ def srid
100
+ @srid
101
+ end
102
+
103
+
104
+ # Returns true if this factory supports a projection.
105
+
106
+ def has_projection?
107
+ !@projector.nil?
108
+ end
109
+
110
+
111
+ # Returns the factory for the projected coordinate space,
112
+ # or nil if this factory does not support a projection.
113
+
114
+ def projection_factory
115
+ @projector ? @projector.projection_factory : nil
116
+ end
117
+
118
+
119
+ # Projects the given geometry into the projected coordinate space,
120
+ # and returns the projected geometry.
121
+ # Returns nil if this factory does not support a projection.
122
+ # Raises Error::InvalidGeometry if the given geometry is not of
123
+ # this factory.
124
+
125
+ def project(geometry_)
126
+ return nil unless @projector
127
+ unless geometry_.factory == self
128
+ raise Error::InvalidGeometry, 'Wrong geometry type'
129
+ end
130
+ @projector.project(geometry_)
131
+ end
132
+
133
+
134
+ # Reverse-projects the given geometry from the projected coordinate
135
+ # space into lat-long space.
136
+ # Raises Error::InvalidGeometry if the given geometry is not of
137
+ # the projection defined by this factory.
138
+
139
+ def unproject(geometry_)
140
+ unless @projector && @projector.projection_factory == geometry_.factory
141
+ raise Error::InvalidGeometry, 'You can unproject only features that are in the projected coordinate space.'
142
+ end
143
+ @projector.unproject(geometry_)
144
+ end
145
+
146
+
147
+ # Returns true if this factory supports a projection and the
148
+ # projection wraps its x (easting) direction. For example, a
149
+ # Mercator projection wraps, but a local projection that is valid
150
+ # only for a small area does not wrap. Returns nil if this factory
151
+ # does not support or a projection, or if it is not known whether
152
+ # or not it wraps.
153
+
154
+ def projection_wraps?
155
+ @projector ? @projector.wraps? : nil
156
+ end
157
+
158
+
159
+ # Returns a ProjectedWindow specifying the limits of the domain of
160
+ # the projection space.
161
+ # Returns nil if this factory does not support a projection, or the
162
+ # projection limits are not known.
163
+
164
+ def projection_limits_window
165
+ if @projector
166
+ unless defined?(@projection_limits_window)
167
+ @projection_limits_window = @projector.limits_window
168
+ end
169
+ @projection_limits_window
170
+ else
171
+ nil
172
+ end
173
+ end
174
+
175
+
176
+ # See ::RGeo::Feature::Factory#property
177
+
178
+ def property(name_)
179
+ case name_
180
+ when :has_z_coordinate
181
+ @support_z
182
+ when :has_m_coordinate
183
+ @support_m
184
+ when :is_geographic
185
+ true
186
+ else
187
+ nil
188
+ end
189
+ end
190
+
191
+
192
+ # See ::RGeo::Feature::Factory#parse_wkt
193
+
194
+ def parse_wkt(str_)
195
+ WKRep::WKTParser.new(self).parse(str_)
196
+ end
197
+
198
+
199
+ # See ::RGeo::Feature::Factory#parse_wkb
200
+
201
+ def parse_wkb(str_)
202
+ WKRep::WKBParser.new(self).parse(str_)
203
+ end
204
+
205
+
206
+ # See ::RGeo::Feature::Factory#point
207
+
208
+ def point(x_, y_, *extra_)
209
+ @point_class.new(self, x_, y_, *extra_) rescue nil
210
+ end
211
+
212
+
213
+ # See ::RGeo::Feature::Factory#line_string
214
+
215
+ def line_string(points_)
216
+ @line_string_class.new(self, points_) rescue nil
217
+ end
218
+
219
+
220
+ # See ::RGeo::Feature::Factory#line
221
+
222
+ def line(start_, end_)
223
+ @line_class.new(self, start_, end_) rescue nil
224
+ end
225
+
226
+
227
+ # See ::RGeo::Feature::Factory#linear_ring
228
+
229
+ def linear_ring(points_)
230
+ @linear_ring_class.new(self, points_) rescue nil
231
+ end
232
+
233
+
234
+ # See ::RGeo::Feature::Factory#polygon
235
+
236
+ def polygon(outer_ring_, inner_rings_=nil)
237
+ @polygon_class.new(self, outer_ring_, inner_rings_) rescue nil
238
+ end
239
+
240
+
241
+ # See ::RGeo::Feature::Factory#collection
242
+
243
+ def collection(elems_)
244
+ @geometry_collection_class.new(self, elems_) rescue nil
245
+ end
246
+
247
+
248
+ # See ::RGeo::Feature::Factory#multi_point
249
+
250
+ def multi_point(elems_)
251
+ @multi_point_class.new(self, elems_) rescue nil
252
+ end
253
+
254
+
255
+ # See ::RGeo::Feature::Factory#multi_line_string
256
+
257
+ def multi_line_string(elems_)
258
+ @multi_line_string_class.new(self, elems_) rescue nil
259
+ end
260
+
261
+
262
+ # See ::RGeo::Feature::Factory#multi_polygon
263
+
264
+ def multi_polygon(elems_)
265
+ @multi_polygon_class.new(self, elems_) rescue nil
266
+ end
267
+
268
+
269
+ # See ::RGeo::Feature::Factory#proj4
270
+
271
+ def proj4
272
+ @proj4
273
+ end
274
+
275
+
276
+ # See ::RGeo::Feature::Factory#coord_sys
277
+
278
+ def coord_sys
279
+ @coord_sys
280
+ end
281
+
282
+
283
+ end
284
+
285
+ end
286
+
287
+ end
@@ -0,0 +1,410 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Access to geographic data factories
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
+ module RGeo
38
+
39
+ module Geographic
40
+
41
+ class << self
42
+
43
+
44
+ # Creates and returns a geographic factory that does not include a
45
+ # a projection, and which performs calculations assuming a
46
+ # spherical earth. In other words, geodesics are treated as great
47
+ # circle arcs, and geometric calculations are handled accordingly.
48
+ # Size and distance calculations report results in meters.
49
+ # This implementation is thus ideal for everyday calculations on
50
+ # the globe in which good accuracy is desired, but in which it is
51
+ # not deemed necessary to perform the complex ellipsoidal
52
+ # calculations needed for greater precision.
53
+ #
54
+ # The maximum error is about 0.5 percent, for objects and
55
+ # calculations that span a significant percentage of the globe, due
56
+ # to distortion caused by rotational flattening of the earth. For
57
+ # calculations that span a much smaller area, the error can drop to
58
+ # a few meters or less.
59
+ #
60
+ # === Limitations
61
+ #
62
+ # This implementation does not implement some of the more advanced
63
+ # geometric operations. In particular:
64
+ #
65
+ # * Relational operators such as Feature::Geometry#intersects? are
66
+ # not implemented for most types.
67
+ # * Relational constructors such as Feature::Geometry#union are
68
+ # not implemented for most types.
69
+ # * Buffer, convex hull, and envelope calculations are not
70
+ # implemented for most types. Boundaries are available except for
71
+ # GeometryCollection.
72
+ # * Length calculations are available, but areas are not. Distances
73
+ # are available only between points.
74
+ # * Equality and simplicity evaluation are implemented for some but
75
+ # not all types.
76
+ # * Assertions for polygons and multipolygons are not implemented.
77
+ #
78
+ # Unimplemented operations will return nil if invoked.
79
+ #
80
+ # === Options
81
+ #
82
+ # You may use the following options when creating a spherical
83
+ # factory:
84
+ #
85
+ # [<tt>:has_z_coordinate</tt>]
86
+ # Support a Z coordinate. Default is false.
87
+ # [<tt>:has_m_coordinate</tt>]
88
+ # Support an M coordinate. Default is false.
89
+ # [<tt>:proj4</tt>]
90
+ # Provide the coordinate system in Proj4 format. You may pass
91
+ # either an RGeo::CoordSys::Proj4 object, or a string or hash
92
+ # containing the Proj4 parameters. This coordinate system must be
93
+ # a geographic (lat/long) coordinate system. The default is the
94
+ # "popular visualization CRS" (EPSG 4055), represented by
95
+ # "<tt>+proj=longlat +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +no_defs</tt>".
96
+ # Has no effect if Proj4 is not available.
97
+ # [<tt>:coord_sys</tt>]
98
+ # Provide a coordinate system in OGC format, either as an object
99
+ # (one of the CoordSys::CS classes) or as a string in WKT format.
100
+ # This coordinate system must be a GeographicCoordinateSystem.
101
+ # The default is the "popular visualization CRS" (EPSG 4055).
102
+ # [<tt>:srid</tt>]
103
+ # The SRID that should be returned by features from this factory.
104
+ # Default is 4055, indicating EPSG 4055, the "popular
105
+ # visualization crs". You may alternatively wish to set the srid
106
+ # to 4326, indicating the WGS84 crs, but note that that value
107
+ # implies an ellipsoidal datum, not a spherical datum.
108
+ # [<tt>:srs_database</tt>]
109
+ # Optional. If provided, the value should be an implementation of
110
+ # CoordSys::SRSDatabase::Interface. If both this and an SRID are
111
+ # provided, they are used to look up the proj4 and coord_sys
112
+ # objects from a spatial reference system database.
113
+
114
+ def spherical_factory(opts_={})
115
+ proj4_ = opts_[:proj4]
116
+ coord_sys_ = opts_[:coord_sys]
117
+ srid_ = opts_[:srid]
118
+ if (!proj4_ || !coord_sys_) && srid_ && (db_ = opts_[:srs_database])
119
+ entry_ = db_.get(srid_.to_i)
120
+ if entry_
121
+ proj4_ ||= entry_.proj4
122
+ coord_sys_ ||= entry_.coord_sys
123
+ end
124
+ end
125
+ srid_ ||= coord_sys_.authority_code if coord_sys_
126
+ Geographic::Factory.new('Spherical', :has_z_coordinate => opts_[:has_z_coordinate], :has_m_coordinate => opts_[:has_m_coordinate], :proj4 => proj4_ || _proj4_4055, :coord_sys => coord_sys_ || _coordsys_4055, :srid => (srid_ || 4055).to_i)
127
+ end
128
+
129
+
130
+ # Creates and returns a geographic factory that is designed for
131
+ # visualization applications that use Google or Bing maps, or any
132
+ # other visualization systems that use the same projection. It
133
+ # includes a projection factory that matches the projection used
134
+ # by those mapping systems.
135
+ #
136
+ # Like all geographic factories, this one creates features using
137
+ # latitude-longitude values. However, calculations such as
138
+ # intersections are done in the projected coordinate system, and
139
+ # size and distance calculations report results in the projected
140
+ # units.
141
+ #
142
+ # The behavior of the simple_mercator factory could also be obtained
143
+ # using a projected_factory with appropriate Proj4 specifications.
144
+ # However, the simple_mercator implementation is done without
145
+ # actually requiring the Proj4 library. The projections are simple
146
+ # enough to be implemented in pure ruby.
147
+ #
148
+ # === About the coordinate system
149
+ #
150
+ # Many popular visualization technologies, such as Google and Bing
151
+ # maps, actually use two coordinate systems. The first is the
152
+ # standard WSG84 lat-long system used by the GPS and represented
153
+ # by EPSG 4326. Most API calls and input-output in these mapping
154
+ # technologies utilize this coordinate system. The second is a
155
+ # Mercator projection based on a "sphericalization" of the WGS84
156
+ # lat-long system. This projection is the basis of the map's screen
157
+ # and tiling coordinates, and has been assigned EPSG 3785.
158
+ #
159
+ # This factory represents both coordinate systems. The main factory
160
+ # produces data in the lat-long system and reports SRID 4326, and
161
+ # the projected factory produces data in the projection and reports
162
+ # SRID 3785. Latitudes are restricted to the range
163
+ # (-85.05112877980659, 85.05112877980659), which conveniently
164
+ # results in a square projected domain.
165
+ #
166
+ # === Options
167
+ #
168
+ # You may use the following options when creating a simple_mercator
169
+ # factory:
170
+ #
171
+ # [<tt>:has_z_coordinate</tt>]
172
+ # Support a Z coordinate. Default is false.
173
+ # [<tt>:has_m_coordinate</tt>]
174
+ # Support an M coordinate. Default is false.
175
+ #
176
+ # You may also provide options understood by the underlying
177
+ # projected Cartesian factory. For example, if GEOS is used for the
178
+ # projected factory, you may also set the
179
+ # <tt>:lenient_multi_polygon_assertions</tt> and
180
+ # <tt>:buffer_resolution</tt> options. See RGeo::Geos::factory for
181
+ # more details.
182
+
183
+ def simple_mercator_factory(opts_={})
184
+ factory_ = Geographic::Factory.new('Projected', :proj4 => _proj4_4326, :coord_sys => _coordsys_4326, :srid => 4326, :has_z_coordinate => opts_[:has_z_coordinate], :has_m_coordinate => opts_[:has_m_coordinate])
185
+ projector_ = Geographic::SimpleMercatorProjector.new(factory_, :buffer_resolution => opts_[:buffer_resolution], :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :has_z_coordinate => opts_[:has_z_coordinate], :has_m_coordinate => opts_[:has_m_coordinate])
186
+ factory_._set_projector(projector_)
187
+ factory_
188
+ end
189
+
190
+
191
+ # Creates and returns a geographic factory that includes a
192
+ # projection specified by a Proj4 coordinate system. Like all
193
+ # geographic factories, this one creates features using latitude-
194
+ # longitude values. However, calculations such as intersections are
195
+ # done in the projected coordinate system, and size and distance
196
+ # calculations report results in the projected units. Thus, this
197
+ # factory actually includes two factories representing different
198
+ # coordinate systems: the main factory representing the geographic
199
+ # lat-long coordinate system, and an auxiliary "projection factory"
200
+ # representing the projected coordinate system.
201
+ #
202
+ # This implementation is intended for advanced GIS applications
203
+ # requiring greater control over the projection being used.
204
+ #
205
+ # === Options
206
+ #
207
+ # When creating a projected implementation, you must provide enough
208
+ # information to construct a Proj4 specification for the projection.
209
+ # Generally, this means you will provide either the projection's
210
+ # factory itself (via the <tt>:projection_factory</tt> option), in
211
+ # which case the factory must include a Proj4 coordinate system;
212
+ # or, alternatively, you should provide the Proj4 coordinate system
213
+ # and let this method construct a projection factory for you (which
214
+ # it will do using the preferred Cartesian factory generator).
215
+ # If you choose this second method, you may provide the proj4
216
+ # directly via the <tt>:projection_proj4</tt> option, or indirectly
217
+ # by providing both an <tt>:srid</tt> and a <tt>:srs_database</tt>
218
+ # to use to look up the coordinate system.
219
+ #
220
+ # Following are detailed descriptions of the various options you can
221
+ # pass to this method.
222
+ #
223
+ # [<tt>:projection_factory</tt>]
224
+ # Specify an existing Cartesian factory to use for the projection.
225
+ # This factory must have a non-nil Proj4. If this is provided, any
226
+ # <tt>:projection_proj4</tt>, <tt>:projection_coord_sys</tt>, and
227
+ # <tt>:projection_srid</tt> are ignored.
228
+ # [<tt>:projection_proj4</tt>]
229
+ # Specify a Proj4 projection to use to construct the projection
230
+ # factory. This may be specified as a CoordSys::Proj4 object, or
231
+ # as a Proj4 string or hash representation.
232
+ # [<tt>:projection_coord_sys</tt>]
233
+ # Specify a OGC coordinate system for the projection. This may be
234
+ # specified as an RGeo::CoordSys::CS::GeographicCoordinateSystem
235
+ # object, or as a String in OGC WKT format. Optional.
236
+ # [<tt>:projection_srid</tt>]
237
+ # The SRID value to use for the projection factory. Defaults to
238
+ # the given projection coordinate system's authority code, or to
239
+ # 0 if no projection coordinate system is known.
240
+ # [<tt>:proj4</tt>]
241
+ # A proj4 projection for the geographic (lat-lon) factory. You may
242
+ # pass either an RGeo::CoordSys::Proj4 object, or a string or hash
243
+ # containing the Proj4 parameters. This coordinate system must be
244
+ # a geographic (lat/long) coordinate system. It defaults to the
245
+ # geographic part of the projection factory's coordinate system.
246
+ # Generally, you should leave it at the default unless you want
247
+ # the geographic coordinate system to be based on a different
248
+ # horizontal datum than the projection.
249
+ # [<tt>:coord_sys</tt>]
250
+ # An OGC coordinate system for the geographic (lat-lon) factory,
251
+ # which may be an RGeo::CoordSys::CS::GeographicCoordinateSystem
252
+ # object or a string in OGC WKT format. It defaults to the
253
+ # geographic system embedded in the projection coordinate system.
254
+ # Generally, you should leave it at the default unless you want
255
+ # the geographic coordinate system to be based on a different
256
+ # horizontal datum than the projection.
257
+ # [<tt>:srid</tt>]
258
+ # The SRID value to use for the main geographic factory. Defaults
259
+ # to the given geographic coordinate system's authority code, or
260
+ # to 0 if no geographic coordinate system is known.
261
+ # [<tt>:srs_database</tt>]
262
+ # Optional. If provided, the value should be an implementation of
263
+ # CoordSys::SRSDatabase::Interface. If both this and an SRID are
264
+ # provided, they are used to look up the proj4 and coord_sys
265
+ # objects from a spatial reference system database.
266
+ # [<tt>:has_z_coordinate</tt>]
267
+ # Support a Z coordinate. Default is false.
268
+ # Note: this is ignored if a <tt>:projection_factory</tt> is
269
+ # provided; in that case, the geographic factory's z-coordinate
270
+ # availability will match the projection factory's setting.
271
+ # [<tt>:has_m_coordinate</tt>]
272
+ # Support an M coordinate. Default is false.
273
+ # Note: this is ignored if a <tt>:projection_factory</tt> is
274
+ # provided; in that case, the geographic factory's m-coordinate
275
+ # availability will match the projection factory's setting.
276
+ #
277
+ # If a <tt>:projection_factory</tt> is _not_ provided, you may also
278
+ # provide options for configuring the projected Cartesian factory.
279
+ # For example, if GEOS is used for the projected factory, you may
280
+ # also set the <tt>:lenient_multi_polygon_assertions</tt> and
281
+ # <tt>:buffer_resolution</tt> options. See RGeo::Geos::factory for
282
+ # more details.
283
+
284
+ def projected_factory(opts_={})
285
+ unless CoordSys::Proj4.supported?
286
+ raise Error::UnsupportedOperation, "Proj4 is not supported because the proj4 library was not found at install time."
287
+ end
288
+ db_ = opts_[:srs_database]
289
+ if (projection_factory_ = opts_[:projection_factory])
290
+ # Get the projection coordinate systems from the given factory
291
+ projection_proj4_ = projection_factory_.proj4
292
+ unless projection_proj4_
293
+ raise ::ArgumentError, 'The :projection_factory does not have a proj4.'
294
+ end
295
+ projection_coord_sys_ = projection_factory_.coord_sys
296
+ if projection_coord_sys_ && !projection_coord_sys_.kind_of?(CoordSys::CS::ProjectedCoordinateSystem)
297
+ raise ::ArgumentError, 'The :projection_factory\'s coord_sys is not a ProjectedCoordinateSystem.'
298
+ end
299
+ # Determine geographic coordinate system. First check parameters.
300
+ proj4_ = opts_[:proj4]
301
+ coord_sys_ = opts_[:coord_sys]
302
+ srid_ = opts_[:srid]
303
+ # Lookup srid from srs database if needed
304
+ if (!proj4_ || !coord_sys_) && srid_ && db_
305
+ entry_ = db_.get(srid_.to_i)
306
+ if entry_
307
+ proj4_ ||= entry_.proj4
308
+ coord_sys_ ||= entry_.coord_sys
309
+ end
310
+ end
311
+ # Fall back to getting the values from the projection.
312
+ proj4_ ||= projection_proj4_.get_geographic || _proj4_4326
313
+ coord_sys_ ||= projection_coord_sys_.geographic_coordinate_system if projection_coord_sys_
314
+ srid_ ||= coord_sys_.authority_code if coord_sys_
315
+ srid_ ||= 4326
316
+ # Now we should have all the coordinate system info.
317
+ factory_ = Geographic::Factory.new('Projected', :proj4 => proj4_, :coord_sys => coord_sys_, :srid => srid_.to_i, :has_z_coordinate => projection_factory_.property(:has_z_coordinate), :has_m_coordinate => projection_factory_.property(:has_m_coordinate))
318
+ projector_ = Geographic::Proj4Projector.create_from_existing_factory(factory_, projection_factory_)
319
+ else
320
+ # Determine projection coordinate system. First check the parameters.
321
+ projection_proj4_ = opts_[:projection_proj4]
322
+ projection_coord_sys_ = opts_[:projection_coord_sys]
323
+ projection_srid_ = opts_[:projection_srid]
324
+ # Check the case where we need to look up a srid from an srs database.
325
+ if (!projection_proj4_ || !projection_coord_sys_) && projection_srid_ && db_
326
+ entry_ = db_.get(projection_srid_.to_i)
327
+ if entry_
328
+ projection_proj4_ ||= entry_.proj4
329
+ projection_coord_sys_ ||= entry_.coord_sys
330
+ end
331
+ end
332
+ # A projection proj4 is absolutely required.
333
+ unless projection_proj4_
334
+ raise ::ArgumentError, 'Unable to determine the Proj4 for the projected coordinate system.'
335
+ end
336
+ # Check the projection coordinate systems, and parse if needed.
337
+ if projection_proj4_.kind_of?(::String) || projection_proj4_.kind_of?(::Hash)
338
+ actual_projection_proj4_ = CoordSys::Proj4.create(projection_proj4_)
339
+ unless actual_projection_proj4_
340
+ raise ::ArgumentError, "Bad proj4 syntax: #{projection_proj4_.inspect}"
341
+ end
342
+ projection_proj4_ = actual_projection_proj4_
343
+ end
344
+ if projection_coord_sys_ && !projection_coord_sys_.kind_of?(CoordSys::CS::ProjectedCoordinateSystem)
345
+ raise ::ArgumentError, 'The :projection_coord_sys is not a ProjectedCoordinateSystem.'
346
+ end
347
+ projection_srid_ ||= projection_coord_sys_.authority_code if projection_coord_sys_
348
+ # Determine geographic coordinate system. First check parameters.
349
+ proj4_ = opts_[:proj4]
350
+ coord_sys_ = opts_[:coord_sys]
351
+ srid_ = opts_[:srid]
352
+ # Lookup srid from srs database if needed
353
+ if (!proj4_ || !coord_sys_) && srid_ && db_
354
+ entry_ = db_.get(srid_.to_i)
355
+ if entry_
356
+ proj4_ ||= entry_.proj4
357
+ coord_sys_ ||= entry_.coord_sys
358
+ end
359
+ end
360
+ # Fall back to getting the values from the projection.
361
+ proj4_ ||= projection_proj4_.get_geographic || _proj4_4326
362
+ coord_sys_ ||= projection_coord_sys_.geographic_coordinate_system if projection_coord_sys_
363
+ srid_ ||= coord_sys_.authority_code if coord_sys_
364
+ srid_ ||= 4326
365
+ # Now we should have all the coordinate system info.
366
+ factory_ = Geographic::Factory.new('Projected', :proj4 => proj4_, :coord_sys => coord_sys_, :srid => srid_.to_i, :has_z_coordinate => opts_[:has_z_coordinate], :has_m_coordinate => opts_[:has_m_coordinate])
367
+ projector_ = Geographic::Proj4Projector.create_from_proj4(factory_, projection_proj4_, :srid => projection_srid_, :coord_sys => projection_coord_sys_, :buffer_resolution => opts_[:buffer_resolution], :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :has_z_coordinate => opts_[:has_z_coordinate], :has_m_coordinate => opts_[:has_m_coordinate])
368
+ end
369
+ factory_._set_projector(projector_)
370
+ factory_
371
+ end
372
+
373
+
374
+ def _proj4_4055 # :nodoc:
375
+ unless defined?(@proj4_4055)
376
+ @proj4_4055 = CoordSys::Proj4.create('+proj=longlat +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +no_defs')
377
+ end
378
+ @proj4_4055
379
+ end
380
+
381
+
382
+ def _coordsys_4055 # :nodoc:
383
+ unless defined?(@coordsys_4055)
384
+ @coordsys_4055 = CoordSys::CS.create_from_wkt('GEOGCS["Popular Visualisation CRS",DATUM["Popular_Visualisation_Datum",SPHEROID["Popular Visualisation Sphere",6378137,0,AUTHORITY["EPSG","7059"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6055"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4055"]]')
385
+ end
386
+ @coordsys_4055
387
+ end
388
+
389
+
390
+ def _proj4_4326 # :nodoc:
391
+ unless defined?(@proj4_4326)
392
+ @proj4_4326 = CoordSys::Proj4.create('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
393
+ end
394
+ @proj4_4326
395
+ end
396
+
397
+
398
+ def _coordsys_4326 # :nodoc:
399
+ unless defined?(@coordsys_4326)
400
+ @coordsys_4326 = CoordSys::CS.create_from_wkt('GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]')
401
+ end
402
+ @coordsys_4326
403
+ end
404
+
405
+
406
+ end
407
+
408
+ end
409
+
410
+ end