rgeo 0.1.19 → 0.1.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. data/History.rdoc +11 -0
  2. data/README.rdoc +23 -7
  3. data/Version +1 -1
  4. data/ext/geos_c_impl/factory.c +1 -1
  5. data/{lib/rgeo/geography/simple_mercator.rb → ext/proj4_c_impl/extconf.rb} +35 -30
  6. data/ext/proj4_c_impl/main.c +256 -0
  7. data/lib/rgeo.rb +54 -42
  8. data/lib/rgeo/active_record/arel_modifications.rb +2 -2
  9. data/lib/rgeo/active_record/base_modifications.rb +1 -1
  10. data/lib/rgeo/active_record/mysql_common.rb +12 -12
  11. data/lib/rgeo/all.rb +5 -4
  12. data/lib/rgeo/cartesian.rb +3 -2
  13. data/lib/rgeo/cartesian/bounding_box.rb +9 -9
  14. data/lib/rgeo/cartesian/factory.rb +30 -13
  15. data/lib/rgeo/cartesian/feature_classes.rb +33 -33
  16. data/lib/rgeo/cartesian/interface.rb +2 -2
  17. data/lib/rgeo/{geography/all.rb → coord_sys.rb} +22 -4
  18. data/lib/rgeo/coord_sys/proj4.rb +275 -0
  19. data/lib/rgeo/{errors.rb → error.rb} +5 -6
  20. data/lib/rgeo/{features.rb → feature.rb} +22 -20
  21. data/lib/rgeo/{features → feature}/curve.rb +6 -6
  22. data/lib/rgeo/{features → feature}/factory.rb +19 -3
  23. data/lib/rgeo/{features → feature}/factory_generator.rb +1 -1
  24. data/lib/rgeo/{features → feature}/geometry.rb +34 -34
  25. data/lib/rgeo/{features → feature}/geometry_collection.rb +4 -4
  26. data/lib/rgeo/{features → feature}/line.rb +1 -1
  27. data/lib/rgeo/{features → feature}/line_string.rb +4 -4
  28. data/lib/rgeo/{features → feature}/linear_ring.rb +1 -1
  29. data/lib/rgeo/{features → feature}/multi_curve.rb +3 -3
  30. data/lib/rgeo/{features → feature}/multi_line_string.rb +1 -1
  31. data/lib/rgeo/{features → feature}/multi_point.rb +1 -1
  32. data/lib/rgeo/{features → feature}/multi_polygon.rb +1 -1
  33. data/lib/rgeo/{features → feature}/multi_surface.rb +4 -4
  34. data/lib/rgeo/{features → feature}/point.rb +5 -5
  35. data/lib/rgeo/{features → feature}/polygon.rb +5 -5
  36. data/lib/rgeo/{features → feature}/surface.rb +4 -4
  37. data/lib/rgeo/feature/types.rb +301 -0
  38. data/lib/rgeo/geo_json.rb +1 -1
  39. data/lib/rgeo/geo_json/coder.rb +13 -13
  40. data/lib/rgeo/geo_json/interface.rb +2 -2
  41. data/lib/rgeo/geography.rb +33 -6
  42. data/lib/rgeo/geography/factory.rb +82 -39
  43. data/lib/rgeo/geography/interface.rb +135 -89
  44. data/lib/rgeo/geography/proj4_projector.rb +98 -0
  45. data/lib/rgeo/geography/projected_feature_classes.rb +213 -0
  46. data/lib/rgeo/geography/projected_feature_methods.rb +228 -0
  47. data/lib/rgeo/geography/projected_window.rb +7 -7
  48. data/lib/rgeo/geography/simple_mercator_projector.rb +133 -0
  49. data/lib/rgeo/geography/spherical_feature_classes.rb +212 -0
  50. data/lib/rgeo/geography/{simple_spherical/feature_methods.rb → spherical_feature_methods.rb} +39 -43
  51. data/lib/rgeo/geography/{simple_spherical/calculations.rb → spherical_math.rb} +7 -7
  52. data/lib/rgeo/geos.rb +1 -1
  53. data/lib/rgeo/geos/factory.rb +37 -19
  54. data/lib/rgeo/geos/impl_additions.rb +10 -11
  55. data/lib/rgeo/geos/interface.rb +1 -1
  56. data/lib/rgeo/geos/zm_factory.rb +15 -15
  57. data/lib/rgeo/geos/zm_impl.rb +10 -10
  58. data/lib/rgeo/{impl_helpers.rb → impl_helper.rb} +8 -8
  59. data/lib/rgeo/{impl_helpers → impl_helper}/basic_geometry_collection_methods.rb +13 -13
  60. data/lib/rgeo/{impl_helpers → impl_helper}/basic_geometry_methods.rb +2 -2
  61. data/lib/rgeo/{impl_helpers → impl_helper}/basic_line_string_methods.rb +13 -13
  62. data/lib/rgeo/{impl_helpers → impl_helper}/basic_point_methods.rb +5 -5
  63. data/lib/rgeo/{impl_helpers → impl_helper}/basic_polygon_methods.rb +6 -6
  64. data/lib/rgeo/{impl_helpers → impl_helper}/math.rb +1 -1
  65. data/lib/rgeo/shapefile.rb +1 -1
  66. data/lib/rgeo/shapefile/reader.rb +3 -3
  67. data/lib/rgeo/wkrep.rb +1 -1
  68. data/lib/rgeo/wkrep/wkb_generator.rb +17 -17
  69. data/lib/rgeo/wkrep/wkb_parser.rb +12 -12
  70. data/lib/rgeo/wkrep/wkt_generator.rb +8 -8
  71. data/lib/rgeo/wkrep/wkt_parser.rb +10 -10
  72. data/{tests → test}/active_record/readme.txt +0 -0
  73. data/{tests → test}/active_record/tc_mysqlspatial.rb +2 -2
  74. data/{tests → test}/common/geometry_collection_tests.rb +22 -22
  75. data/{tests → test}/common/line_string_tests.rb +20 -20
  76. data/{tests → test}/common/multi_line_string_tests.rb +19 -19
  77. data/{tests → test}/common/multi_point_tests.rb +17 -17
  78. data/{tests → test}/common/multi_polygon_tests.rb +16 -16
  79. data/{tests → test}/common/point_tests.rb +9 -9
  80. data/{tests → test}/common/polygon_tests.rb +9 -9
  81. data/test/coord_sys/tc_proj4.rb +111 -0
  82. data/{tests → test}/geos/tc_factory.rb +1 -1
  83. data/{tests → test}/geos/tc_geometry_collection.rb +1 -1
  84. data/{tests → test}/geos/tc_line_string.rb +0 -0
  85. data/{tests → test}/geos/tc_misc.rb +1 -1
  86. data/{tests → test}/geos/tc_multi_line_string.rb +1 -1
  87. data/{tests → test}/geos/tc_multi_point.rb +1 -1
  88. data/{tests → test}/geos/tc_multi_polygon.rb +1 -1
  89. data/{tests → test}/geos/tc_point.rb +1 -1
  90. data/{tests → test}/geos/tc_polygon.rb +0 -0
  91. data/{tests → test}/geos/tc_zmfactory.rb +2 -2
  92. data/test/projected_geography/tc_geometry_collection.rb +62 -0
  93. data/test/projected_geography/tc_line_string.rb +62 -0
  94. data/test/projected_geography/tc_multi_line_string.rb +62 -0
  95. data/test/projected_geography/tc_multi_point.rb +62 -0
  96. data/test/projected_geography/tc_multi_polygon.rb +63 -0
  97. data/test/projected_geography/tc_point.rb +93 -0
  98. data/test/projected_geography/tc_polygon.rb +62 -0
  99. data/{tests → test}/shapefile/shapelib_testcases/readme.txt +0 -0
  100. data/{tests → test}/shapefile/shapelib_testcases/test.dbf +0 -0
  101. data/{tests → test}/shapefile/shapelib_testcases/test.shp +0 -0
  102. data/{tests → test}/shapefile/shapelib_testcases/test.shx +0 -0
  103. data/{tests → test}/shapefile/shapelib_testcases/test0.shp +0 -0
  104. data/{tests → test}/shapefile/shapelib_testcases/test0.shx +0 -0
  105. data/{tests → test}/shapefile/shapelib_testcases/test1.shp +0 -0
  106. data/{tests → test}/shapefile/shapelib_testcases/test1.shx +0 -0
  107. data/{tests → test}/shapefile/shapelib_testcases/test10.shp +0 -0
  108. data/{tests → test}/shapefile/shapelib_testcases/test10.shx +0 -0
  109. data/{tests → test}/shapefile/shapelib_testcases/test11.shp +0 -0
  110. data/{tests → test}/shapefile/shapelib_testcases/test11.shx +0 -0
  111. data/{tests → test}/shapefile/shapelib_testcases/test12.shp +0 -0
  112. data/{tests → test}/shapefile/shapelib_testcases/test12.shx +0 -0
  113. data/{tests → test}/shapefile/shapelib_testcases/test13.shp +0 -0
  114. data/{tests → test}/shapefile/shapelib_testcases/test13.shx +0 -0
  115. data/{tests → test}/shapefile/shapelib_testcases/test2.shp +0 -0
  116. data/{tests → test}/shapefile/shapelib_testcases/test2.shx +0 -0
  117. data/{tests → test}/shapefile/shapelib_testcases/test3.shp +0 -0
  118. data/{tests → test}/shapefile/shapelib_testcases/test3.shx +0 -0
  119. data/{tests → test}/shapefile/shapelib_testcases/test4.shp +0 -0
  120. data/{tests → test}/shapefile/shapelib_testcases/test4.shx +0 -0
  121. data/{tests → test}/shapefile/shapelib_testcases/test5.shp +0 -0
  122. data/{tests → test}/shapefile/shapelib_testcases/test5.shx +0 -0
  123. data/{tests → test}/shapefile/shapelib_testcases/test6.shp +0 -0
  124. data/{tests → test}/shapefile/shapelib_testcases/test6.shx +0 -0
  125. data/{tests → test}/shapefile/shapelib_testcases/test7.shp +0 -0
  126. data/{tests → test}/shapefile/shapelib_testcases/test7.shx +0 -0
  127. data/{tests → test}/shapefile/shapelib_testcases/test8.shp +0 -0
  128. data/{tests → test}/shapefile/shapelib_testcases/test8.shx +0 -0
  129. data/{tests → test}/shapefile/shapelib_testcases/test9.shp +0 -0
  130. data/{tests → test}/shapefile/shapelib_testcases/test9.shx +0 -0
  131. data/{tests → test}/shapefile/tc_shapelib_tests.rb +17 -17
  132. data/{tests → test}/simple_cartesian/tc_calculations.rb +0 -0
  133. data/{tests → test}/simple_cartesian/tc_geometry_collection.rb +0 -0
  134. data/{tests → test}/simple_cartesian/tc_line_string.rb +0 -0
  135. data/{tests → test}/simple_cartesian/tc_multi_line_string.rb +0 -0
  136. data/{tests → test}/simple_cartesian/tc_multi_point.rb +0 -0
  137. data/{tests → test}/simple_cartesian/tc_multi_polygon.rb +0 -0
  138. data/{tests → test}/simple_cartesian/tc_point.rb +0 -0
  139. data/{tests → test}/simple_cartesian/tc_polygon.rb +0 -0
  140. data/{tests → test}/simple_mercator/tc_geometry_collection.rb +1 -1
  141. data/{tests → test}/simple_mercator/tc_line_string.rb +0 -0
  142. data/{tests → test}/simple_mercator/tc_multi_line_string.rb +1 -1
  143. data/{tests → test}/simple_mercator/tc_multi_point.rb +1 -1
  144. data/{tests → test}/simple_mercator/tc_multi_polygon.rb +1 -1
  145. data/{tests → test}/simple_mercator/tc_point.rb +2 -2
  146. data/{tests → test}/simple_mercator/tc_polygon.rb +0 -0
  147. data/{tests → test}/simple_mercator/tc_window.rb +1 -1
  148. data/test/spherical_geography/tc_calculations.rb +203 -0
  149. data/{tests/simple_spherical → test/spherical_geography}/tc_geometry_collection.rb +2 -2
  150. data/{tests/simple_spherical → test/spherical_geography}/tc_line_string.rb +2 -2
  151. data/{tests/simple_spherical → test/spherical_geography}/tc_multi_line_string.rb +2 -2
  152. data/{tests/simple_spherical → test/spherical_geography}/tc_multi_point.rb +2 -2
  153. data/{tests/simple_spherical → test/spherical_geography}/tc_multi_polygon.rb +3 -3
  154. data/{tests/simple_spherical → test/spherical_geography}/tc_point.rb +7 -7
  155. data/{tests/simple_spherical → test/spherical_geography}/tc_polygon.rb +2 -2
  156. data/{tests → test}/tc_cartesian_analysis.rb +0 -0
  157. data/{tests → test}/tc_geojson.rb +0 -0
  158. data/{tests → test}/tc_oneoff.rb +2 -1
  159. data/{tests → test}/wkrep/tc_wkb_generator.rb +0 -0
  160. data/{tests → test}/wkrep/tc_wkb_parser.rb +32 -32
  161. data/{tests → test}/wkrep/tc_wkt_generator.rb +0 -0
  162. data/{tests → test}/wkrep/tc_wkt_parser.rb +46 -46
  163. metadata +183 -164
  164. data/lib/rgeo/features/types.rb +0 -272
  165. data/lib/rgeo/geography/simple_mercator/feature_classes.rb +0 -279
  166. data/lib/rgeo/geography/simple_mercator/feature_methods.rb +0 -278
  167. data/lib/rgeo/geography/simple_mercator/projector.rb +0 -112
  168. data/lib/rgeo/geography/simple_spherical.rb +0 -68
  169. data/lib/rgeo/geography/simple_spherical/feature_classes.rb +0 -216
  170. data/tests/simple_spherical/tc_calculations.rb +0 -203
