proj4rb 1.0.0 → 2.0.0

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 (87) hide show
  1. checksums.yaml +5 -5
  2. data/ChangeLog +46 -0
  3. data/Gemfile +4 -0
  4. data/README.rdoc +158 -148
  5. data/Rakefile +26 -41
  6. data/lib/area.rb +32 -0
  7. data/lib/config.rb +70 -0
  8. data/lib/context.rb +103 -0
  9. data/lib/coordinate.rb +197 -0
  10. data/lib/crs.rb +206 -0
  11. data/lib/ellipsoid.rb +42 -0
  12. data/lib/error.rb +18 -0
  13. data/lib/operation.rb +43 -0
  14. data/lib/pj_object.rb +82 -0
  15. data/lib/point.rb +72 -0
  16. data/lib/prime_meridian.rb +40 -0
  17. data/lib/proj.rb +31 -0
  18. data/lib/proj4.rb +3 -469
  19. data/lib/projection.rb +207 -0
  20. data/lib/transformation.rb +61 -0
  21. data/lib/unit.rb +54 -0
  22. data/proj4rb.gemspec +31 -0
  23. data/test/abstract_test.rb +7 -0
  24. data/test/context_test.rb +82 -0
  25. data/test/coordinate_test.rb +35 -0
  26. data/test/crs_test.rb +373 -0
  27. data/test/ellipsoid_test.rb +34 -0
  28. data/test/operation_test.rb +29 -0
  29. data/test/prime_meridians_test.rb +33 -0
  30. data/test/proj_test.rb +17 -0
  31. data/test/projection_test.rb +224 -0
  32. data/test/transformation_test.rb +68 -0
  33. data/test/unit_test.rb +47 -0
  34. metadata +82 -77
  35. data/data/GL27 +0 -22
  36. data/data/MD +0 -0
  37. data/data/TN +0 -0
  38. data/data/WI +0 -0
  39. data/data/WO +0 -0
  40. data/data/conus +0 -0
  41. data/data/epsg +0 -5443
  42. data/data/epsg-deprecated +0 -2
  43. data/data/esri +0 -5937
  44. data/data/esri.extra +0 -948
  45. data/data/hawaii +0 -0
  46. data/data/nad.lst +0 -142
  47. data/data/nad27 +0 -809
  48. data/data/nad83 +0 -744
  49. data/data/ntv1_can.dat +0 -0
  50. data/data/null +0 -0
  51. data/data/other.extra +0 -49
  52. data/data/proj_def.dat +0 -17
  53. data/data/prvi +0 -0
  54. data/data/stgeorge +0 -0
  55. data/data/stlrnc +0 -0
  56. data/data/stpaul +0 -0
  57. data/data/world +0 -212
  58. data/example/basic.rb +0 -18
  59. data/example/list-datums.rb +0 -17
  60. data/example/list-ellipsoids.rb +0 -17
  61. data/example/list-errors.rb +0 -11
  62. data/example/list-prime-meridians.rb +0 -17
  63. data/example/list-projection-types.rb +0 -17
  64. data/example/list-units.rb +0 -17
  65. data/example/version.rb +0 -8
  66. data/ext/Makefile +0 -238
  67. data/ext/extconf.rb +0 -16
  68. data/ext/mkmf.log +0 -103
  69. data/ext/out.log +0 -0
  70. data/ext/proj4_ruby-x64-mingw32.def +0 -2
  71. data/ext/proj4_ruby.so +0 -0
  72. data/ext/projrb.c +0 -566
  73. data/ext/projrb.o +0 -0
  74. data/ext/vc/proj4_ruby.sln +0 -19
  75. data/ext/vc/proj4_ruby.vcproj +0 -208
  76. data/test/test_constants.rb +0 -18
  77. data/test/test_create_projection.rb +0 -63
  78. data/test/test_datums.rb +0 -45
  79. data/test/test_ellipsoids.rb +0 -46
  80. data/test/test_errors.rb +0 -66
  81. data/test/test_init_projection.rb +0 -109
  82. data/test/test_prime_meridians.rb +0 -45
  83. data/test/test_projection_type.rb +0 -44
  84. data/test/test_simple_projection.rb +0 -58
  85. data/test/test_suite.rb +0 -14
  86. data/test/test_transform.rb +0 -115
  87. data/test/test_units.rb +0 -46
