schleyfox-rgeo 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. data/History.rdoc +199 -0
  2. data/README.rdoc +172 -0
  3. data/Spatial_Programming_With_RGeo.rdoc +440 -0
  4. data/Version +1 -0
  5. data/ext/geos_c_impl/extconf.rb +84 -0
  6. data/ext/geos_c_impl/factory.c +468 -0
  7. data/ext/geos_c_impl/factory.h +224 -0
  8. data/ext/geos_c_impl/geometry.c +705 -0
  9. data/ext/geos_c_impl/geometry.h +55 -0
  10. data/ext/geos_c_impl/geometry_collection.c +482 -0
  11. data/ext/geos_c_impl/geometry_collection.h +69 -0
  12. data/ext/geos_c_impl/line_string.c +509 -0
  13. data/ext/geos_c_impl/line_string.h +64 -0
  14. data/ext/geos_c_impl/main.c +70 -0
  15. data/ext/geos_c_impl/point.c +193 -0
  16. data/ext/geos_c_impl/point.h +62 -0
  17. data/ext/geos_c_impl/polygon.c +265 -0
  18. data/ext/geos_c_impl/polygon.h +66 -0
  19. data/ext/geos_c_impl/preface.h +50 -0
  20. data/ext/proj4_c_impl/extconf.rb +88 -0
  21. data/ext/proj4_c_impl/main.c +271 -0
  22. data/lib/rgeo.rb +124 -0
  23. data/lib/rgeo/cartesian.rb +60 -0
  24. data/lib/rgeo/cartesian/analysis.rb +118 -0
  25. data/lib/rgeo/cartesian/bounding_box.rb +337 -0
  26. data/lib/rgeo/cartesian/calculations.rb +161 -0
  27. data/lib/rgeo/cartesian/factory.rb +209 -0
  28. data/lib/rgeo/cartesian/feature_classes.rb +173 -0
  29. data/lib/rgeo/cartesian/feature_methods.rb +106 -0
  30. data/lib/rgeo/cartesian/interface.rb +150 -0
  31. data/lib/rgeo/coord_sys.rb +79 -0
  32. data/lib/rgeo/coord_sys/cs/entities.rb +1524 -0
  33. data/lib/rgeo/coord_sys/cs/factories.rb +208 -0
  34. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +308 -0
  35. data/lib/rgeo/coord_sys/proj4.rb +312 -0
  36. data/lib/rgeo/coord_sys/srs_database/active_record_table.rb +194 -0
  37. data/lib/rgeo/coord_sys/srs_database/interface.rb +165 -0
  38. data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +188 -0
  39. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +108 -0
  40. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +108 -0
  41. data/lib/rgeo/error.rb +63 -0
  42. data/lib/rgeo/feature.rb +88 -0
  43. data/lib/rgeo/feature/curve.rb +156 -0
  44. data/lib/rgeo/feature/factory.rb +332 -0
  45. data/lib/rgeo/feature/factory_generator.rb +138 -0
  46. data/lib/rgeo/feature/geometry.rb +614 -0
  47. data/lib/rgeo/feature/geometry_collection.rb +129 -0
  48. data/lib/rgeo/feature/line.rb +66 -0
  49. data/lib/rgeo/feature/line_string.rb +102 -0
  50. data/lib/rgeo/feature/linear_ring.rb +66 -0
  51. data/lib/rgeo/feature/multi_curve.rb +113 -0
  52. data/lib/rgeo/feature/multi_line_string.rb +66 -0
  53. data/lib/rgeo/feature/multi_point.rb +73 -0
  54. data/lib/rgeo/feature/multi_polygon.rb +97 -0
  55. data/lib/rgeo/feature/multi_surface.rb +116 -0
  56. data/lib/rgeo/feature/point.rb +120 -0
  57. data/lib/rgeo/feature/polygon.rb +141 -0
  58. data/lib/rgeo/feature/surface.rb +122 -0
  59. data/lib/rgeo/feature/types.rb +305 -0
  60. data/lib/rgeo/geographic.rb +75 -0
  61. data/lib/rgeo/geographic/factory.rb +287 -0
  62. data/lib/rgeo/geographic/interface.rb +410 -0
  63. data/lib/rgeo/geographic/proj4_projector.rb +98 -0
  64. data/lib/rgeo/geographic/projected_feature_classes.rb +213 -0
  65. data/lib/rgeo/geographic/projected_feature_methods.rb +228 -0
  66. data/lib/rgeo/geographic/projected_window.rb +467 -0
  67. data/lib/rgeo/geographic/simple_mercator_projector.rb +157 -0
  68. data/lib/rgeo/geographic/spherical_feature_classes.rb +212 -0
  69. data/lib/rgeo/geographic/spherical_feature_methods.rb +97 -0
  70. data/lib/rgeo/geographic/spherical_math.rb +206 -0
  71. data/lib/rgeo/geos.rb +72 -0
  72. data/lib/rgeo/geos/factory.rb +301 -0
  73. data/lib/rgeo/geos/impl_additions.rb +76 -0
  74. data/lib/rgeo/geos/interface.rb +139 -0
  75. data/lib/rgeo/geos/zm_factory.rb +275 -0
  76. data/lib/rgeo/geos/zm_impl.rb +432 -0
  77. data/lib/rgeo/impl_helper.rb +53 -0
  78. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +235 -0
  79. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +85 -0
  80. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +197 -0
  81. data/lib/rgeo/impl_helper/basic_point_methods.rb +138 -0
  82. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +121 -0
  83. data/lib/rgeo/impl_helper/math.rb +50 -0
  84. data/lib/rgeo/version.rb +52 -0
  85. data/lib/rgeo/wkrep.rb +72 -0
  86. data/lib/rgeo/wkrep/wkb_generator.rb +267 -0
  87. data/lib/rgeo/wkrep/wkb_parser.rb +315 -0
  88. data/lib/rgeo/wkrep/wkt_generator.rb +275 -0
  89. data/lib/rgeo/wkrep/wkt_parser.rb +496 -0
  90. data/test/common/geometry_collection_tests.rb +238 -0
  91. data/test/common/line_string_tests.rb +324 -0
  92. data/test/common/multi_line_string_tests.rb +209 -0
  93. data/test/common/multi_point_tests.rb +201 -0
  94. data/test/common/multi_polygon_tests.rb +208 -0
  95. data/test/common/point_tests.rb +331 -0
  96. data/test/common/polygon_tests.rb +232 -0
  97. data/test/coord_sys/tc_active_record_table.rb +102 -0
  98. data/test/coord_sys/tc_ogc_cs.rb +356 -0
  99. data/test/coord_sys/tc_proj4.rb +138 -0
  100. data/test/coord_sys/tc_proj4_srs_data.rb +76 -0
  101. data/test/coord_sys/tc_sr_org.rb +70 -0
  102. data/test/coord_sys/tc_url_reader.rb +82 -0
  103. data/test/geos/tc_factory.rb +91 -0
  104. data/test/geos/tc_geometry_collection.rb +62 -0
  105. data/test/geos/tc_line_string.rb +62 -0
  106. data/test/geos/tc_misc.rb +72 -0
  107. data/test/geos/tc_multi_line_string.rb +62 -0
  108. data/test/geos/tc_multi_point.rb +62 -0
  109. data/test/geos/tc_multi_polygon.rb +63 -0
  110. data/test/geos/tc_point.rb +86 -0
  111. data/test/geos/tc_polygon.rb +86 -0
  112. data/test/geos/tc_zmfactory.rb +85 -0
  113. data/test/projected_geographic/tc_geometry_collection.rb +62 -0
  114. data/test/projected_geographic/tc_line_string.rb +62 -0
  115. data/test/projected_geographic/tc_multi_line_string.rb +62 -0
  116. data/test/projected_geographic/tc_multi_point.rb +62 -0
  117. data/test/projected_geographic/tc_multi_polygon.rb +63 -0
  118. data/test/projected_geographic/tc_point.rb +93 -0
  119. data/test/projected_geographic/tc_polygon.rb +62 -0
  120. data/test/simple_cartesian/tc_calculations.rb +145 -0
  121. data/test/simple_cartesian/tc_geometry_collection.rb +69 -0
  122. data/test/simple_cartesian/tc_line_string.rb +70 -0
  123. data/test/simple_cartesian/tc_multi_line_string.rb +67 -0
  124. data/test/simple_cartesian/tc_multi_point.rb +67 -0
  125. data/test/simple_cartesian/tc_multi_polygon.rb +70 -0
  126. data/test/simple_cartesian/tc_point.rb +91 -0
  127. data/test/simple_cartesian/tc_polygon.rb +67 -0
  128. data/test/simple_mercator/tc_geometry_collection.rb +62 -0
  129. data/test/simple_mercator/tc_line_string.rb +62 -0
  130. data/test/simple_mercator/tc_multi_line_string.rb +62 -0
  131. data/test/simple_mercator/tc_multi_point.rb +62 -0
  132. data/test/simple_mercator/tc_multi_polygon.rb +63 -0
  133. data/test/simple_mercator/tc_point.rb +93 -0
  134. data/test/simple_mercator/tc_polygon.rb +62 -0
  135. data/test/simple_mercator/tc_window.rb +219 -0
  136. data/test/spherical_geographic/tc_calculations.rb +203 -0
  137. data/test/spherical_geographic/tc_geometry_collection.rb +70 -0
  138. data/test/spherical_geographic/tc_line_string.rb +70 -0
  139. data/test/spherical_geographic/tc_multi_line_string.rb +67 -0
  140. data/test/spherical_geographic/tc_multi_point.rb +67 -0
  141. data/test/spherical_geographic/tc_multi_polygon.rb +70 -0
  142. data/test/spherical_geographic/tc_point.rb +100 -0
  143. data/test/spherical_geographic/tc_polygon.rb +67 -0
  144. data/test/tc_cartesian_analysis.rb +107 -0
  145. data/test/tc_oneoff.rb +63 -0
  146. data/test/wkrep/tc_wkb_generator.rb +249 -0
  147. data/test/wkrep/tc_wkb_parser.rb +353 -0
  148. data/test/wkrep/tc_wkt_generator.rb +362 -0
  149. data/test/wkrep/tc_wkt_parser.rb +480 -0
  150. metadata +267 -0
@@ -0,0 +1,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