@@ -43,7 +43,7 @@ module RGeo
43
43
 
44
44
  # High-level convenience routine for encoding an object as GeoJSON.
45
45
  # Pass the object, which may one of the geometry objects specified
46
- # in RGeo::Features, or an appropriate GeoJSON wrapper entity such
46
+ # in RGeo::Feature, or an appropriate GeoJSON wrapper entity such
47
47
  # as RGeo::GeoJSON::Feature or RGeo::GeoJSON::FeatureCollection.
48
48
  #
49
49
  # The only option supported is <tt>:entity_factory</tt>, which lets
@@ -91,7 +91,7 @@ module RGeo
91
91
 
92
92
  # Creates and returns a coder object of type RGeo::GeoJSON::Coder
93
93
  # that encapsulates encoding and decoding settings (principally the
94
- # RGeo::Features::Factory and the RGeo::GeoJSON::EntityFactory to be
94
+ # RGeo::Feature::Factory and the RGeo::GeoJSON::EntityFactory to be
95
95
  # used).
96
96
  #
97
97
  # The geo factory is a required argument. Other options include:
@@ -41,19 +41,46 @@ require 'rgeo'
41
41
  module RGeo
42
42
 
43
43
 
44
- # The Geography implementation provides geographic features using
45
- # latitude/longitude coordinates measured in degrees.
44
+ # The Geography implementation actually comprises a suite of
45
+ # implementations with one common feature: they represent geographic
46
+ # latitude/longitude coordinates measured in degrees. The "x"
47
+ # coordinate corresponds to longitude, and the "y" coordinate to
48
+ # latitude. Thus, coordinates are often expressed in reverse
49
+ # (i.e. long-lat) order. e.g.
50
+ #
51
+ # location = geography_factory.point(long, lat)
52
+ #
53
+ # Some geography implementations include a secondary factory that
54
+ # represents a projection. For these implementations, you can quickly
55
+ # transform data between lat/long coordinates and the projected
56
+ # coordinate system, and most calculations are done in the projected
57
+ # coordinate system. For implementations that do not include this
58
+ # secondary projection factory, calculations are done on the sphereoid.
59
+ # See the various class methods of Geography for more information on
60
+ # the behaviors of the factories they generate.
46
61
 