@@ -0,0 +1,32 @@
1
+ module Proj
2
+ class Area
3
+ attr_reader :name, :west_lon_degree, :south_lat_degree, :east_lon_degree, :north_lat_degree
4
+
5
+ def self.for_object(pj_object)
6
+ p_name = FFI::MemoryPointer.new(:pointer)
7
+ p_west_lon_degree = FFI::MemoryPointer.new(:double)
8
+ p_south_lat_degree = FFI::MemoryPointer.new(:double)
9
+ p_east_lon_degree = FFI::MemoryPointer.new(:double)
10
+ p_north_lat_degree = FFI::MemoryPointer.new(:double)
11
+
12
+ result = Api.proj_get_area_of_use(Context.current, pj_object,
13
+ p_west_lon_degree, p_south_lat_degree, p_east_lon_degree, p_north_lat_degree,
14
+ p_name)
15
+ unless result
16
+ Error.check
17
+ end
18
+
19
+ name = p_name.read_pointer.read_string_to_null.force_encoding('utf-8')
20
+ self.new(name,
21
+ p_west_lon_degree.read_double, p_south_lat_degree.read_double, p_east_lon_degree.read_double, p_north_lat_degree.read_double)
22
+ end
23
+
24
+ def initialize(name, west_lon_degree, south_lat_degree, east_lon_degree, north_lat_degree)
25
+ @name = name
26
+ @west_lon_degree = west_lon_degree
27
+ @south_lat_degree = south_lat_degree
28
+ @east_lon_degree = east_lon_degree
29
+ @north_lat_degree = north_lat_degree
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,70 @@
1
+ require 'singleton'
2
+
3
+ module Proj
4
+ class Config
5
+ include Singleton
6
+
7
+ def set_search_paths
8
+ p_paths = self.search_paths_pointer
9
+ items = p_paths.type_size/p_paths.size
10
+
11
+ # Set search paths on default context - any new contexts will inherit from this
12
+ if Api.method_defined?(:proj_context_set_search_paths)
13
+ Api.proj_context_set_search_paths(nil, items, p_paths)
14
+ end
15
+
16
+ if Api.method_defined?(:pj_set_searchpath)
17
+ Api.pj_set_searchpath(items, p_paths)
18
+ end
19
+ end
20
+
21
+ def search_paths
22
+ ['/usr/share/proj',
23
+ '/usr/local/share/proj',
24
+ '/opt/share/proj',
25
+ '/opt/local/share/proj',
26
+ 'c:/msys64/mingw64/share/proj',
27
+ 'c:/mingw64/share/proj',
28
+ '/opt/local/lib/proj6/share/proj',
29
+ '/opt/local/lib/proj5/share/proj',
30
+ '/opt/local/lib/proj49/share/proj']
31
+ end
32
+
33
+ def data_path
34
+ if ENV['PROJ_LIB'] && File.directory?(ENV['PROJ_LIB'])
35
+ ENV['PROJ_LIB']
36
+ else
37
+ result = self.search_paths.detect do |path|
38
+ File.directory?(path)
39
+ end
40
+
41
+ unless result
42
+ raise(Error, "Could not find Proj data directory. Please set the PROJ_LIB environmental variable to correct directory")
43
+ end
44
+
45
+ result
46
+ end
47
+ end
48
+
49
+ def search_paths_pointer
50
+ p_path = FFI::MemoryPointer.from_string(self.data_path)
51
+ p_paths = FFI::MemoryPointer.new(:pointer, 1)
52
+ p_paths[0].write_pointer(p_path)
53
+ p_paths
54
+ end
55
+
56
+ def db_path
57
+ result = self.search_paths.map do |path|
58
+ File.join(path, 'proj.db')
59
+ end.detect do |path|
60
+ File.exists?(path)
61
+ end
62
+
63
+ unless result
64
+ raise(Error, "Could not find Proj database (proj.db). Please set the PROJ_LIB environmental variable to directory that contains it")
65
+ end
66
+
67
+ result
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,103 @@
1
+ module Proj
2
+ # Proj 4.8 introduced the concept of a thread context object to support multi-threaded programs. The bindings
3
+ # automatically create on context per thread (its stored in local thread storage).
4
+ class Context
5
+ # The context for the current thread
6
+ #
7
+ # @return [Context]
8
+ def self.current
9
+ Thread.current[:proj_context] ||= Context.new
10
+ end
11
+
12
+ def self.finalize(pointer)
13
+ proc do
14
+ Api.proj_context_destroy(pointer)
15
+ end
16
+ end
17
+
18
+ def initialize
19
+ @pointer = Api.proj_context_create
20
+ ObjectSpace.define_finalizer(self, self.class.finalize(@pointer))
21
+
22
+ set_database_path
23
+ end
24
+
25
+ # Helper method that tries to locate the Proj coordinate database (proj.db)
26
+ def set_database_path
27
+ return unless Api.method_defined?(:proj_context_get_database_path)
28
+ return if database_path
29
+
30
+ self.database_path = Config.instance.db_path
31
+ end
32
+
33
+ def to_ptr
34
+ @pointer
35
+ end
36
+
37
+ # Get the last error number
38
+ #
39
+ # return [Integer]
40
+ def errno
41
+ Api.proj_context_errno(self)
42
+ end
43
+
44
+ # Gets the path the Proj database
45
+ #
46
+ # return [String]
47
+ def database_path
48
+ Api.proj_context_get_database_path(self)
49
+ end
50
+
51
+ # Sets the path to the Proj database
52
+ def database_path=(value)
53
+ result = Api.proj_context_set_database_path(self, value, nil, nil)
54
+ unless result == 1
55
+ Error.check(self.errno)
56
+ end
57
+ end
58
+
59
+ # Sets a custom log function
60
+ #
61
+ # @example
62
+ # context.set_log_function(data) do |pointer, int, message|
63
+ # ... do stuff...
64
+ # end
65
+ #
66
+ # @param pointer [FFI::MemoryPointer] Optional pointer to custom data
67
+ # @param proc [Proc] Custom logging procedure
68
+ # @return [nil]
69
+ def set_log_function(pointer = nil, &proc)
70
+ Api.proj_log_func(self, pointer, proc)
71
+ end
72
+
73
+ # Gets the current log level
74
+ #
75
+ # @return [:PJ_LOG_LEVEL]
76
+ def log_level
77
+ Api.proj_log_level(self, :PJ_LOG_TELL)
78
+ end
79
+
80
+ # Sets the current log level
81
+ #
82
+ # @param value [:PJ_LOG_LEVEL]
83
+ # @return [nil]
84
+ def log_level=(value)
85
+ Api.proj_log_level(self, value)
86
+ end
87
+
88
+ # Gets if proj4 init rules are being used (i.e., support +init parameters)
89
+ #
90
+ # @return [Boolean]
91
+ def use_proj4_init_rules
92
+ Api.proj_context_get_use_proj4_init_rules(self, 0)
93
+ end
94
+
95
+ # Sets if proj4 init rules should be used
96
+ #
97
+ # @param value [Boolean]
98
+ # @return [nil]
99
+ def use_proj4_init_rules=(value)
100
+ Api.proj_context_use_proj4_init_rules(self, value ? 1 : 0)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,197 @@
1
+ # encoding: UTF-8
2
+
3
+ module Proj
4
+ # A four dimensional coordinate of double values.
5
+ #
6
+ # For most geographic Crses, the units will be in degrees.
7
+ class Coordinate
8
+ def self.from_coord(pj_coord)
9
+ result = self.allocate
10
+ result.instance_variable_set(:@coord, pj_coord)
11
+ result
12
+ end
13
+
14
+ # Creates a new coordinate.
15
+ #
16
+ # @example
17
+ #
18
+ # coord = Proj::Coordinate.new(:x => 1, :y => 2, :z => 3, :t => 4)
19
+ # coord = Proj::Coordinate.new(:u => 5, :v => 6, :w => 7, :t => 8)
20
+ # coord = Proj::Coordinate.new(:lam => 9, :phi => 10, :z => 11, :t => 12)
21
+ # coord = Proj::Coordinate.new(:s => 13, :a1 => 14, :a2 => 15)
22
+ # coord = Proj::Coordinate.new(:o => 16, :p => 17, :k => 18)
23
+ # coord = Proj::Coordinate.new(:e => 19, :n => 20, :u => 21)
24
+
25
+ def initialize(x: nil, y: nil, z: nil, t: nil,
26
+ u: nil, v: nil, w: nil, # t: nil
27
+ lam: nil, phi: nil, # z: nil, t: nil,
28
+ s: nil, a1: nil, a2: nil,
29
+ o: nil, p: nil, k: nil,
30
+ e: nil, n: nil) #u: nil
31
+
32
+ @coord = Api::PJ_COORD.new
33
+
34
+ keys = if x && y && z && t
35
+ [:x, :y, :z, :t]
36
+ elsif x && y && z
37
+ [:x, :y, :z]
38
+ elsif x && y
39
+ [:x, :y]
40
+ elsif u && v && w && t
41
+ [:u, :v, :w, :t]
42
+ elsif u && v && w
43
+ [:u, :v, :w]
44
+ elsif u && v
45
+ [:u, :v]
46
+ elsif lam && phi && z && t
47
+ [:lam, :phi, :z, :t]
48
+ elsif lam && phi && z
49
+ [:lam, :phi, :z]
50
+ elsif lam && phi
51
+ [:lam, :phi]
52
+ elsif s && a1 && a2
53
+ [:s, :a1, :a2]
54
+ elsif e && n && u
55
+ [:e, :n, :u]
56
+ elsif o && p && k
57
+ [:o, :p, :k]
58
+ end
59
+
60
+ coord_struct = @coord[:v]
61
+ keys.each_with_index do |key, index|
62
+ coord_struct[index] = binding.local_variable_get(key)
63
+ end
64
+ end
65
+
66
+ def to_ptr
67
+ @coord.to_ptr
68
+ end
69
+
70
+ # Returns x coordinate
71
+ #
72
+ # @return [Float]
73
+ def x
74
+ @coord[:v][0]
75
+ end
76
+
77
+ # Returns y coordinate
78
+ #
79
+ # @return [Float]
80
+ def y
81
+ @coord[:v][1]
82
+ end
83
+
84
+ # Returns z coordinate
85
+ #
86
+ # @return [Float]
87
+ def z
88
+ @coord[:v][2]
89
+ end
90
+
91
+ # Returns t coordinate
92
+ #
93
+ # @return [Float]
94
+ def t
95
+ @coord[:v][3]
96
+ end
97
+
98
+ # Returns u coordinate
99
+ #
100
+ # @return [Float]
101
+ # TODO - This could be u in uvw or enu. Going to ignore that
102
+ def u
103
+ @coord[:v][0]
104
+ end
105
+
106
+ # Returns v coordinate
107
+ #
108
+ # @return [Float]
109
+ def v
110
+ @coord[:v][1]
111
+ end
112
+
113
+ # Returns w coordinate
114
+ #
115
+ # @return [Float]
116
+ def w
117
+ @coord[:v][2]
118
+ end
119
+
120
+ # Returns lam coordinate
121
+ #
122
+ # @return [Float]
123
+ def lam
124
+ @coord[:v][0]
125
+ end
126
+
127
+ # Returns phi coordinate
128
+ #
129
+ # @return [Float]
130
+ def phi
131
+ @coord[:v][1]
132
+ end
133
+
134
+ # Returns o coordinate
135
+ #
136
+ # @return [Float]
137
+ def o
138
+ @coord[:v][0]
139
+ end
140
+
141
+ # Returns p coordinate
142
+ #
143
+ # @return [Float]
144
+ def p
145
+ @coord[:v][1]
146
+ end
147
+
148
+ # Returns k coordinate
149
+ #
150
+ # @return [Float]
151
+ def k
152
+ @coord[:v][3]
153
+ end
154
+
155
+ # Returns e coordinate
156
+ #
157
+ # @return [Float]
158
+ def e
159
+ @coord[:v][0]
160
+ end
161
+
162
+ # Returns n coordinate
163
+ #
164
+ # @return [Float]
165
+ def n
166
+ @coord[:v][1]
167
+ end
168
+
169
+ # Returns s coordinate
170
+ #
171
+ # @return [Float]
172
+ def s
173
+ @coord[:v][0]
174
+ end
175
+
176
+ # Returns a1 coordinate
177
+ #
178
+ # @return [Float]
179
+ def a1
180
+ @coord[:v][1]
181
+ end
182
+
183
+ # Returns a2 coordinate
184
+ #
185
+ # @return [Float]
186
+ def a2
187
+ @coord[:v][2]
188
+ end
189
+
190
+ # Returns nice printout of coordinate contents
191
+ #
192
+ # @return [String]
193
+ def to_s
194
+ "v0: #{self.x}, v1: #{self.y}, v2: #{self.z}, v3: #{self.t}"
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,206 @@
1
+ # encoding: UTF-8
2
+ require 'stringio'
3
+
4
+ module Proj
5
+ # Represents a coordinate reference system.
6
+ class Crs < PjObject
7
+ # To create a coordinate system, you can use CRS codes, well-known text (WKT) strings
8
+ # or old-style Proj4 strings (which are deprecated).
9
+ #
10
+ # @example
11
+ # crs1 = Proj::Crs.new('EPSG:4326')
12
+ # crs2 = Proj::Crs.new('urn:ogc:def:crs:EPSG::4326')
13
+ # crs3 = Proj::Crs.new('+proj=longlat +datum=WGS84 +no_defs +type=crs')
14
+ # crs4 = Proj::Crs.new(<<~EOS)
15
+ # GEOGCRS["WGS 84",
16
+ # DATUM["World Geodetic System 1984",
17
+ # ELLIPSOID["WGS 84",6378137,298.257223563,
18
+ # LENGTHUNIT["metre",1]]],
19
+ # PRIMEM["Greenwich",0,
20
+ # ANGLEUNIT["degree",0.0174532925199433]],
21
+ # CS[ellipsoidal,2],
22
+ # AXIS["geodetic latitude (Lat)",north,
23
+ # ORDER[1],
24
+ # ANGLEUNIT["degree",0.0174532925199433]],
25
+ # AXIS["geodetic longitude (Lon)",east,
26
+ # ORDER[2],
27
+ # ANGLEUNIT["degree",0.0174532925199433]],
28
+ # USAGE[
29
+ # SCOPE["unknown"],
30
+ # AREA["World"],
31
+ # BBOX[-90,-180,90,180]],
32
+ # ID["EPSG",4326]]
33
+ # EOS
34
+ #
35
+ # Notice when using the old-style Proj4 string, the addition of the "+type=crs" value.
36
+ #
37
+ # @param value [String]. See above
38
+ # @param context [Context]. An optional Context that the Crs will use for calculations.
39
+ def initialize(value, context=nil)
40
+ pointer = Api.proj_create(context || Context.current, value)
41
+
42
+ if pointer.null?
43
+ Error.check
44
+ end
45
+
46
+ super(pointer, context)
47
+
48
+ if Api.method_defined?(:proj_is_crs) && !Api.proj_is_crs(pointer)
49
+ raise(Error, "Invalid crs definition. Proj created an instance of: #{self.proj_type}.")
50
+ end
51
+ end
52
+
53
+ # Get the geodeticCRS / geographicCRS from a CRS.
54
+ #
55
+ # @return [Crs]
56
+ def geodetic_crs
57
+ PjObject.new(Api.proj_crs_get_geodetic_crs(self.context, self))
58
+ end
59
+
60
+ # Get a CRS component from a CompoundCRS.
61
+ #
62
+ # @return [Crs]
63
+ def sub_crs(index)
64
+ PjObject.new(Api.proj_crs_get_sub_crs(self.context, self, index))
65
+ end
66
+
67
+ # Returns the datum of a SingleCRS.
68
+ #
69
+ # @return [Crs]
70
+ def datum
71
+ PjObject.new(Api.proj_crs_get_datum(self.context, self))
72
+ end
73
+
74
+ # Get the horizontal datum from a CRS.
75
+ #
76
+ # @return [Crs]
77
+ def horizontal_datum
78
+ PjObject.new(Api.proj_crs_get_horizontal_datum(self.context, self))
79
+ end
80
+
81
+ # Returns the coordinate system of a SingleCRS.
82
+ #
83
+ # @return [Crs]
84
+ def coordinate_system
85
+ PjObject.new(Api.proj_crs_get_coordinate_system(self.context, self))
86
+ end
87
+
88
+ # Returns the number of axis of the coordinate system.
89
+ #
90
+ # @return [Integer]
91
+ def axis_count
92
+ foo = Api.proj_crs_get_coordinate_system(self.context, self)
93
+ result = Api.proj_cs_get_axis_count(self.context, self.coordinate_system)
94
+ if result == -1
95
+ Error.check
96
+ end
97
+ result
98
+ end
99
+
100
+ # Returns information on an axis.
101
+ #
102
+ # @return [Array<Hash>]
103
+ def axis_info
104
+ self.axis_count.times.map do |index|
105
+ p_name = FFI::MemoryPointer.new(:pointer)
106
+ p_abbreviation = FFI::MemoryPointer.new(:pointer)
107
+ p_direction = FFI::MemoryPointer.new(:pointer)
108
+ p_unit_conv_factor = FFI::MemoryPointer.new(:double)
109
+ p_unit_name = FFI::MemoryPointer.new(:pointer)
110
+ p_unit_auth_name = FFI::MemoryPointer.new(:pointer)
111
+ p_unit_code = FFI::MemoryPointer.new(:pointer)
112
+
113
+ result = Api.proj_cs_get_axis_info(self.context, self.coordinate_system, index,
114
+ p_name, p_abbreviation, p_direction, p_unit_conv_factor, p_unit_name, p_unit_auth_name, p_unit_code)
115
+
116
+ unless result
117
+ Error.check
118
+ end
119
+
120
+ {:name => p_name.read_pointer.read_string,
121
+ :abbreviation => p_abbreviation.read_pointer.read_string_to_null,
122
+ :direction => p_direction.read_pointer.read_string_to_null,
123
+ :unit_conv_factor => p_unit_conv_factor.read_double,
124
+ :unit_name => p_unit_name.read_pointer.read_string_to_null,
125
+ :unit_auth_name => p_unit_auth_name.read_pointer.read_string_to_null,
126
+ :unit_code => p_unit_code.read_pointer.read_string_to_null}
127
+ end
128
+ end
129
+
130
+ # Returns the type of the coordinate system.
131
+ #
132
+ # @return [:PJ_COORDINATE_SYSTEM_TYPE]
133
+ def crs_type
134
+ foo = Api.proj_crs_get_coordinate_system(self.context, self)
135
+ result = Api.proj_cs_get_type(self.context, self.coordinate_system)
136
+ if result == :PJ_CS_TYPE_UNKNOWN
137
+ Error.check
138
+ end
139
+ result
140
+ end
141
+
142
+ # Return the area of use of an object.
143
+ #
144
+ # @return [Area]
145
+ def area
146
+ @area ||= Area.for_object(self)
147
+ end
148
+
149
+ # Get the ellipsoid from a CRS or a GeodeticReferenceFrame.
150
+ #
151
+ # @return [PjObject]
152
+ def ellipsoid
153
+ PjObject.new(Api.proj_get_ellipsoid(self.context, self))
154
+ end
155
+
156
+ # Return the Conversion of a DerivedCRS (such as a ProjectedCRS), or the Transformation from
157
+ # the baseCRS to the hubCRS of a BoundCRS.
158
+ #
159
+ # @return [PjObject]
160
+ def operation
161
+ pointer = Api.proj_crs_get_coordoperation(self.context, self)
162
+ if pointer.null?
163
+ Error.check
164
+ end
165
+ PjObject.new(pointer)
166
+ end
167
+
168
+ # Get the prime meridian of a CRS or a GeodeticReferenceFrame.
169
+ #
170
+ # @return [PjObject]
171
+ def prime_meridian
172
+ PjObject.new(Api.proj_get_prime_meridian(self.context, self))
173
+ end
174
+
175
+ # A nicely printed out description
176
+ #
177
+ # @return [String]
178
+ def inspect
179
+ result = StringIO.new
180
+ result.set_encoding('UTF-8')
181
+ result << <<~EOS
182
+ <#{self.class.name}>: #{self.auth(0)}
183
+ #{self.description}
184
+ Axis Info [#{self.crs_type}]:
185
+ EOS
186
+
187
+ self.axis_info.each do |axis_info|
188
+ result << "- #{axis_info[:abbreviation]}[#{axis_info[:direction]}]: #{axis_info[:name]} (#{axis_info[:unit_name]})" << "\n"
189
+ end
190
+
191
+ result << <<~EOS
192
+ Area of Use:
193
+ - name: #{self.area.name}
194
+ - bounds: (#{self.area.west_lon_degree}, #{self.area.south_lat_degree}, #{self.area.east_lon_degree}, #{self.area.north_lat_degree})
195
+ Coordinate operation:
196
+ - name: ?
197
+ - method: ?
198
+ Datum: #{self.datum.name}
199
+ - Ellipsoid: #{self.ellipsoid.name}
200
+ - Prime Meridian: #{self.prime_meridian.name}
201
+ EOS
202
+
203
+ result.string
204
+ end
205
+ end
206
+ end