schleyfox-rgeo 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/History.rdoc +199 -0
  2. data/README.rdoc +172 -0
  3. data/Spatial_Programming_With_RGeo.rdoc +440 -0
  4. data/Version +1 -0
  5. data/ext/geos_c_impl/extconf.rb +84 -0
  6. data/ext/geos_c_impl/factory.c +468 -0
  7. data/ext/geos_c_impl/factory.h +224 -0
  8. data/ext/geos_c_impl/geometry.c +705 -0
  9. data/ext/geos_c_impl/geometry.h +55 -0
  10. data/ext/geos_c_impl/geometry_collection.c +482 -0
  11. data/ext/geos_c_impl/geometry_collection.h +69 -0
  12. data/ext/geos_c_impl/line_string.c +509 -0
  13. data/ext/geos_c_impl/line_string.h +64 -0
  14. data/ext/geos_c_impl/main.c +70 -0
  15. data/ext/geos_c_impl/point.c +193 -0
  16. data/ext/geos_c_impl/point.h +62 -0
  17. data/ext/geos_c_impl/polygon.c +265 -0
  18. data/ext/geos_c_impl/polygon.h +66 -0
  19. data/ext/geos_c_impl/preface.h +50 -0
  20. data/ext/proj4_c_impl/extconf.rb +88 -0
  21. data/ext/proj4_c_impl/main.c +271 -0
  22. data/lib/rgeo.rb +124 -0
  23. data/lib/rgeo/cartesian.rb +60 -0
  24. data/lib/rgeo/cartesian/analysis.rb +118 -0
  25. data/lib/rgeo/cartesian/bounding_box.rb +337 -0
  26. data/lib/rgeo/cartesian/calculations.rb +161 -0
  27. data/lib/rgeo/cartesian/factory.rb +209 -0
  28. data/lib/rgeo/cartesian/feature_classes.rb +173 -0
  29. data/lib/rgeo/cartesian/feature_methods.rb +106 -0
  30. data/lib/rgeo/cartesian/interface.rb +150 -0
  31. data/lib/rgeo/coord_sys.rb +79 -0
  32. data/lib/rgeo/coord_sys/cs/entities.rb +1524 -0
  33. data/lib/rgeo/coord_sys/cs/factories.rb +208 -0
  34. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +308 -0
  35. data/lib/rgeo/coord_sys/proj4.rb +312 -0
  36. data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +194 -0
  37. data/lib/rgeo/coord_sys/srs_database/interface.rb +165 -0
  38. data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +188 -0
  39. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +108 -0
  40. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +108 -0
  41. data/lib/rgeo/error.rb +63 -0
  42. data/lib/rgeo/feature.rb +88 -0
  43. data/lib/rgeo/feature/curve.rb +156 -0
  44. data/lib/rgeo/feature/factory.rb +332 -0
  45. data/lib/rgeo/feature/factory_generator.rb +138 -0
  46. data/lib/rgeo/feature/geometry.rb +614 -0
  47. data/lib/rgeo/feature/geometry_collection.rb +129 -0
  48. data/lib/rgeo/feature/line.rb +66 -0
  49. data/lib/rgeo/feature/line_string.rb +102 -0
  50. data/lib/rgeo/feature/linear_ring.rb +66 -0
  51. data/lib/rgeo/feature/multi_curve.rb +113 -0
  52. data/lib/rgeo/feature/multi_line_string.rb +66 -0
  53. data/lib/rgeo/feature/multi_point.rb +73 -0
  54. data/lib/rgeo/feature/multi_polygon.rb +97 -0
  55. data/lib/rgeo/feature/multi_surface.rb +116 -0
  56. data/lib/rgeo/feature/point.rb +120 -0
  57. data/lib/rgeo/feature/polygon.rb +141 -0
  58. data/lib/rgeo/feature/surface.rb +122 -0
  59. data/lib/rgeo/feature/types.rb +305 -0
  60. data/lib/rgeo/geographic.rb +75 -0
  61. data/lib/rgeo/geographic/factory.rb +287 -0
  62. data/lib/rgeo/geographic/interface.rb +410 -0
  63. data/lib/rgeo/geographic/proj4_projector.rb +98 -0
  64. data/lib/rgeo/geographic/projected_feature_classes.rb +213 -0
  65. data/lib/rgeo/geographic/projected_feature_methods.rb +228 -0
  66. data/lib/rgeo/geographic/projected_window.rb +467 -0
  67. data/lib/rgeo/geographic/simple_mercator_projector.rb +157 -0
  68. data/lib/rgeo/geographic/spherical_feature_classes.rb +212 -0
  69. data/lib/rgeo/geographic/spherical_feature_methods.rb +97 -0
  70. data/lib/rgeo/geographic/spherical_math.rb +206 -0
  71. data/lib/rgeo/geos.rb +72 -0
  72. data/lib/rgeo/geos/factory.rb +301 -0
  73. data/lib/rgeo/geos/impl_additions.rb +76 -0
  74. data/lib/rgeo/geos/interface.rb +139 -0
  75. data/lib/rgeo/geos/zm_factory.rb +275 -0
  76. data/lib/rgeo/geos/zm_impl.rb +432 -0
  77. data/lib/rgeo/impl_helper.rb +53 -0
  78. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +235 -0
  79. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +85 -0
  80. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +197 -0
  81. data/lib/rgeo/impl_helper/basic_point_methods.rb +138 -0
  82. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +121 -0
  83. data/lib/rgeo/impl_helper/math.rb +50 -0
  84. data/lib/rgeo/version.rb +52 -0
  85. data/lib/rgeo/wkrep.rb +72 -0
  86. data/lib/rgeo/wkrep/wkb_generator.rb +267 -0
  87. data/lib/rgeo/wkrep/wkb_parser.rb +315 -0
  88. data/lib/rgeo/wkrep/wkt_generator.rb +275 -0
  89. data/lib/rgeo/wkrep/wkt_parser.rb +496 -0
  90. data/test/common/geometry_collection_tests.rb +238 -0
  91. data/test/common/line_string_tests.rb +324 -0
  92. data/test/common/multi_line_string_tests.rb +209 -0
  93. data/test/common/multi_point_tests.rb +201 -0
  94. data/test/common/multi_polygon_tests.rb +208 -0
  95. data/test/common/point_tests.rb +331 -0
  96. data/test/common/polygon_tests.rb +232 -0
  97. data/test/coord_sys/tc_active_record_table.rb +102 -0
  98. data/test/coord_sys/tc_ogc_cs.rb +356 -0
  99. data/test/coord_sys/tc_proj4.rb +138 -0
  100. data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
  101. data/test/coord_sys/tc_sr_org.rb +70 -0
  102. data/test/coord_sys/tc_url_reader.rb +82 -0
  103. data/test/geos/tc_factory.rb +91 -0
  104. data/test/geos/tc_geometry_collection.rb +62 -0
  105. data/test/geos/tc_line_string.rb +62 -0
  106. data/test/geos/tc_misc.rb +72 -0
  107. data/test/geos/tc_multi_line_string.rb +62 -0
  108. data/test/geos/tc_multi_point.rb +62 -0
  109. data/test/geos/tc_multi_polygon.rb +63 -0
  110. data/test/geos/tc_point.rb +86 -0
  111. data/test/geos/tc_polygon.rb +86 -0
  112. data/test/geos/tc_zmfactory.rb +85 -0
  113. data/test/projected_geographic/tc_geometry_collection.rb +62 -0
  114. data/test/projected_geographic/tc_line_string.rb +62 -0
  115. data/test/projected_geographic/tc_multi_line_string.rb +62 -0
  116. data/test/projected_geographic/tc_multi_point.rb +62 -0
  117. data/test/projected_geographic/tc_multi_polygon.rb +63 -0
  118. data/test/projected_geographic/tc_point.rb +93 -0
  119. data/test/projected_geographic/tc_polygon.rb +62 -0
  120. data/test/simple_cartesian/tc_calculations.rb +145 -0
  121. data/test/simple_cartesian/tc_geometry_collection.rb +69 -0
  122. data/test/simple_cartesian/tc_line_string.rb +70 -0
  123. data/test/simple_cartesian/tc_multi_line_string.rb +67 -0
  124. data/test/simple_cartesian/tc_multi_point.rb +67 -0
  125. data/test/simple_cartesian/tc_multi_polygon.rb +70 -0
  126. data/test/simple_cartesian/tc_point.rb +91 -0
  127. data/test/simple_cartesian/tc_polygon.rb +67 -0
  128. data/test/simple_mercator/tc_geometry_collection.rb +62 -0
  129. data/test/simple_mercator/tc_line_string.rb +62 -0
  130. data/test/simple_mercator/tc_multi_line_string.rb +62 -0
  131. data/test/simple_mercator/tc_multi_point.rb +62 -0
  132. data/test/simple_mercator/tc_multi_polygon.rb +63 -0
  133. data/test/simple_mercator/tc_point.rb +93 -0
  134. data/test/simple_mercator/tc_polygon.rb +62 -0
  135. data/test/simple_mercator/tc_window.rb +219 -0
  136. data/test/spherical_geographic/tc_calculations.rb +203 -0
  137. data/test/spherical_geographic/tc_geometry_collection.rb +70 -0
  138. data/test/spherical_geographic/tc_line_string.rb +70 -0
  139. data/test/spherical_geographic/tc_multi_line_string.rb +67 -0
  140. data/test/spherical_geographic/tc_multi_point.rb +67 -0
  141. data/test/spherical_geographic/tc_multi_polygon.rb +70 -0
  142. data/test/spherical_geographic/tc_point.rb +100 -0
  143. data/test/spherical_geographic/tc_polygon.rb +67 -0
  144. data/test/tc_cartesian_analysis.rb +107 -0
  145. data/test/tc_oneoff.rb +63 -0
  146. data/test/wkrep/tc_wkb_generator.rb +249 -0
  147. data/test/wkrep/tc_wkb_parser.rb +353 -0
  148. data/test/wkrep/tc_wkt_generator.rb +362 -0
  149. data/test/wkrep/tc_wkt_parser.rb +480 -0
  150. metadata +267 -0