47
62
  module Geography
48
-
49
- autoload(:SimpleSpherical, 'rgeo/geography/simple_spherical')
50
- autoload(:SimpleMercator, 'rgeo/geography/simple_mercator')
51
-
52
63
  end
53
64
 
54
65
 
55
66
  end
56
67
 
57
68
 
69
+ # Dependency files
70
+ require 'rgeo/feature'
71
+ require 'rgeo/coord_sys'
72
+ require 'rgeo/wkrep'
73
+ require 'rgeo/impl_helper'
74
+ require 'rgeo/cartesian'
75
+
58
76
  # Implementation files.
77
+ require 'rgeo/geography/factory'
78
+ require 'rgeo/geography/projected_window'
59
79
  require 'rgeo/geography/interface'
80
+ require 'rgeo/geography/spherical_math'
81
+ require 'rgeo/geography/spherical_feature_methods'
82
+ require 'rgeo/geography/spherical_feature_classes'
83
+ require 'rgeo/geography/proj4_projector'
84
+ require 'rgeo/geography/simple_mercator_projector'
85
+ require 'rgeo/geography/projected_feature_methods'
86
+ require 'rgeo/geography/projected_feature_classes'
@@ -45,31 +45,58 @@ module RGeo
45
45
 
46
46
  class Factory
47
47
 
48
- include Features::Factory::Instance
49
-
50
-
51
- def initialize(namespace_, opts_={}) # :nodoc:
52
- @namespace = namespace_
53
- @opts = opts_.dup
54
- if @namespace.const_defined?(:Projector)
55
- @projector = @namespace.const_get(:Projector).new(self, opts_)
56
- else
57
- @projector = nil
58
- end
48
+ include Feature::Factory::Instance
49
+
50
+
51
+ def initialize(impl_prefix_, opts_={}) # :nodoc:
52
+ @impl_prefix = impl_prefix_
53
+ @point_class = Geography.const_get("#{impl_prefix_}PointImpl")
54
+ @line_string_class = Geography.const_get("#{impl_prefix_}LineStringImpl")
55
+ @linear_ring_class = Geography.const_get("#{impl_prefix_}LinearRingImpl")
56
+ @line_class = Geography.const_get("#{impl_prefix_}LineImpl")
57
+ @polygon_class = Geography.const_get("#{impl_prefix_}PolygonImpl")
58
+ @geometry_collection_class = Geography.const_get("#{impl_prefix_}GeometryCollectionImpl")
59
+ @multi_point_class = Geography.const_get("#{impl_prefix_}MultiPointImpl")
60
+ @multi_line_string_class = Geography.const_get("#{impl_prefix_}MultiLineStringImpl")
61
+ @multi_polygon_class = Geography.const_get("#{impl_prefix_}MultiPolygonImpl")
59
62
  @support_z = opts_[:support_z_coordinate] ? true : false