@@ -0,0 +1,106 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Spherical geometry common methods
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 Cartesian
40
+
41
+
42
+ module GeometryMethods # :nodoc:
43
+
44
+
45
+ def srid
46
+ factory.srid
47
+ end
48
+
49
+
50
+ def envelope
51
+ BoundingBox.new(factory).add(self).to_geometry
52
+ end
53
+
54
+
55
+ end
56
+
57
+
58
+ module LineStringMethods # :nodoc:
59
+
60
+
61
+ def _segments
62
+ unless @segments
63
+ @segments = (0..num_points-2).map do |i_|
64
+ Segment.new(point_n(i_), point_n(i_+1))
65
+ end
66
+ end
67
+ @segments
68
+ end
69
+
70
+
71
+ def is_simple?
72
+ segs_ = _segments
73
+ len_ = segs_.length
74
+ return false if segs_.any?{ |a_| a_.degenerate? }
75
+ return true if len_ == 1
76
+ return segs_[0].s != segs_[1].e if len_ == 2
77
+ segs_.each_with_index do |seg_, index_|
78
+ nindex_ = index_ + 1
79
+ nindex_ = nil if nindex_ == len_
80
+ return false if nindex_ && seg_.contains_point?(segs_[nindex_].e)
81
+ pindex_ = index_ - 1
82
+ pindex_ = nil if pindex_ < 0
83
+ return false if pindex_ && seg_.contains_point?(segs_[pindex_].s)
84
+ if nindex_
85
+ oindex_ = nindex_ + 1
86
+ while oindex_ < len_
87
+ oseg_ = segs_[oindex_]
88
+ return false if !(index_ == 0 && oindex_ == len_-1 && seg_.s == oseg_.e) && seg_.intersects_segment?(oseg_)
89
+ oindex_ += 1
90
+ end
91
+ end
92
+ end
93
+ true
94
+ end
95
+
96
+
97
+ def length
98
+ @segments.inject(0.0){ |sum_, seg_| sum_ + seg_.length }
99
+ end
100
+
101
+
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,150 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Cartesian toplevel interface
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 Cartesian
40
+
41
+ class << self
42
+
43
+
44
+ # Creates and returns a cartesian factory of the preferred
45
+ # Cartesian implementation.
46
+ #
47
+ # The actual implementation returned depends on which ruby
48
+ # interpreter is running and what libraries are available.
49
+ # RGeo will try to provide a fully-functional and performant
50
+ # implementation if possible. If not, the simple Cartesian
51
+ # implementation will be returned.
52
+ # In practice, this means it returns a Geos implementation if
53
+ # available; otherwise it falls back to the simple implementation.
54
+ #
55
+ # The given options are passed to the factory's constructor.
56
+ # What options are available depends on the particular
57
+ # implementation. See Geos::factory and Cartesian::simple_factory
58
+ # for details. Unsupported options are ignored.
59
+
60
+ def preferred_factory(opts_={})
61
+ if ::RGeo::Geos.supported?
62
+ ::RGeo::Geos.factory(opts_)
63
+ else
64
+ simple_factory(opts_)
65
+ end
66
+ end
67
+ alias_method :factory, :preferred_factory
68
+
69
+
70
+ # Returns a factory for the simple Cartesian implementation. This
71
+ # implementation provides all SFS 1.1 types, and also allows Z and
72
+ # M coordinates. It does not depend on external libraries, and is
73
+ # thus always available, but it does not implement many of the more
74
+ # advanced geometric operations. These limitations are:
75
+ #
76
+ # * Relational operators such as Feature::Geometry#intersects? are
77
+ # not implemented for most types.
78
+ # * Relational constructors such as Feature::Geometry#union are
79
+ # not implemented for most types.
80
+ # * Buffer and convex hull calculations are not implemented for most
81
+ # types. Boundaries are available except for GeometryCollection.
82
+ # * Length calculations are available, but areas are not. Distances
83
+ # are available only between points.
84
+ # * Equality and simplicity evaluation are implemented for some but
85
+ # not all types.
86
+ # * Assertions for polygons and multipolygons are not implemented.
87
+ #
88
+ # Unimplemented operations may raise Error::UnsupportedOperation
89
+ # if invoked.
90
+ #
91
+ # Options include:
92
+ #
93
+ # [<tt>:srid</tt>]
94
+ # Set the SRID returned by geometries created by this factory.
95
+ # Default is 0.
96
+ # [<tt>:proj4</tt>]
97
+ # The coordinate system in Proj4 format, either as a
98
+ # CoordSys::Proj4 object or as a string or hash representing the
99
+ # proj4 format. Optional.
100
+ # [<tt>:coord_sys</tt>]
101
+ # The coordinate system in OGC form, either as a subclass of
102
+ # CoordSys::CS::CoordinateSystem, or as a string in WKT format.
103
+ # Optional.
104
+ # [<tt>:srs_database</tt>]
105
+ # Optional. If provided, the value should be an implementation of
106
+ # CoordSys::SRSDatabase::Interface. If both this and an SRID are
107
+ # provided, they are used to look up the proj4 and coord_sys
108
+ # objects from a spatial reference system database.
109
+ # [<tt>:has_z_coordinate</tt>]
110
+ # Support a Z coordinate. Default is false.
111
+ # [<tt>:has_m_coordinate</tt>]
112
+ # Support an M coordinate. Default is false.
113
+
114
+ def simple_factory(opts_={})
115
+ Cartesian::Factory.new(opts_)
116
+ end
117
+
118
+
119
+ # Returns a Feature::FactoryGenerator that creates preferred
120
+ # factories. The given options are used as the default options.
121
+ #
122
+ # A common case for this is to provide the <tt>:srs_database</tt>
123
+ # as a default. Then, the factory generator need only be passed
124
+ # an SRID and it will automatically fetch the appropriate Proj4
125
+ # and CoordSys objects.
126
+
127
+ def preferred_factory_generator(defaults_={})
128
+ ::Proc.new{ |c_| preferred_factory(defaults_.merge(c_)) }
129
+ end
130
+ alias_method :factory_generator, :preferred_factory_generator
131
+
132
+
133
+ # Returns a Feature::FactoryGenerator that creates simple factories.
134
+ # The given options are used as the default options.
135
+ #
136
+ # A common case for this is to provide the <tt>:srs_database</tt>
137
+ # as a default. Then, the factory generator need only be passed
138
+ # an SRID and it will automatically fetch the appropriate Proj4
139
+ # and CoordSys objects.
140
+
141
+ def simple_factory_generator(defaults_={})
142
+ ::Proc.new{ |c_| simple_factory(defaults_.merge(c_)) }
143
+ end
144
+
145
+
146
+ end
147
+
148
+ end
149
+
150
+ end
@@ -0,0 +1,79 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Coordinate systems 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
+ # This module provides data structures and tools related to coordinate
41
+ # systems and coordinate transforms. It comprises the following parts:
42
+ #
43
+ # RGeo::CoordSys::Proj4 is a wrapper around the proj4 library, which
44
+ # defines a commonly-used syntax for specifying geographic and projected
45
+ # coordinate systems, and performs coordinate transformations.
46
+ #
47
+ # The RGeo::CoordSys::CS module contains an implementation of the CS
48
+ # (coordinate systems) package of the OGC Coordinate Transform spec.
49
+ # This includes classes for representing ellipsoids, datums, coordinate
50
+ # systems, and other related concepts, as well as a parser for the WKT
51
+ # format for specifying coordinate systems.
52
+ #
53
+ # The RGeo::CoordSys::SRSDatabase module contains tools for accessing
54
+ # spatial reference databases, from which you can look up coordinate
55
+ # system specifications. You can access the <tt>spatial_ref_sys</tt>
56
+ # table provided with OGC-compliant spatial databases such as PostGIS,
57
+ # read the databases provided with the proj4 library, or access URLs
58
+ # such as those provided by spatialreference.org.
59
+
60
+ module CoordSys
61
+ end
62
+
63
+
64
+ end
65
+
66
+
67
+ # Implementation files
68
+ begin
69
+ require 'rgeo/coord_sys/proj4_c_impl'
70
+ rescue ::LoadError; end
71
+ require 'rgeo/coord_sys/proj4'
72
+ require 'rgeo/coord_sys/cs/factories'
73
+ require 'rgeo/coord_sys/cs/entities'
74
+ require 'rgeo/coord_sys/cs/wkt_parser'
75
+ require 'rgeo/coord_sys/srs_database/interface.rb'
76
+ require 'rgeo/coord_sys/srs_database/active_record_table.rb'
77
+ require 'rgeo/coord_sys/srs_database/proj4_data.rb'
78
+ require 'rgeo/coord_sys/srs_database/url_reader.rb'
79
+ require 'rgeo/coord_sys/srs_database/sr_org.rb'
@@ -0,0 +1,1524 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -----------------------------------------------------------------------------
3
+ #
4
+ # OGC CS objects for RGeo
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
+ module RGeo
39
+
40
+ module CoordSys
41
+
42
+
43
+ module CS
44
+
45
+
46
+ # An axis orientation constant for AxisInfo.
47
+ # Unknown or unspecified axis orientation. This can be used for
48
+ # local or fitted coordinate systems.
49
+ AO_OTHER = 0
50
+
51
+ # An axis orientation constant for AxisInfo.
52
+ # Increasing ordinates values go North. This is usually used for
53
+ # Grid Y coordinates and Latitude.
54
+ AO_NORTH = 1
55
+
56
+ # An axis orientation constant for AxisInfo.
57
+ # Increasing ordinates values go South. This is rarely used.
58
+ AO_SOUTH = 2
59
+
60
+ # An axis orientation constant for AxisInfo.
61
+ # Increasing ordinates values go East. This is rarely used.
62
+ AO_EAST = 3
63
+
64
+ # An axis orientation constant for AxisInfo.
65
+ # Increasing ordinates values go West. This is usually used for
66
+ # Grid X coordinates and Longitude.
67
+ AO_WEST = 4
68
+
69
+ # An axis orientation constant for AxisInfo.
70
+ # Increasing ordinates values go up. This is used for vertical
71
+ # coordinate systems.
72
+ AO_UP = 5
73
+
74
+ # An axis orientation constant for AxisInfo.
75
+ # Increasing ordinates values go down. This is used for vertical
76
+ # coordinate systems.
77
+ AO_DOWN = 6
78
+
79
+
80
+ # A datum type constant for HorizontalDatum.
81
+ # Lowest possible value for horizontal datum types.
82
+ HD_MIN = 1000
83
+
84
+ # A datum type constant for HorizontalDatum.
85
+ # Unspecified horizontal datum type. Horizontal datums with this
86
+ # type should never supply a conversion to WGS84 using Bursa Wolf
87
+ # parameters.
88
+ HD_OTHER = 1000
89
+
90
+ # A datum type constant for HorizontalDatum.
91
+ # These datums, such as ED50, NAD27 and NAD83, have been designed
92
+ # to support horizontal positions on the ellipsoid as opposed to
93
+ # positions in 3-D space. These datums were designed mainly to
94
+ # support a horizontal component of a position in a domain of
95
+ # limited extent, such as a country, a region or a continent.
96
+ HD_CLASSIC = 1001
97
+
98
+ # A datum type constant for HorizontalDatum.
99
+ # A geocentric datum is a "satellite age" modern geodetic datum
100
+ # mainly of global extent, such as WGS84 (used in GPS), PZ90 (used
101
+ # in GLONASS) and ITRF. These datums were designed to support both
102
+ # a horizontal component of position and a vertical component of
103
+ # position (through ellipsoidal heights). The regional realizations
104
+ # of ITRF, such as ETRF, are also included in this category.
105
+ HD_GEOCENTRIC = 1002
106
+
107
+ # A datum type constant for HorizontalDatum.
108
+ # Highest possible value for horizontal datum types.
109
+ HD_MAX = 1999
110
+
111
+ # A datum type constant for VerticalDatum.
112
+ # Lowest possible value for vertical datum types.
113
+ VD_MIN = 2000
114
+
115
+ # A datum type constant for VerticalDatum.
116
+ # Unspecified vertical datum type.
117
+ VD_OTHER = 2000
118
+
119
+ # A datum type constant for VerticalDatum.
120
+ # A vertical datum for orthometric heights that are measured along
121
+ # the plumb line.
122
+ VD_ORTHOMETRIC = 2001
123
+
124
+ # A datum type constant for VerticalDatum.
125
+ # A vertical datum for ellipsoidal heights that are measured along
126
+ # the normal to the ellipsoid used in the definition of horizontal
127
+ # datum.
128
+ VD_ELLIPSOIDAL = 2002
129
+
130
+ # A datum type constant for VerticalDatum.
131
+ # The vertical datum of altitudes or heights in the atmosphere.
132
+ # These are approximations of orthometric heights obtained with the
133
+ # help of a barometer or a barometric altimeter. These values are
134
+ # usually expressed in one of the following units: meters, feet,
135
+ # millibars (used to measure pressure levels), or theta value (units
136
+ # used to measure geopotential height).
137
+ VD_ALTITUDE_BAROMETRIC = 2003
138
+
139
+ # A datum type constant for VerticalDatum.
140
+ # A normal height system.
141
+ VD_NORMAL = 2004
142
+
143
+ # A datum type constant for VerticalDatum.
144
+ # A vertical datum of geoid model derived heights, also called
145
+ # GPS-derived heights. These heights are approximations of
146
+ # orthometric heights (H), constructed from the ellipsoidal heights
147
+ # (h) by the use of the given geoid undulation model (N) through
148
+ # the equation: H=h-N.
149
+ VD_GEOID_MODE_DERIVED = 2005
150
+
151
+ # A datum type constant for VerticalDatum.
152
+ # This attribute is used to support the set of datums generated for
153
+ # hydrographic engineering projects where depth measurements below
154
+ # sea level are needed. It is often called a hydrographic or a
155
+ # marine datum. Depths are measured in the direction perpendicular
156
+ # (approximately) to the actual equipotential surfaces of the
157
+ # earth's gravity field, using such procedures as echo-sounding.
158
+ VD_DEPTH = 2006
159
+
160
+ # A datum type constant for VerticalDatum.
161
+ # Highest possible value for vertical datum types.
162
+ VD_MAX = 2999
163
+
164
+ # A datum type constant for LocalDatum.
165
+ # Lowest possible value for local datum types.
166
+ LD_MIN = 10000
167
+
168
+ # A datum type constant for LocalDatum.
169
+ # Highest possible value for local datum types.
170
+ LD_MAX = 32767
171
+
172
+
173
+ # This is a base class for all OGC coordinate system objects.
174
+ # This includes both interfaces and data types from the OGC
175
+ # Coordinate Transformation spec.
176
+ #
177
+ # This is a non-instantiable abstract class.
178
+
179
+ class Base
180
+
181
+
182
+ def inspect # :nodoc:
183
+ "#<#{self.class}:0x#{object_id.to_s(16)} #{to_wkt}>"
184
+ end
185
+
186
+
187
+ # Tests for equality. Two objects are defined as equal if they
188
+ # have the same type (class) and the same WKT representation.
189
+
190
+ def eql?(rhs_)
191
+ rhs_.class == self.class && rhs_.to_wkt == self.to_wkt
192
+ end
193
+ alias_method :==, :eql?
194
+
195
+
196
+ # Returns the default WKT representation.
197
+
198
+ def to_s
199
+ to_wkt
200
+ end
201
+
202
+
203
+ # Computes the WKT representation. Options include:
204
+ #
205
+ # [<tt>:standard_brackets</tt>]
206
+ # If set to true, outputs parentheses rather than square
207
+ # brackets. Default is false.
208
+
209
+ def to_wkt(opts_={})
210
+ opts_[:standard_brackets] ? _to_wkt('(', ')') : _to_wkt('[', ']')
211
+ end
212
+
213
+
214
+ def _to_wkt(open_, close_) # :nodoc:
215
+ content_ = _wkt_content(open_, close_).map{ |obj_| ",#{obj_}" }.join
216
+ if defined?(@authority) && @authority
217
+ authority_ = ",AUTHORITY#{open_}#{@authority.inspect},#{@authority_code.inspect}#{close_}"
218
+ else
219
+ authority_ = ''
220
+ end
221
+ "#{_wkt_typename}#{open_}#{@name.inspect}#{content_}#{authority_}#{close_}"
222
+ end
223
+
224
+
225
+ class << self
226
+
227
+ private :new
228
+
229
+ end
230
+
231
+
232
+ end
233
+
234
+
235
+ # == OGC spec description
236
+ #
237
+ # Details of axis. This is used to label axes, and indicate the
238
+ # orientation.
239
+
240
+ class AxisInfo < Base
241
+
242
+ # :stopdoc:
243
+ NAMES_BY_VALUE = ['OTHER', 'NORTH', 'SOUTH', 'EAST', 'WEST', 'UP', 'DOWN']
244
+ # :startdoc:
245
+
246
+ def initialize(name_, orientation_) # :nodoc:
247
+ @name = name_
248
+ case orientation_
249
+ when ::String, ::Symbol
250
+ @orientation = NAMES_BY_VALUE.index(orientation_.to_s.upcase).to_i
251
+ else
252
+ @orientation = orientation_.to_i
253
+ end
254
+ end
255
+
256
+
257
+ # Human readable name for axis. Possible values are "X", "Y",
258
+ # "Long", "Lat" or any other short string.
259
+ attr_reader :name
260
+
261
+ # Gets enumerated value for orientation.
262
+ attr_reader :orientation
263
+
264
+
265
+ def _wkt_typename # :nodoc:
266
+ "AXIS"
267
+ end
268
+
269
+ def _wkt_content(open_, close_) # :nodoc:
270
+ [NAMES_BY_VALUE[@orientation]]
271
+ end
272
+
273
+
274
+ class << self
275
+
276
+
277
+ # Creates an AxisInfo. you must pass the human readable name for
278
+ # the axis (e.g. "X", "Y", "Long", "Lat", or other short string)
279
+ # and either an integer orientation code or a string. Possible
280
+ # orientation values are "<tt>OTHER</tt>", "<tt>NORTH</tt>",
281
+ # "<tt>SOUTH</tt>", "<tt>EAST</tt>", "<tt>WEST</tt>",
282
+ # "<tt>UP</tt>", and "<tt>DOWN</tt>", or the corresponding
283
+ # integer values 0-5.
284
+
285
+ def create(name_, orientation_)
286
+ new(name_, orientation_)
287
+ end
288
+
289
+
290
+ end
291
+
292
+ end
293
+
294
+
295
+ # == OGC spec description
296
+ #
297
+ # A named projection parameter value. The linear units of
298
+ # parameters' values match the linear units of the containing
299
+ # projected coordinate system. The angular units of parameter
300
+ # values match the angular units of the geographic coordinate
301
+ # system that the projected coordinate system is based on.
302
+
303
+ class ProjectionParameter < Base
304
+
305
+ def initialize(name_, value_) # :nodoc:
306
+ @name = name_
307
+ @value = value_.to_f
308
+ end
309
+
310
+
311
+ # The parameter name.
312
+ attr_reader :name
313
+
314
+ # The parameter value.
315
+ attr_reader :value
316
+
317
+
318
+ def _wkt_typename # :nodoc:
319
+ "PARAMETER"
320
+ end
321
+
322
+ def _wkt_content(open_, close_) # :nodoc:
323
+ [@value]
324
+ end
325
+
326
+
327
+ class << self
328
+
329
+
330
+ # Create a parameter given the name and value.
331
+
332
+ def create(name_, value_)
333
+ new(name_, value_)
334
+ end
335
+
336
+
337
+ end
338
+
339
+ end
340
+
341
+
342
+ # == OGC spec description
343
+ #
344
+ # Parameters for a geographic transformation into WGS84. The Bursa
345
+ # Wolf parameters should be applied to geocentric coordinates, where
346
+ # the X axis points towards the Greenwich Prime Meridian, the Y axis
347
+ # points East, and the Z axis points North.
348
+
349
+ class WGS84ConversionInfo < Base
350
+
351
+ def initialize(dx_, dy_, dz_, ex_, ey_, ez_, ppm_) # :nodoc:
352
+ @dx = dx_.to_f
353
+ @dy = dy_.to_f
354
+ @dz = dz_.to_f
355
+ @ex = ex_.to_f
356
+ @ey = ey_.to_f
357
+ @ez = ez_.to_f
358
+ @ppm = ppm_.to_f
359
+ end
360
+
361
+
362
+ # Bursa Wolf shift in meters.
363
+ attr_reader :dx
364
+
365
+ # Bursa Wolf shift in meters.
366
+ attr_reader :dy
367
+
368
+ # Bursa Wolf shift in meters.
369
+ attr_reader :dz
370
+
371
+ # Bursa Wolf rotation in arc seconds.
372
+ attr_reader :ex
373
+
374
+ # Bursa Wolf rotation in arc seconds.
375
+ attr_reader :ey
376
+
377
+ # Bursa Wolf rotation in arc seconds.
378
+ attr_reader :ez
379
+
380
+ # Bursa Wolf scaling in in parts per million.
381
+ attr_reader :ppm
382
+
383
+
384
+ def _to_wkt(open_, close_) # :nodoc:
385
+ "TOWGS84#{open_}#{@dx},#{@dy},#{@dz},#{@ex},#{@ey},#{@ez},#{@ppm}#{close_}"
386
+ end
387
+
388
+
389
+ class << self
390
+
391
+
392
+ # Create the horizontal datum shift transformation into WGS84,
393
+ # given the seven Bursa Wolf parameters.
394
+ # The Bursa Wolf shift should be in meters, the rotation in arc
395
+ # seconds, and the scaling in parts per million.
396
+
397
+ def create(dx_, dy_, dz_, ex_, ey_, ez_, ppm_)
398
+ new(dx_, dy_, dz_, ex_, ey_, ez_, ppm_)
399
+ end
400
+
401
+
402
+ end
403
+
404
+ end
405
+
406
+
407
+ # == OGC spec description
408
+ #
409
+ # A base interface for metadata applicable to coordinate system
410
+ # objects.
411
+ #
412
+ # The metadata items "Abbreviation"’, "Alias", "Authority",
413
+ # "AuthorityCode", "Name" and "Remarks" were specified in the Simple
414
+ # Features interfaces, so they have been kept here.
415
+ #
416
+ # This specification does not dictate what the contents of these
417
+ # items should be. However, the following guidelines are suggested:
418
+ #
419
+ # When CS_CoordinateSystemAuthorityFactory is used to create an
420
+ # object, the "Authority" and "AuthorityCode" values should be set
421
+ # to the authority name of the factory object, and the authority
422
+ # code supplied by the client, respectively. The other values may or
423
+ # may not be set. (If the authority is EPSG, the implementer may
424
+ # consider using the corresponding metadata values in the EPSG
425
+ # tables.)
426
+ #
427
+ # When CS_CoordinateSystemFactory creates an object, the "Name"
428
+ # should be set to the value supplied by the client. All of the
429
+ # other metadata items should be left empty.
430
+ #
431
+ # == Notes
432
+ #
433
+ # This is a non-instantiable abstract class.
434
+ #
435
+ # Most subclasses will have a set of optional parameters in their
436
+ # "create" method to set the metadata fields. These parameters are,
437
+ # in order:
438
+ #
439
+ # * <b>authority</b>: authority name
440
+ # * <b>authority_code</b>: authority-specific identification code
441
+ # * <b>abbreviation</b>: an abbreviation
442
+ # * <b>alias</b>: an alias
443
+ # * <b>remarks</b>: provider-supplied remarks.
444
+
445
+ class Info < Base
446
+
447
+ def initialize(name_, authority_=nil, authority_code_=nil, abbreviation_=nil, alias_=nil, remarks_=nil) # :nodoc:
448
+ @name = name_
449
+ @authority = authority_ ? authority_.to_s : nil
450
+ @authority_code = authority_code_ ? authority_code_.to_s : nil
451
+ @abbreviation = abbreviation_ ? abbreviation_.to_s : nil
452
+ @alias = alias_ ? alias_.to_s : nil
453
+ @remarks = remarks_ ? remarks_.to_s : nil
454
+ end
455
+
456
+
457
+ # Gets the abbreviation.
458
+ attr_reader :abbreviation
459
+
460
+ # Gets the alias.
461
+ attr_reader :alias
462
+
463
+ # Gets the authority name.
464
+ # An Authority is an organization that maintains definitions of
465
+ # Authority Codes. For example the European Petroleum Survey Group
466
+ # (EPSG) maintains a database of coordinate systems, and other
467
+ # spatial referencing objects, where each object has a code number
468
+ # ID. For example, the EPSG code for a WGS84 Lat/Lon coordinate
469
+ # system is "4326".
470
+ attr_reader :authority
471
+
472
+ # Gets the authority-specific identification code.
473
+ # The AuthorityCode is a compact string defined by an Authority to
474
+ # reference a particular spatial reference object. For example,
475
+ # the European Survey Group (EPSG) authority uses 32 bit integers
476
+ # to reference coordinate systems, so all their code strings will
477
+ # consist of a few digits. The EPSG code for WGS84 Lat/Lon is
478
+ # "4326".
479
+ attr_reader :authority_code
480
+
481
+ # Gets the name.
482
+ attr_reader :name
483
+
484
+ # Gets the provider-supplied remarks.
485
+ attr_reader :remarks
486
+
487
+
488
+ end
489
+
490
+
491
+ # == OGC spec description
492
+ #
493
+ # Base interface for defining units.
494
+ #
495
+ # == Notes
496
+ #
497
+ # Normally, you will instantiate one of the subclasses LinearUnit or
498
+ # AngularUnit. However, it is possible to instantiate Unit if it is
499
+ # not clear whether the data refers to a LinearUnit or AngularUnit.
500
+
501
+ class Unit < Info
502
+
503
+ def initialize(name_, conversion_factor_, *optional_) # :nodoc:
504
+ super(name_, *optional_)
505
+ @conversion_factor = conversion_factor_.to_f
506
+ end
507
+
508
+
509
+ # This field is not part of the OGC CT spec, but is part of the
510
+ # SFS. It is an alias of the appropriate field in the subclass,
511
+ # i.e. LinearUnit#meters_per_unit or AngularUnit#radians_per_unit.
512
+ attr_reader :conversion_factor
513
+
514
+
515
+ def _wkt_typename # :nodoc:
516
+ "UNIT"
517
+ end
518
+
519
+ def _wkt_content(open_, close_) # :nodoc:
520
+ [@conversion_factor]
521
+ end
522
+
523
+
524
+ class << self
525
+
526
+
527
+ # Create a bare Unit that does not specify whether it is a
528
+ # LinearUnit or an AngularUnit, given a unit name and a
529
+ # conversion factor. You may also provide the optional
530
+ # parameters specified by the Info interface.
531
+
532
+ def create(name_, conversion_factor_, *optional_)
533
+ new(name_, conversion_factor_, *optional_)
534
+ end
535
+
536
+
537
+ end
538
+
539
+ end
540
+
541
+
542
+ # == OGC spec description
543
+ #
544
+ # Definition of linear units.
545
+
546
+ class LinearUnit < Unit
547
+
548
+
549
+ # Returns the number of meters per LinearUnit.
550
+ # Also available as Unit#conversion_factor.
551
+
552
+ def meters_per_unit
553
+ @conversion_factor
554
+ end
555
+
556
+
557
+ class << self
558
+
559
+
560
+ # Create a LinearUnit given a unit name and a conversion factor
561
+ # in meters per unit. You may also provide the optional
562
+ # parameters specified by the Info interface.
563
+
564
+ def create(name_, meters_per_unit_, *optional_)
565
+ new(name_, meters_per_unit_, *optional_)
566
+ end
567
+
568
+
569
+ end
570
+
571
+ end
572
+
573
+
574
+ # == OGC spec description
575
+ #
576
+ # Definition of angular units.
577
+
578
+ class AngularUnit < Unit
579
+
580
+
581
+ # Returns the number of radians per AngularUnit.
582
+ # Also available as Unit#conversion_factor.
583
+
584
+ def radians_per_unit
585
+ @conversion_factor
586
+ end
587
+
588
+
589
+ class << self
590
+
591
+
592
+ # Create an AngularUnit given a unit name and a conversion
593
+ # factor in radians per unit. You may also provide the optional
594
+ # parameters specified by the Info interface.
595
+
596
+ def create(name_, radians_per_unit_, *optional_)
597
+ new(name_, radians_per_unit_, *optional_)
598
+ end
599
+
600
+
601
+ end
602
+
603
+ end
604
+
605
+
606
+ # == OGC spec description
607
+ #
608
+ # A meridian used to take longitude measurements from.
609
+
610
+ class PrimeMeridian < Info
611
+
612
+ def initialize(name_, angular_unit_, longitude_, *optional_) # :nodoc:
613
+ super(name_, *optional_)
614
+ @angular_unit = angular_unit_
615
+ @longitude = longitude_.to_f
616
+ end
617
+
618
+
619
+ # Returns the AngularUnits.
620
+ attr_reader :angular_unit
621
+
622
+ # Returns the longitude value relative to the Greenwich Meridian.
623
+ # The longitude is expressed in this objects angular units.
624
+ attr_reader :longitude
625
+
626
+
627
+ def _wkt_typename # :nodoc:
628
+ "PRIMEM"
629
+ end
630
+
631
+ def _wkt_content(open_, close_) # :nodoc:
632
+ [@longitude]
633
+ end
634
+
635
+
636
+ class << self
637
+
638
+
639
+ # Create a PrimeMeridian given a name, AngularUnits, and the
640
+ # longitude relative to the Greenwich Meridian, expressed in
641
+ # the AngularUnits. You may also provide the optional parameters
642
+ # specified by the Info interface.
643
+
644
+ def create(name_, angular_unit_, longitude_, *optional_)
645
+ new(name_, angular_unit_, longitude_, *optional_)
646
+ end
647
+
648
+
649
+ end
650
+
651
+
652
+ end
653
+
654
+
655
+ # == OGC spec description
656
+ #
657
+ # An approximation of the Earth's surface as a squashed sphere.
658
+
659
+ class Ellipsoid < Info
660
+
661
+ def initialize(name_, semi_major_axis_, semi_minor_axis_, inverse_flattening_, ivf_definitive_, linear_unit_, *optional_) # :nodoc:
662
+ super(name_, *optional_)
663
+ @semi_major_axis = semi_major_axis_.to_f
664
+ @semi_minor_axis = semi_minor_axis_.to_f
665
+ @inverse_flattening = inverse_flattening_.to_f
666
+ @ivf_definitive = ivf_definitive_ ? true : false
667
+ @linear_unit = linear_unit_
668
+ end
669
+
670
+
671
+ # Gets the equatorial radius. The returned length is expressed in
672
+ # this object's axis units.
673
+ attr_reader :semi_major_axis
674
+
675
+ # Gets the polar radius. The returned length is expressed in this
676
+ # object's axis units.
677
+ attr_reader :semi_minor_axis
678
+
679
+ # Returns the value of the inverse of the flattening constant. The
680
+ # inverse flattening is related to the equatorial/polar radius by
681
+ # the formula ivf=re/(re-rp). For perfect spheres, this formula
682
+ # breaks down, and a special IVF value of zero is used.
683
+ attr_reader :inverse_flattening
684
+
685
+ # Is the Inverse Flattening definitive for this ellipsoid? Some
686
+ # ellipsoids use the IVF as the defining value, and calculate the
687
+ # polar radius whenever asked. Other ellipsoids use the polar
688
+ # radius to calculate the IVF whenever asked. This distinction can
689
+ # be important to avoid floating-point rounding errors.
690
+ attr_reader :ivf_definitive
691
+
692
+ # Returns the LinearUnit. The units of the semi-major and
693
+ # semi-minor axis values.
694
+ attr_reader :axis_unit
695
+
696
+
697
+ def _wkt_typename # :nodoc:
698
+ "SPHEROID"
699
+ end
700
+
701
+ def _wkt_content(open_, close_) # :nodoc:
702
+ [@semi_major_axis, @inverse_flattening]
703
+ end
704
+
705
+
706
+ class << self
707
+
708
+
709
+ # Create an Ellipsoid given a name, semi-major and semi-minor
710
+ # axes, the inverse flattening, a boolean indicating whether
711
+ # the inverse flattening is definitive, and the LinearUnit
712
+ # indicating the axis units. The LinearUnit is optional and
713
+ # may be set to nil. You may also provide the optional parameters
714
+ # specified by the Info interface.
715
+
716
+ def create(name_, semi_major_axis_, semi_minor_axis_, inverse_flattening_, ivf_definitive_, linear_unit_, *optional_)
717
+ new(name_, semi_major_axis_, semi_minor_axis_, inverse_flattening_, ivf_definitive_, linear_unit_, *optional_)
718
+ end
719
+
720
+
721
+ # Create an Ellipsoid given a name, semi-major and semi-minor
722
+ # axes, and the LinearUnit indicating the axis units. In the
723
+ # resulting ellipsoid, the inverse flattening is not definitive.
724
+ # The LinearUnit is optional and may be set to nil. You may also
725
+ # provide the optional parameters specified by the Info interface.
726
+
727
+ def create_ellipsoid(name_, semi_major_axis_, semi_minor_axis_, linear_unit_, *optional_)
728
+ semi_major_axis_ = semi_major_axis_.to_f
729
+ semi_minor_axis_ = semi_minor_axis_.to_f
730
+ inverse_flattening_ = semi_major_axis_ / (semi_major_axis_ - semi_minor_axis_)
731
+ inverse_flattening_ = 0.0 if inverse_flattening_.infinite?
732
+ new(name_, semi_major_axis_, semi_minor_axis_, inverse_flattening_, false, linear_unit_, *optional_)
733
+ end
734
+
735
+
736
+ # Create an Ellipsoid given a name, semi-major axis, inverse
737
+ # flattening, and the LinearUnit indicating the axis units. In
738
+ # the resulting ellipsoid, the inverse flattening is definitive.
739
+ # The LinearUnit is optional and may be set to nil. You may also
740
+ # provide the optional parameters specified by the Info interface.
741
+
742
+ def create_flattened_sphere(name_, semi_major_axis_, inverse_flattening_, linear_unit_, *optional_)
743
+ semi_major_axis_ = semi_major_axis_.to_f
744
+ inverse_flattening_ = inverse_flattening_.to_f
745
+ semi_minor_axis_ = semi_major_axis_ - semi_major_axis_ / inverse_flattening_
746
+ semi_minor_axis_ = semi_major_axis_ if semi_minor_axis_.infinite?
747
+ new(name_, semi_major_axis_, semi_minor_axis_, inverse_flattening_, true, linear_unit_, *optional_)
748
+ end
749
+
750
+
751
+ end
752
+
753
+ end
754
+
755
+
756
+ # == OGC spec description
757
+ #
758
+ # A set of quantities from which other quantities are calculated.
759
+ # For the OGC abstract model, it can be defined as a set of real
760
+ # points on the earth that have coordinates. EG. A datum can be
761
+ # thought of as a set of parameters defining completely the origin
762
+ # and orientation of a coordinate system with respect to the earth.
763
+ # A textual description and/or a set of parameters describing the
764
+ # relationship of a coordinate system to some predefined physical
765
+ # locations (such as center of mass) and physical directions (such
766
+ # as axis of spin). The definition of the datum may also include
767
+ # the temporal behavior (such as the rate of change of the
768
+ # orientation of the coordinate axes).
769
+ #
770
+ # == Notes
771
+ #
772
+ # This is a non-instantiable abstract class. You must instantiate
773
+ # one of the subclasses HorizontalDatum, VerticalDatum, or
774
+ # LocalDatum.
775
+
776
+ class Datum < Info
777
+
778
+ def initialize(name_, datum_type_, *optional_) # :nodoc:
779
+ super(name_, *optional_)
780
+ @datum_type = datum_type_.to_i
781
+ end
782
+
783
+
784
+ # Gets the type of the datum as an enumerated code.
785
+ attr_reader :datum_type
786
+
787
+
788
+ def _wkt_content(open_, close_) # :nodoc:
789
+ []
790
+ end
791
+
792
+
793
+ end
794
+
795
+
796
+ # == OGC spec description
797
+ #
798
+ # Procedure used to measure vertical distances.
799
+
800
+ class VerticalDatum < Datum
801
+
802
+ def _wkt_typename # :nodoc:
803
+ "VERT_DATUM"
804
+ end
805
+
806
+ def _wkt_content(open_, close_) # :nodoc:
807
+ [@datum_type]
808
+ end
809
+
810
+ class << self
811
+
812
+
813
+ # Create a VerticalDatum given a name and a datum type code.
814
+ # You may also provide the optional parameters specified by the
815
+ # Info interface.
816
+
817
+ def create(name_, datum_type_, *optional_)
818
+ new(name_, datum_type_, *optional_)
819
+ end
820
+
821
+
822
+ end
823
+
824
+ end
825
+
826
+
827
+ # == OGC spec description
828
+ #
829
+ # Local datum. If two local datum objects have the same datum type
830
+ # and name, then they can be considered equal. This means that
831
+ # coordinates can be transformed between two different local
832
+ # coordinate systems, as long as they are based on the same local
833
+ # datum.
834
+
835
+ class LocalDatum < Datum
836
+
837
+ def _wkt_typename # :nodoc:
838
+ "LOCAL_DATUM"
839
+ end
840
+
841
+ def _wkt_content(open_, close_) # :nodoc:
842
+ [@datum_type]
843
+ end
844
+
845
+ class << self
846
+
847
+
848
+ # Create a LocalDatum given a name and a datum type code. You
849
+ # may also provide the optional parameters specified by the
850
+ # Info interface.
851
+
852
+ def create(name_, datum_type_, *optional_)
853
+ new(name_, datum_type_, *optional_)
854
+ end
855
+
856
+
857
+ end
858
+
859
+ end
860
+
861
+
862
+ # == OGC spec description
863
+ #
864
+ # Procedure used to measure positions on the surface of the Earth.
865
+
866
+ class HorizontalDatum < Datum
867
+
868
+ def initialize(name_, datum_type_, ellipsoid_, wgs84_parameters_, *optional_) # :nodoc:
869
+ super(name_, datum_type_, *optional_)
870
+ @ellipsoid = ellipsoid_
871
+ @wgs84_parameters = wgs84_parameters_
872
+ end
873
+
874
+
875
+ # Returns the Ellipsoid.
876
+ attr_reader :ellipsoid
877
+
878
+ # Gets preferred parameters for a Bursa Wolf transformation into
879
+ # WGS84. The 7 returned values correspond to (dx,dy,dz) in meters,
880
+ # (ex,ey,ez) in arc-seconds, and scaling in parts-per-million.
881
+ attr_reader :wgs84_parameters
882
+
883
+
884
+ def _wkt_typename # :nodoc:
885
+ "DATUM"
886
+ end
887
+
888
+ def _wkt_content(open_, close_) # :nodoc:
889
+ array_ = [@ellipsoid._to_wkt(open_, close_)]
890
+ array_ << @wgs84_parameters._to_wkt(open_, close_) if @wgs84_parameters
891
+ array_
892
+ end
893
+
894
+
895
+ class << self
896
+
897
+
898
+ # Create a HorizontalDatum given a name, datum type code,
899
+ # Ellipsoid, and WGS84ConversionInfo. The WGS84ConversionInfo
900
+ # is optional and may be set to nil. You may also provide the
901
+ # optional parameters specified by the Info interface.
902
+
903
+ def create(name_, datum_type_, ellipsoid_, wgs84_parameters_, *optional_)
904
+ new(name_, datum_type_, ellipsoid_, wgs84_parameters_, *optional_)
905
+ end
906
+
907
+
908
+ end
909
+
910
+ end
911
+
912
+
913
+ # == OGC spec description
914
+ #
915
+ # A projection from geographic coordinates to projected coordinates.
916
+
917
+ class Projection < Info
918
+
919
+ def initialize(name_, class_name_, parameters_, *optional_) # :nodoc:
920
+ super(name_, *optional_)
921
+ @class_name = class_name_.to_s
922
+ @parameters = parameters_ ? parameters_.dup : []
923
+ end
924
+
925
+
926
+ # Gets the projection classification name
927
+ # (e.g. "Transverse_Mercator").
928
+ attr_reader :class_name
929
+
930
+
931
+ # Gets number of parameters of the projection.
932
+
933
+ def num_parameters
934
+ @parameters.size
935
+ end
936
+
937
+
938
+ # Gets an inexed parameter of the projection.
939
+
940
+ def get_parameter(index_)
941
+ @parameters[index_]
942
+ end
943
+
944
+
945
+ # Iterates over the parameters of the projection.
946
+
947
+ def each_parameter(&block_)
948
+ @parameters.each(&block_)
949
+ end
950
+
951
+
952
+ def _wkt_typename # :nodoc:
953
+ "PROJECTION"
954
+ end
955
+
956
+ def _wkt_content(open_, close_) # :nodoc:
957
+ []
958
+ end
959
+
960
+
961
+ class << self
962
+
963
+
964
+ # Create a Projection given a name, a projection class, and an
965
+ # array of ProjectionParameter. You may also provide the
966
+ # optional parameters specified by the Info interface.
967
+
968
+ def create(name_, class_name_, parameters_, *optional_)
969
+ new(name_, class_name_, parameters_, *optional_)
970
+ end
971
+
972
+
973
+ end
974
+
975
+ end
976
+
977
+
978
+ # == OGC spec description
979
+ #
980
+ # Base interface for all coordinate systems.
981
+ #
982
+ # A coordinate system is a mathematical space, where the elements
983
+ # of the space are called positions. Each position is described by
984
+ # a list of numbers. The length of the list corresponds to the
985
+ # dimension of the coordinate system. So in a 2D coordinate system
986
+ # each position is described by a list containing 2 numbers.
987
+ #
988
+ # However, in a coordinate system, not all lists of numbers
989
+ # correspond to a position -- some lists may be outside the domain
990
+ # of the coordinate system. For example, in a 2D Lat/Lon coordinate
991
+ # system, the list (91,91) does not correspond to a position.
992
+ #
993
+ # Some coordinate systems also have a mapping from the mathematical
994
+ # space into locations in the real world. So in a Lat/Lon coordinate
995
+ # system, the mathematical position (lat, long) corresponds to a
996
+ # location on the surface of the Earth. This mapping from the
997
+ # mathematical space into real-world locations is called a Datum.
998
+ #
999
+ # == Notes
1000
+ #
1001
+ # This is a non-instantiable abstract class. You must instantiate
1002
+ # one of the subclasses GeocentricCoordinateSystem,
1003
+ # GeographicCoordinateSystem, ProjectedCoordinateSystem,
1004
+ # VerticalCoordinateSystem, LocalCoordinateSystem, or
1005
+ # CompoundCoordinateSystem.
1006
+
1007
+ class CoordinateSystem < Info
1008
+
1009
+ def initialize(name_, dimension_, *optional_) # :nodoc:
1010
+ super(name_, *optional_)
1011
+ @dimension = dimension_.to_i
1012
+ end
1013
+
1014
+
1015
+ # Dimension of the coordinate system
1016
+ attr_reader :dimension
1017
+
1018
+
1019
+ # Gets axis details for dimension within coordinate system. Each
1020
+ # dimension in the coordinate system has a corresponding axis.
1021
+
1022
+ def get_axis(dimension_)
1023
+ nil
1024
+ end
1025
+
1026
+
1027
+ # Gets units for dimension within coordinate system. Each
1028
+ # dimension in the coordinate system has corresponding units.
1029
+
1030
+ def get_units(dimension_)
1031
+ nil
1032
+ end
1033
+
1034
+
1035
+ end
1036
+
1037
+
1038
+ # == OGC spec description
1039
+ #
1040
+ # An aggregate of two coordinate systems (CRS). One of these is
1041
+ # usually a CRS based on a two dimensional coordinate system such
1042
+ # as a geographic or a projected coordinate system with a horizontal
1043
+ # datum. The other is a vertical CRS which is a one-dimensional
1044
+ # coordinate system with a vertical datum.
1045
+
1046
+ class CompoundCoordinateSystem < CoordinateSystem
1047
+
1048
+ def initialize(name_, head_, tail_, *optional_) # :nodoc:
1049
+ super(name_, head_.dimension + tail_.dimension, *optional_)
1050
+ @head = head_
1051
+ @tail = tail_
1052
+ end
1053
+
1054
+
1055
+ # Gets first sub-coordinate system.
1056
+ attr_reader :head
1057
+
1058
+ # Gets second sub-coordinate system.
1059
+ attr_reader :tail
1060
+
1061
+
1062
+ # Implements CoordinateSystem#get_axis
1063
+
1064
+ def get_axis(index_)
1065
+ hd_ = @head.dimension
1066
+ index_ < hd_ ? @head.get_axis(index_) : @tail.get_axis(index_ - hd_)
1067
+ end
1068
+
1069
+
1070
+ # Implements CoordinateSystem#get_units
1071
+
1072
+ def get_units(index_)
1073
+ hd_ = @head.dimension
1074
+ index_ < hd_ ? @head.get_units(index_) : @tail.get_units(index_ - hd_)
1075
+ end
1076
+
1077
+
1078
+ def _wkt_typename # :nodoc:
1079
+ "COMPD_CS"
1080
+ end
1081
+
1082
+ def _wkt_content(open_, close_) # :nodoc:
1083
+ [@head._to_wkt(open_, close_), @tail._to_wkt(open_, close_)]
1084
+ end
1085
+
1086
+
1087
+ class << self
1088
+
1089
+
1090
+ # Create a CompoundCoordinateSystem given two sub-coordinate
1091
+ # systems. You may also provide the optional parameters
1092
+ # specified by the Info interface.
1093
+
1094
+ def create(name_, head_, tail_, *optional_)
1095
+ new(name_, head_, tail_, *optional_)
1096
+ end
1097
+
1098
+
1099
+ end
1100
+
1101
+
1102
+ end
1103
+
1104
+
1105
+ # == OGC spec description
1106
+ #
1107
+ # A local coordinate system, with uncertain relationship to the
1108
+ # world. In general, a local coordinate system cannot be related to
1109
+ # other coordinate systems. However, if two objects supporting this
1110
+ # interface have the same dimension, axes, units and datum then
1111
+ # client code is permitted to assume that the two coordinate systems
1112
+ # are identical. This allows several datasets from a common source
1113
+ # (e.g. a CAD system) to be overlaid. In addition, some
1114
+ # implementations of the Coordinate Transformation (CT) package may
1115
+ # have a mechanism for correlating local datums. (E.g. from a
1116
+ # database of transformations, which is created and maintained from
1117
+ # real-world measurements.)
1118
+ #
1119
+ # == Notes
1120
+ #
1121
+ # RGeo's implementation does not provide the Coordinate
1122
+ # Transformation (CT) package.
1123
+
1124
+ class LocalCoordinateSystem < CoordinateSystem
1125
+
1126
+ def initialize(name_, local_datum_, unit_, axes_, *optional_) # :nodoc:
1127
+ super(name_, axes_.size, *optional_)
1128
+ @local_datum = local_datum_
1129
+ @unit = unit_
1130
+ @axes = axes_.dup
1131
+ end
1132
+
1133
+
1134
+ # Gets the local datum.
1135
+ attr_reader :local_datum
1136
+
1137
+
1138
+ # Implements CoordinateSystem#get_axis
1139
+
1140
+ def get_axis(index_)
1141
+ @axes[index_]
1142
+ end
1143
+
1144
+
1145
+ # Implements CoordinateSystem#get_units
1146
+
1147
+ def get_units(index_)
1148
+ @unit
1149
+ end
1150
+
1151
+
1152
+ def _wkt_typename # :nodoc:
1153
+ "LOCAL_CS"
1154
+ end
1155
+
1156
+ def _wkt_content(open_, close_) # :nodoc:
1157
+ [@local_datum._to_wkt(open_, close_), @unit._to_wkt(open_, close_)] + @axes.map{ |ax_| ax_._to_wkt(open_, close_) }
1158
+ end
1159
+
1160
+
1161
+ class << self
1162
+
1163
+
1164
+ # Create a LocalCoordinateSystem given a name, a LocalDatum, a
1165
+ # Unit, and an array of at least one AxisInfo. You may also
1166
+ # provide the optional parameters specified by the Info
1167
+ # interface.
1168
+
1169
+ def create(name_, local_datum_, unit_, axes_, *optional_)
1170
+ new(name_, local_datum_, unit_, axes_, *optional_)
1171
+ end
1172
+
1173
+
1174
+ end
1175
+
1176
+ end
1177
+
1178
+
1179
+ # == OGC spec description
1180
+ #
1181
+ # A 3D coordinate system, with its origin at the centre of the
1182
+ # Earth. The X axis points towards the prime meridian. The Y axis
1183
+ # points East or West. The Z axis points North or South. By default
1184
+ # the Z axis will point North, and the Y axis will point East (e.g.
1185
+ # a right handed system), but you should check the axes for
1186
+ # non-default values.
1187
+
1188
+ class GeocentricCoordinateSystem < CoordinateSystem
1189
+
1190
+ def initialize(name_, horizontal_datum_, prime_meridian_, linear_unit_, axis0_, axis1_, axis2_, *optional_) # :nodoc:
1191
+ super(name_, 3, *optional_)
1192
+ @horizontal_datum = horizontal_datum_
1193
+ @prime_meridian = prime_meridian_
1194
+ @linear_unit = linear_unit_
1195
+ @axis0 = axis0_
1196
+ @axis1 = axis1_
1197
+ @axis2 = axis2_
1198
+ end
1199
+
1200
+
1201
+ # Returns the HorizontalDatum. The horizontal datum is used to
1202
+ # determine where the centre of the Earth is considered to be.
1203
+ # All coordinate points will be measured from the centre of the
1204
+ # Earth, and not the surface.
1205
+ attr_reader :horizontal_datum
1206
+
1207
+ # Returns the PrimeMeridian.
1208
+ attr_reader :prime_meridian
1209
+
1210
+ # Gets the units used along all the axes.
1211
+ attr_reader :linear_unit
1212
+
1213
+
1214
+ # Implements CoordinateSystem#get_units
1215
+
1216
+ def get_units(index_)
1217
+ @linear_unit
1218
+ end
1219
+
1220
+
1221
+ # Implements CoordinateSystem#get_axis
1222
+
1223
+ def get_axis(index_)
1224
+ [@axis0, @axis1, @axis2][index_]
1225
+ end
1226
+
1227
+
1228
+ def _wkt_typename # :nodoc:
1229
+ "GEOCCS"
1230
+ end
1231
+
1232
+ def _wkt_content(open_, close_) # :nodoc:
1233
+ arr_ = [@horizontal_datum._to_wkt(open_, close_), @prime_meridian._to_wkt(open_, close_), @linear_unit._to_wkt(open_, close_)]
1234
+ arr_ << @axis0._to_wkt(open_, close_) if @axis0
1235
+ arr_ << @axis1._to_wkt(open_, close_) if @axis1
1236
+ arr_ << @axis2._to_wkt(open_, close_) if @axis2
1237
+ arr_
1238
+ end
1239
+
1240
+
1241
+ class << self
1242
+
1243
+
1244
+ # Create a GeocentricCoordinateSystem given a name, a
1245
+ # HorizontalDatum, a PrimeMeridian, a LinearUnit, and three
1246
+ # AxisInfo objects. The AxisInfo are optional and may be nil.
1247
+ # You may also provide the optional parameters specified by the
1248
+ # Info interface.
1249
+
1250
+ def create(name_, horizontal_datum_, prime_meridian_, linear_unit_, axis0_, axis1_, axis2_, *optional_)
1251
+ new(name_, horizontal_datum_, prime_meridian_, linear_unit_, axis0_, axis1_, axis2_, *optional_)
1252
+ end
1253
+
1254
+
1255
+ end
1256
+
1257
+
1258
+ end
1259
+
1260
+
1261
+ # == OGC spec description
1262
+ #
1263
+ # A one-dimensional coordinate system suitable for vertical
1264
+ # measurements.
1265
+
1266
+ class VerticalCoordinateSystem < CoordinateSystem
1267
+
1268
+ def initialize(name_, vertical_datum_, vertical_unit_, axis_, *optional_) # :nodoc:
1269
+ super(name_, 1, *optional_)
1270
+ @vertical_datum = vertical_datum_
1271
+ @vertical_unit = vertical_unit_
1272
+ @axis = axis_
1273
+ end
1274
+
1275
+
1276
+ # Gets the vertical datum, which indicates the measurement method.
1277
+ attr_reader :vertical_datum
1278
+
1279
+ # Gets the units used along the vertical axis. The vertical units
1280
+ # must be the same as the CS_CoordinateSystem units.
1281
+ attr_reader :vertical_unit
1282
+
1283
+
1284
+ # Implements CoordinateSystem#get_units
1285
+
1286
+ def get_units(index_)
1287
+ @vertical_unit
1288
+ end
1289
+
1290
+
1291
+ # Implements CoordinateSystem#get_axis
1292
+
1293
+ def get_axis(index_)
1294
+ @axis
1295
+ end
1296
+
1297
+
1298
+ def _wkt_typename # :nodoc:
1299
+ "VERT_CS"
1300
+ end
1301
+
1302
+ def _wkt_content(open_, close_) # :nodoc:
1303
+ arr_ = [@vertical_datum._to_wkt(open_, close_), @vertical_unit._to_wkt(open_, close_)]
1304
+ arr_ << @axis._to_wkt(open_, close_) if @axis
1305
+ arr_
1306
+ end
1307
+
1308
+
1309
+ class << self
1310
+
1311
+
1312
+ # Create a VerticalCoordinateSystem given a name, a
1313
+ # VerticalDatum, a LinearUnit, and an AxisInfo. The AxisInfo is
1314
+ # optional and may be nil. You may also provide the optional
1315
+ # parameters specified by the Info interface.
1316
+
1317
+ def create(name_, vertical_datum_, vertical_unit_, axis_, *optional_)
1318
+ new(name_, vertical_datum_, vertical_unit_, axis_, *optional_)
1319
+ end
1320
+
1321
+
1322
+ end
1323
+
1324
+
1325
+ end
1326
+
1327
+
1328
+ # == OGC spec description
1329
+ #
1330
+ # A 2D coordinate system suitable for positions on the Earth's surface.
1331
+ #
1332
+ # == Notes
1333
+ #
1334
+ # This is a non-instantiable abstract class. You must instantiate
1335
+ # one of the subclasses GeographicCoordinateSystem or
1336
+ # ProjectedCoordinateSystem.
1337
+
1338
+ class HorizontalCoordinateSystem < CoordinateSystem
1339
+
1340
+ def initialize(name_, horizontal_datum_, *optional_) # :nodoc:
1341
+ super(name_, 2, *optional_)
1342
+ @horizontal_datum = horizontal_datum_
1343
+ end
1344
+
1345
+
1346
+ # Returns the HorizontalDatum.
1347
+ attr_reader :horizontal_datum
1348
+
1349
+
1350
+ end
1351
+
1352
+
1353
+ # == OGC spec description
1354
+ #
1355
+ # A coordinate system based on latitude and longitude. Some
1356
+ # geographic coordinate systems are Lat/Lon, and some are Lon/Lat.
1357
+ # You can find out which this is by examining the axes. You should
1358
+ # also check the angular units, since not all geographic coordinate
1359
+ # systems use degrees.
1360
+
1361
+ class GeographicCoordinateSystem < HorizontalCoordinateSystem
1362
+
1363
+ def initialize(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_, *optional_) # :nodoc:
1364
+ super(name_, horizontal_datum_, *optional_)
1365
+ @prime_meridian = prime_meridian_
1366
+ @angular_unit = angular_unit_
1367
+ @axis0 = axis0_
1368
+ @axis1 = axis1_
1369
+ end
1370
+
1371
+
1372
+ # Returns the PrimeMeridian.
1373
+ attr_reader :prime_meridian
1374
+
1375
+ # Returns the AngularUnit. The angular unit must be the same as
1376
+ # the CS_CoordinateSystem units.
1377
+ attr_reader :angular_unit
1378
+
1379
+
1380
+ # Implements CoordinateSystem#get_units
1381
+
1382
+ def get_units(index_)
1383
+ @angular_unit
1384
+ end
1385
+
1386
+
1387
+ # Implements CoordinateSystem#get_axis
1388
+
1389
+ def get_axis(index_)
1390
+ index_ == 1 ? @axis1 : @axis0
1391
+ end
1392
+
1393
+
1394
+ # Gets the number of available conversions to WGS84 coordinates.
1395
+
1396
+ def num_conversion_to_wgs84
1397
+ @horizontal_datum.wgs84_parameters ? 1 : 0
1398
+ end
1399
+
1400
+
1401
+ # Gets details on a conversion to WGS84. Some geographic
1402
+ # coordinate systems provide several transformations into WGS84,
1403
+ # which are designed to provide good accuracy in different areas
1404
+ # of interest. The first conversion (with index=0) should provide
1405
+ # acceptable accuracy over the largest possible area of interest.
1406
+
1407
+ def get_wgs84_conversion_info(index_)
1408
+ @horizontal_datum.wgs84_parameters
1409
+ end
1410
+
1411
+
1412
+ def _wkt_typename # :nodoc:
1413
+ "GEOGCS"
1414
+ end
1415
+
1416
+ def _wkt_content(open_, close_) # :nodoc:
1417
+ arr_ = [@horizontal_datum._to_wkt(open_, close_), @prime_meridian._to_wkt(open_, close_), @angular_unit._to_wkt(open_, close_)]
1418
+ arr_ << @axis0._to_wkt(open_, close_) if @axis0
1419
+ arr_ << @axis1._to_wkt(open_, close_) if @axis1
1420
+ arr_
1421
+ end
1422
+
1423
+
1424
+ class << self
1425
+
1426
+
1427
+ # Create a GeographicCoordinateSystem, given a name, an
1428
+ # AngularUnit, a HorizontalDatum, a PrimeMeridian, and two
1429
+ # AxisInfo objects. The AxisInfo objects are optional and may
1430
+ # be set to nil. You may also provide the optional parameters
1431
+ # specified by the Info interface.
1432
+
1433
+ def create(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_, *optional_)
1434
+ new(name_, angular_unit_, horizontal_datum_, prime_meridian_, axis0_, axis1_, *optional_)
1435
+ end
1436
+
1437
+
1438
+ end
1439
+
1440
+
1441
+ end
1442
+
1443
+
1444
+ # == OGC spec description
1445
+ #
1446
+ # A 2D cartographic coordinate system.
1447
+
1448
+ class ProjectedCoordinateSystem < HorizontalCoordinateSystem
1449
+
1450
+ def initialize(name_, geographic_coordinate_system_, projection_, linear_unit_, axis0_, axis1_, *optional_) # :nodoc:
1451
+ super(name_, geographic_coordinate_system_.horizontal_datum, *optional_)
1452
+ @geographic_coordinate_system = geographic_coordinate_system_
1453
+ @projection = projection_
1454
+ @linear_unit = linear_unit_
1455
+ @axis0 = axis0_
1456
+ @axis1 = axis1_
1457
+ end
1458
+
1459
+
1460
+ # Returns the GeographicCoordinateSystem.
1461
+ attr_reader :geographic_coordinate_system
1462
+
1463
+ # Gets the projection.
1464
+ attr_reader :projection
1465
+
1466
+ # Returns the LinearUnits. The linear unit must be the same as
1467
+ # the CS_CoordinateSystem units.
1468
+ attr_reader :linear_unit
1469
+
1470
+
1471
+ # Implements CoordinateSystem#get_units
1472
+
1473
+ def get_units(index_)
1474
+ @linear_unit
1475
+ end
1476
+
1477
+
1478
+ # Implements CoordinateSystem#get_axis
1479
+
1480
+ def get_axis(index_)
1481
+ index_ == 1 ? @axis1 : @axis0
1482
+ end
1483
+
1484
+
1485
+ def _wkt_typename # :nodoc:
1486
+ "PROJCS"
1487
+ end
1488
+
1489
+ def _wkt_content(open_, close_) # :nodoc:
1490
+ arr_ = [@geographic_coordinate_system._to_wkt(open_, close_), @projection._to_wkt(open_, close_)]
1491
+ @projection.each_parameter{ |param_| arr_ << param_._to_wkt(open_, close_) }
1492
+ arr_ << @linear_unit._to_wkt(open_, close_)
1493
+ arr_ << @axis0._to_wkt(open_, close_) if @axis0
1494
+ arr_ << @axis1._to_wkt(open_, close_) if @axis1
1495
+ arr_
1496
+ end
1497
+
1498
+
1499
+ class << self
1500
+
1501
+
1502
+ # Create a ProjectedCoordinateSystem given a name, a
1503
+ # GeographicCoordinateSystem, and Projection, a LinearUnit, and
1504
+ # two AxisInfo objects. The AxisInfo objects are optional and
1505
+ # may be set to nil. You may also provide the optional
1506
+ # parameters specified by the Info interface.
1507
+
1508
+ def create(name_, geographic_coordinate_system_, projection_, linear_unit_, axis0_, axis1_, *optional_)
1509
+ new(name_, geographic_coordinate_system_, projection_, linear_unit_, axis0_, axis1_, *optional_)
1510
+ end
1511
+
1512
+
1513
+ end
1514
+
1515
+
1516
+ end
1517
+
1518
+
1519
+ end
1520
+
1521
+
1522
+ end
1523
+
1524
+ end