60
63
  @support_m = opts_[:support_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
+ end
74
+
75
+
76
+ def _set_projector(projector_) # :nodoc:
77
+ @projector = projector_
61
78
  end
62
79
 
63
80
 
64
81
  # Equivalence test.
65
82
 
66
83
  def eql?(rhs_)
67
- rhs_.is_a?(self.class) && @namespace == rhs_.instance_variable_get(:@namespace) &&
68
- @opts == rhs_.instance_variable_get(:@opts)
84
+ rhs_.is_a?(Geography::Factory) &&
85
+ @impl_prefix == rhs_.instance_variable_get(:@impl_prefix) &&
86
+ @support_z == rhs_.instance_variable_get(:@support_z) &&
87
+ @support_m == rhs_.instance_variable_get(:@support_m) &&
88
+ @proj4 == rhs_.instance_variable_get(:@proj4)
69
89
  end
70
90
  alias_method :==, :eql?
71
91
 
72
92
 
93
+ # Returns the srid reported by this factory.
94
+
95
+ def srid
96
+ @srid
97
+ end
98
+
99
+
73
100
  # Returns true if this factory supports a projection.
74
101
 
75
102
  def has_projection?
@@ -88,13 +115,13 @@ module RGeo
88
115
  # Projects the given geometry into the projected coordinate space,
89
116
  # and returns the projected geometry.
90
117
  # Returns nil if this factory does not support a projection.
91
- # Raises Errors::InvalidGeometry if the given geometry is not of
118
+ # Raises Error::InvalidGeometry if the given geometry is not of
92
119
  # this factory.
93
120
 
94
121
  def project(geometry_)
95
122
  return nil unless @projector
96
123
  unless geometry_.factory == self
97
- raise Errors::InvalidGeometry, 'Wrong geometry type'
124
+ raise Error::InvalidGeometry, 'Wrong geometry type'
98
125
  end
99
126
  @projector.project(geometry_)
100
127
  end
@@ -102,12 +129,12 @@ module RGeo
102
129
 
103
130
  # Reverse-projects the given geometry from the projected coordinate
104
131
  # space into lat-long space.
105
- # Raises Errors::InvalidGeometry if the given geometry is not of
132
+ # Raises Error::InvalidGeometry if the given geometry is not of
106
133
  # the projection defined by this factory.
107
134
 
108
135
  def unproject(geometry_)
109
136
  unless @projector && @projector.projection_factory == geometry_.factory
110
- raise Errors::InvalidGeometry, 'You can unproject only features that are in the projected coordinate space.'
137
+ raise Error::InvalidGeometry, 'You can unproject only features that are in the projected coordinate space.'
111
138
  end
112
139
  @projector.unproject(geometry_)
113
140
  end
@@ -128,11 +155,18 @@ module RGeo
128
155
  # Returns nil if this factory does not support a projection.
129
156
 
130
157
  def projection_limits_window
131
- @projector ? (@projection_limits_window ||= @projector.limits_window) : nil
158
+ if @projector
159
+ unless defined?(@projection_limits_window)
160
+ @projection_limits_window = @projector.limits_window
161
+ end
162
+ @projection_limits_window
163
+ else
164
+ nil
165
+ end
132
166
  end
133
167
 
134
168
 
135
- # See ::RGeo::Features::Factory#has_capability?
169
+ # See ::RGeo::Feature::Factory#has_capability?
136
170
 
137
171
  def has_capability?(name_)
138
172
  case name_
@@ -140,86 +174,95 @@ module RGeo
140
174
  @support_z
141
175
  when :m_coordinate
142
176
  @support_m
177
+ when :proj4
178
+ @proj4 ? true : false
143
179
  else
144
180
  nil
145
181
  end
146
182
  end
147
183
 
148
184
 
149
- # See ::RGeo::Features::Factory#parse_wkt
185
+ # See ::RGeo::Feature::Factory#parse_wkt
150
186
 
151
187
  def parse_wkt(str_)
152
188
  WKRep::WKTParser.new(:default_factory => self).parse(str_)
153
189
  end
154
190
 
155
191
 
156
- # See ::RGeo::Features::Factory#parse_wkb
192
+ # See ::RGeo::Feature::Factory#parse_wkb
157
193
 
158
194
  def parse_wkb(str_)
159
195
  WKRep::WKBParser.new(:default_factory => self).parse(str_)
160
196
  end
161
197
 
162
198
 
163
- # See ::RGeo::Features::Factory#point
199
+ # See ::RGeo::Feature::Factory#point
164
200
 
165
201
  def point(x_, y_, *extra_)
166
- @namespace.const_get(:PointImpl).new(self, x_, y_, *extra_) rescue nil
202
+ @point_class.new(self, x_, y_, *extra_) rescue nil
167
203
  end
168
204
 
169
205
 
170
- # See ::RGeo::Features::Factory#line_string
206
+ # See ::RGeo::Feature::Factory#line_string
171
207
 
172
208
  def line_string(points_)
173
- @namespace.const_get(:LineStringImpl).new(self, points_) rescue nil
209
+ @line_string_class.new(self, points_) rescue nil
174
210
  end
175
211
 
176
212
 
177
- # See ::RGeo::Features::Factory#line
213
+ # See ::RGeo::Feature::Factory#line
178
214
 
179
215
  def line(start_, end_)
180
- @namespace.const_get(:LineImpl).new(self, start_, end_) rescue nil
216
+ @line_class.new(self, start_, end_) rescue nil
181
217
  end
182
218
 
183
219
 
184
- # See ::RGeo::Features::Factory#linear_ring
220
+ # See ::RGeo::Feature::Factory#linear_ring
185
221
 
186
222
  def linear_ring(points_)
187
- @namespace.const_get(:LinearRingImpl).new(self, points_) rescue nil
223
+ @linear_ring_class.new(self, points_) rescue nil
188
224
  end
189
225
 
190
226
 
191
- # See ::RGeo::Features::Factory#polygon
227
+ # See ::RGeo::Feature::Factory#polygon
192
228
 
193
229
  def polygon(outer_ring_, inner_rings_=nil)
194
- @namespace.const_get(:PolygonImpl).new(self, outer_ring_, inner_rings_) rescue nil
230
+ @polygon_class.new(self, outer_ring_, inner_rings_) rescue nil
195
231
  end
196
232
 
197
233
 
198
- # See ::RGeo::Features::Factory#collection
234
+ # See ::RGeo::Feature::Factory#collection
199
235
 
200
236
  def collection(elems_)
201
- @namespace.const_get(:GeometryCollectionImpl).new(self, elems_) rescue nil
237
+ @geometry_collection_class.new(self, elems_) rescue nil
202
238
  end
203
239
 
204
240
 
205
- # See ::RGeo::Features::Factory#multi_point
241
+ # See ::RGeo::Feature::Factory#multi_point
206
242
 
207
243
  def multi_point(elems_)
208
- @namespace.const_get(:MultiPointImpl).new(self, elems_) rescue nil
244
+ @multi_point_class.new(self, elems_) rescue nil
209
245
  end
210
246
 
211
247
 
212
- # See ::RGeo::Features::Factory#multi_line_string
248
+ # See ::RGeo::Feature::Factory#multi_line_string
213
249
 
214
250
  def multi_line_string(elems_)
215
- @namespace.const_get(:MultiLineStringImpl).new(self, elems_) rescue nil
251
+ @multi_line_string_class.new(self, elems_) rescue nil
216
252
  end
217
253
 
218
254
 
219
- # See ::RGeo::Features::Factory#multi_polygon
255
+ # See ::RGeo::Feature::Factory#multi_polygon
220
256
 
221
257
  def multi_polygon(elems_)
222
- @namespace.const_get(:MultiPolygonImpl).new(self, elems_) rescue nil
258
+ @multi_polygon_class.new(self, elems_) rescue nil
259
+ end
260
+
261
+
262
+ # See ::RGeo::Feature::Factory#proj4
263
+
264
+ def proj4
265
+ @proj4
223
266
  end
224
267
 
225
268
 
@@ -41,22 +41,30 @@ module RGeo
41
41
  class << self
42
42
 
43
43
 
44
- # Geographic features provided by this factory perform calculations
45
- # assuming a spherical earth. In other words, geodesics are treated
46
- # as great circle arcs, and size and geometric calculations are
47
- # treated accordingly. Distance calculations report results in
48
- # meters. This makes this implementation ideal for everyday
49
- # calculations on the globe where accuracy within about 0.5 percent
50
- # is sufficient.
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.
51
59
  #
52
60
  # === Limitations
53
61
  #
54
- # This implementation does not implement many of the more advanced
62
+ # This implementation does not implement some of the more advanced
55
63
  # geometric operations. In particular:
56
64
  #
57
- # * Relational operators such as Features::Geometry#intersects? are
65
+ # * Relational operators such as Feature::Geometry#intersects? are
58
66
  # not implemented for most types.
59
- # * Relational constructors such as Features::Geometry#union are
67
+ # * Relational constructors such as Feature::Geometry#union are
60
68
  # not implemented for most types.
61
69
  # * Buffer, convex hull, and envelope calculations are not
62
70
  # implemented for most types. Boundaries are available except for
@@ -69,38 +77,81 @@ module RGeo
69
77
  #
70
78
  # Unimplemented operations will return nil if invoked.
71
79
  #
72
- # === SRID for simple_spherical
80
+ # === Options
73
81
  #
74
- # Simple_spherical features report SRID=4326, indicating EPSG 4326
75
- # (i.e. the WGS84 spheroid and the lat/lon system commonly used by
76
- # most GIS systems).
77
- # This is technically not correct, for two reasons:
82
+ # You may use the following options when creating a spherical
83
+ # factory:
78
84
  #
79
- # * We are running calculations on a spherical approximation of the
80
- # WGS84 spheroid rather than the ellipsoidal shape itself.
81
- # * While most functions use the EPSG 4326 unit of degrees longitude
82
- # and latitude, a few (specifically, distance and area calculations)
83
- # return their results in meters.
85
+ # <tt>:support_z_coordinate</tt>::
86
+ # Support <tt>z_coordinate</tt>. Default is false.
87
+ # <tt>:support_m_coordinate</tt>::
88
+ # Support <tt>m_coordinate</tt>. 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>:srid</tt>::
98
+ # The SRID that should be returned by features from this factory.
99
+ # Default is 4055, indicating EPSG 4055, the "popular
100
+ # visualization crs". You may alternatively wish to set the srid
101
+ # to 4326, indicating the WGS84 crs, but note that that value
102
+ # implies an ellipsoidal datum, not a spherical datum.
103
+
104
+ def spherical(opts_={})
105
+ Geography::Factory.new('Spherical', :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate], :proj4 => opts_[:proj4] || '+proj=longlat +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +no_defs', :srid => opts_[:srid] || 4055)
106
+ end
107
+
108
+
109
+ # Creates and returns a geographic factory that is designed for
110
+ # visualization applications that use Google or Bing maps, or any
111
+ # other visualization systems that use the same projection. It
112
+ # includes a projection factory that matches the projection used
113
+ # by those mapping systems.
114
+ #
115
+ # Like all geographic factories, this one creates features using
116
+ # latitude-longitude values. However, calculations such as
117
+ # intersections are done in the projected coordinate system, and
118
+ # size and distance calculations report results in the projected
119
+ # units.
120
+ #
121
+ # The behavior of the simple_mercator factory could also be obtained
122
+ # using a projected with appropriate Proj4 specifications. However,
123
+ # the simple_mercator implementation is done without actually
124
+ # requiring the Proj4 library. The projections are simple enough to
125
+ # be implemented in pure ruby.
84
126
  #
85
- # We, however, hereby punt on this issue for this particular factory,
86
- # on the theory that, for "most applications" that we expect will
87
- # want to use this library, these behaviors are sufficient, and the
88
- # SRID imprecision isn't crucial.
89
- # Note, however, that this means features created with this factory
90
- # may generate slightly different results from geodesic calculations
91
- # than those generated by, e.g., PostGIS (unless you direct PostGIS
92
- # to use spherical geodesics).
127
+ # === About the coordinate system
128
+ #
129
+ # Many popular visualization technologies, such as Google and Bing
130
+ # maps, actually use two coordinate systems. The first is the
131
+ # standard WSG84 lat-long system used by the GPS and represented
132
+ # by EPSG 4326. Most API calls and input-output in these mapping
133
+ # technologies utilize this coordinate system. The second is a
134
+ # Mercator projection based on a "sphericalization" of the WGS84
135
+ # lat-long system. This projection is the basis of the map's screen
136
+ # and tiling coordinates, and has been assigned EPSG 3857.
137
+ #
138
+ # This factory represents both coordinate systems. The main factory
139
+ # produces data in the lat-long system and reports SRID 4326, and
140
+ # the projected factory produces data in the projection and reports
141
+ # SRID 3857. Latitudes are restricted to the range
142
+ # (-85.05112877980659, 85.05112877980659), which conveniently
143
+ # results in a square projected domain.
93
144
  #
94
145
  # === Options
95
146
  #
96
- # You may use the following options when creating a simple_spherical
147
+ # You may use the following options when creating a simple_mercator
97
148
  # factory:
98
149
  #
99
150
  # <tt>:lenient_multi_polygon_assertions</tt>::
100
151
  # If set to true, assertion checking on MultiPolygon is disabled.
101
152
  # This may speed up creation of MultiPolygon objects, at the
102
153
  # expense of not doing the proper checking for OGC MultiPolygon
103
- # compliance. See RGeo::Features::MultiPolygon for details on
154
+ # compliance. See RGeo::Feature::MultiPolygon for details on
104
155
  # the MultiPolygon assertions. Default is false.
105
156
  # <tt>:buffer_resolution</tt>::
106
157
  # The resolution of buffers around geometries created by this
@@ -121,68 +172,57 @@ module RGeo
121
172
  # <tt>z_coordinate</tt> and <tt>m_coordinate</tt>. They may at
122
173
  # most support one or the other.
123
174
 
124
- def simple_spherical(opts_={})
125
- namespace_ = Geography::SimpleSpherical
126
- Geography::Factory.new(namespace_, :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate])
175
+ def simple_mercator(opts_={})
176
+ factory_ = Geography::Factory.new('Projected', :proj4 => '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs', :srid => 4326, :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate])
177
+ projector_ = Geography::SimpleMercatorProjector.new(factory_, :buffer_resolution => opts_[:buffer_resolution], :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate])
178
+ factory_._set_projector(projector_)
179
+ factory_
127
180
  end
128
181
 
129
182
 
130
- # Geographic features provided by this factory perform calculations
131
- # on the simple mercator projection currently used by Google and
132
- # Bing maps. This makes this implementation ideal for representing
133
- # and performing calculations on features to be visualized using
134
- # those technologies. Note, however, that significant discrepancies
135
- # may occur for large features between the "mapping visualization"
136
- # sizes and shapes, and the actual sizes and shapes on the globe,
137
- # because the mercator projection, like all projections of a
138
- # non-flat earth onto a flat coordinate system, does introduce
139
- # distortions (especially near the poles.)
140
- #
141
- # Distance and area computations return results in meters, whereas
142
- # all coordinates are represented in degrees latitude and longitude.
143
- #
144
- # === About the coordinate system
183
+ # Creates and returns a geographic factory that includes a
184
+ # projection specified by a Proj4 coordinate system. Like all
185
+ # geographic factories, this one creates features using latitude-
186
+ # longitude values. However, calculations such as intersections are
187
+ # done in the projected coordinate system, and size and distance
188
+ # calculations report results in the projected units.
145
189
  #
146
- # This is not a true projected spatial reference: point coordinates
147
- # are still represented in degrees latitude and longitude. However,
148
- # computations are done in the projected spatial reference. (That
149
- # spatial reference is EPSG 3857, for the interested.) This means,
150
- # for example, that a line segment whose endpoints fall on a line of
151
- # latitude away from the equator will follow the line of latitude
152
- # rather than the actual geodesic (which will curve away from the
153
- # equator in the projected coordinate system). It also means that
154
- # latitudes very near the poles are excluded. Specifically,
155
- # latitudes are restricted to the range (-85.05112877980659,
156
- # 85.05112877980659), which conveniently results in a square
157
- # projected domain.
158
- #
159
- # In general, this implementation is designed specifically for
160
- # mapping applications using Google and Bing maps, and any others
161
- # that use the same projection.
162
- #
163
- # Simple_mercator features report SRID=4326, indicating EPSG 4326
164
- # (i.e. the WGS84 spheroid and the lat/lon system commonly used by
165
- # most GIS systems).
166
- # This is actualy grossly inaccurate for a number of reasons, chief
167
- # among them being that calculations are being done on a projection,
168
- # whereas EPSG 4326 calculations are supposed to be done on the
169
- # spheroid. However, we continue to report SRID=4326 because the x
170
- # and y coordinates represent latitude and longitude rather than
171
- # projected coordinates. There is no EPSG spatial reference that
172
- # describes the <i>actual</i> behavior of the common map
173
- # visualization APIs, so we've decided to fudge on this in the
174
- # interest of being true to our expected application use cases.
190
+ # This implementation is intended for advanced GIS applications
191
+ # requiring intimate control over the projection being used.
175
192
  #
176
193
  # === Options
177
194
  #
178
- # You may use the following options when creating a simple_mercator
179
- # factory:
195
+ # When creating a projected implementation, you must provide either
196
+ # the <tt>:projection_factory</tt> option, indicating an existing
197
+ # Cartesian factory to use for the projection, or the
198
+ # <tt>:projection_proj4</tt> option, indicating a Proj4 projection
199
+ # to use to construct an appropriate projection factory.
200
+ #
201
+ # If you provide <tt>:projection_factory</tt>, the following options
202
+ # are supported.
203
+ #
204
+ # <tt>:projection_factory</tt>::
205
+ # Specify an existing Cartesian factory to use for the projection.
206
+ # This factory must support the <tt>:proj4</tt> capability.
207
+ #
208
+ # Note that in this case, the geography factory's z-coordinate and
209
+ # m-coordinate availability will be set to match the projection's
210
+ # z-coordinate and m-coordinate availability.
180
211
  #
212
+ # If you provide <tt>:projection_proj4</tt>, the following options
213
+ # are supported.
214
+ #
215
+ # <tt>:projection_proj4</tt>::
216
+ # Specify a Proj4 projection to use. This may be specified as a
217
+ # CoordSys::Proj4 object, or as a Proj4 string or hash
218
+ # representation.
219
+ # <tt>:projection_srid</tt>::
220
+ # An SRID value to use for the projection factory. Default is 0.
181
221
  # <tt>:lenient_multi_polygon_assertions</tt>::
182
222
  # If set to true, assertion checking on MultiPolygon is disabled.
183
223
  # This may speed up creation of MultiPolygon objects, at the
184
224
  # expense of not doing the proper checking for OGC MultiPolygon
185
- # compliance. See RGeo::Features::MultiPolygon for details on
225
+ # compliance. See RGeo::Feature::MultiPolygon for details on
186
226
  # the MultiPolygon assertions. Default is false.
187
227
  # <tt>:buffer_resolution</tt>::
188
228
  # The resolution of buffers around geometries created by this
@@ -194,18 +234,24 @@ module RGeo
194
234
  # for different kinds of buffers is defined by GEOS.
195
235
  # <tt>:support_z_coordinate</tt>::
196
236
  # Support <tt>z_coordinate</tt>. Default is false.
197
- # Note that simple_mercator factories cannot support both
198
- # <tt>z_coordinate</tt> and <tt>m_coordinate</tt>. They may at
199
- # most support one or the other.
200
237
  # <tt>:support_m_coordinate</tt>::
201
238
  # Support <tt>m_coordinate</tt>. Default is false.
202
- # Note that simple_mercator factories cannot support both
203
- # <tt>z_coordinate</tt> and <tt>m_coordinate</tt>. They may at
204
- # most support one or the other.
205
239
 
206
- def simple_mercator(opts_={})
207
- namespace_ = Geography::SimpleMercator
208
- Geography::Factory.new(namespace_, :buffer_resolution => opts_[:buffer_resolution], :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate])
240
+ def projected(opts_={})
241
+ unless CoordSys::Proj4.supported?
242
+ raise Error::UnsupportedCapability, "Proj4 is not supported because the proj4 library was not found at install time."
243
+ end
244
+ if (projection_factory_ = opts_[:projection_factory])
245
+ factory_ = Geography::Factory.new('Projected', :proj4 => opts_[:proj4] || '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs', :srid => opts_[:srid] || 4326, :support_z_coordinate => projection_factory_.has_capability?(:z_coordinate), :support_m_coordinate => projection_factory_.has_capability?(:m_coordinate))
246
+ projector_ = Geography::Proj4Projector.create_from_existing_factory(factory_, projection_factory_)
247
+ elsif opts_[:projection_proj4]
248
+ factory_ = Geography::Factory.new('Projected', :proj4 => opts_[:proj4] || '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs', :srid => opts_[:srid] || 4326, :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate])
249
+ projector_ = Geography::Proj4Projector.create_from_proj4(factory_, opts_[:projection_proj4], :srid => opts_[:projection_srid], :buffer_resolution => opts_[:buffer_resolution], :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :support_z_coordinate => opts_[:support_z_coordinate], :support_m_coordinate => opts_[:support_m_coordinate])
250
+ else
251
+ raise ::ArgumentError, 'You must provide either :projection_proj4 or :projection_factory.'
252
+ end
253
+ factory_._set_projector(projector_)
254
+ factory_
209
255
  end
210
256
 
211
257