rgeo-proj4 3.1.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ #ifdef HAVE_PROJ_H
2
+ #ifdef HAVE_PROJ_CREATE
3
+ #ifdef HAVE_PROJ_CREATE_CRS_TO_CRS_FROM_PJ
4
+ #ifdef HAVE_PROJ_NORMALIZE_FOR_VISUALIZATION
5
+ #define RGEO_PROJ4_SUPPORTED
6
+ #endif
7
+ #endif
8
+ #endif
9
+ #endif
10
+
11
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
12
+ #define mark rb_gc_mark_movable
13
+ #else
14
+ #define mark rb_gc_mark
15
+ #endif
16
+
17
+ // When using ruby ALLOC* macros, we are using ruby_xmalloc, which counterpart
18
+ // is ruby_xfree. This macro helps enforcing that by showing us the way.
19
+ #define FREE ruby_xfree
20
+
21
+ #ifdef __cplusplus
22
+ #define RGEO_BEGIN_C extern "C" {
23
+ #define RGEO_END_C }
24
+ #else
25
+ #define RGEO_BEGIN_C
26
+ #define RGEO_END_C
27
+ #endif
@@ -6,25 +6,49 @@ module RGeo
6
6
  # This is a Ruby wrapper around a proj crs_to_crs
7
7
  # A crs_to_crs transformation object is a pipeline between two known coordinate reference systems.
8
8
  # https://proj.org/development/reference/functions.html#c.proj_create_crs_to_crs
9
- class CRSToCRS
10
- attr_writer :from, :to
9
+ #
10
+ # It also inherits from the RGeo::CoordSys::CoordinateTransform abstract class.
11
+ class CRSToCRS < CS::CoordinateTransform
12
+ attr_accessor :source_cs, :target_cs
11
13
 
12
14
  class << self
13
15
  def create(from, to)
14
16
  crs_to_crs = _create(from, to)
15
- crs_to_crs.from = from
16
- crs_to_crs.to = to
17
+ crs_to_crs.source_cs = from
18
+ crs_to_crs.target_cs = to
17
19
  crs_to_crs
18
20
  end
19
21
  end
22
+
23
+ alias from source_cs
24
+ alias to target_cs
25
+ alias to_wkt _as_text
26
+
27
+ def wkt_typename
28
+ wkt_str = to_wkt
29
+ wkt_str[0, wkt_str.index("[")]
30
+ end
31
+
32
+ def transform_type
33
+ PROJ_TYPES[_proj_type]
34
+ end
35
+
36
+ def area_of_use
37
+ _area_of_use
38
+ end
39
+
40
+ def identity?
41
+ _identity?(source_cs, target_cs)
42
+ end
43
+
20
44
  # transform the coordinates from the initial CRS to the destination CRS
21
45
  def transform_coords(x, y, z)
22
- if @from._radians? && @from._geographic?
46
+ if from._radians? && from._geographic?
23
47
  x *= ImplHelper::Math::DEGREES_PER_RADIAN
24
48
  y *= ImplHelper::Math::DEGREES_PER_RADIAN
25
49
  end
26
50
  result = _transform_coords(x, y, z)
27
- if result && @to._radians? && @to._geographic?
51
+ if result && to._radians? && to._geographic?
28
52
  result[0] *= ImplHelper::Math::RADIANS_PER_DEGREE
29
53
  result[1] *= ImplHelper::Math::RADIANS_PER_DEGREE
30
54
  end
@@ -79,6 +103,10 @@ module RGeo
79
103
  int_ = from_polygon_.interior_rings.map { |r_| transform_linear_ring(r_, to_factory_) }
80
104
  to_factory_.polygon(ext_, int_)
81
105
  end
106
+
107
+ def inspect
108
+ "#<#{self.class}:0x#{object_id.to_s(16)} @source_cs=#{source_cs.original_str} @target_cs=#{target_cs.original_str}>"
109
+ end
82
110
  end
83
111
 
84
112
  # Store of all the created CRSToCRS
@@ -19,7 +19,9 @@ module RGeo
19
19
  # option. You may also use this object directly to perform low-level
20
20
  # coordinate transformations.
21
21
 
22
- class Proj4
22
+ class Proj4 < CS::CoordinateSystem
23
+ attr_accessor :dimension
24
+
23
25
  def inspect # :nodoc:
24
26
  "#<#{self.class}:0x#{object_id.to_s(16)} #{canonical_str.inspect}>"
25
27
  end
@@ -110,6 +112,7 @@ module RGeo
110
112
  def as_text
111
113
  _as_text
112
114
  end
115
+ alias to_wkt as_text
113
116
 
114
117
  # Returns the string representing the authority and code of the
115
118
  # CRS if it exists, nil otherwise.
@@ -120,6 +123,18 @@ module RGeo
120
123
  _auth_name
121
124
  end
122
125
 
126
+ # Gets axis details for dimension within coordinate system. Each
127
+ # dimension in the coordinate system has a corresponding axis.
128
+ def get_axis(dimension)
129
+ _axis_and_unit_info(dimension).split(":")[0]
130
+ end
131
+
132
+ # Gets units for dimension within coordinate system. Each
133
+ # dimension in the coordinate system has corresponding units.
134
+ def get_units(dimension)
135
+ _axis_and_unit_info(dimension).split(":")[1]
136
+ end
137
+
123
138
  # Returns true if this Proj4 object is a geographic (lat-long)
124
139
  # coordinate system.
125
140
 
@@ -134,6 +149,13 @@ module RGeo
134
149
  _geocentric?
135
150
  end
136
151
 
152
+ # Returns true if this Proj4 object is a projected
153
+ # coordinate system
154
+
155
+ def projected?
156
+ _projected?
157
+ end
158
+
137
159
  # Returns true if this Proj4 object uses radians rather than degrees
138
160
  # if it is a geographic coordinate system.
139
161
 
@@ -148,6 +170,39 @@ module RGeo
148
170
  def get_geographic
149
171
  _get_geographic
150
172
  end
173
+ alias geographic_coordinate_system get_geographic
174
+
175
+ # Returns true if this Proj4 object represents a CRS.
176
+
177
+ def crs?
178
+ _crs?
179
+ end
180
+
181
+ # Sometimes used to assign SRIDs in factory creation
182
+ # Also in the base CS::Info class that CS::CoordinateSystem
183
+ # inherits from
184
+ #
185
+ # @return [Integer|NilClass] authority code if available
186
+ def authority_code
187
+ auth_name.split(":")[1].to_i if auth_name
188
+ end
189
+
190
+ # Low-level coordinate transform method.
191
+ # Transforms the given coordinate (x, y, [z]) from one proj4
192
+ # coordinate system to another. Returns an array with either two
193
+ # or three elements.
194
+ def transform_coords(to_proj, x, y, z = nil)
195
+ self.class.transform_coords(self, to_proj, x, y, z)
196
+ end
197
+
198
+ # Low-level geometry transform method.
199
+ # Transforms the given geometry between the given two projections.
200
+ # The resulting geometry is constructed using the to_factory.
201
+ # Any projections associated with the factories themselves are
202
+ # ignored.
203
+ def transform(from_geometry, to_proj, to_factory)
204
+ self.class.transform(self, from_geometry, to_proj, to_factory)
205
+ end
151
206
 
152
207
  class << self
153
208
  # Returns true if Proj4 is supported in this installation.
@@ -165,8 +220,9 @@ module RGeo
165
220
  end
166
221
 
167
222
  # Create a new Proj4 object, given a definition, which may be
168
- # either a string or a hash. Returns nil if the given definition
169
- # is invalid or Proj4 is not supported.
223
+ # either a string, hash, or integer. If an integer is given, it
224
+ # assumes that you are using the EPSG SRID that matches that code.
225
+ # Returns nil if the given definition is invalid or Proj4 is not supported.
170
226
  #
171
227
  # Recognized options include:
172
228
  #
@@ -188,11 +244,16 @@ module RGeo
188
244
  defn_ = defn_.map { |k_, v_| v_ ? "+#{k_}=#{v_}" : "+#{k_}" }.join(" ")
189
245
  end
190
246
 
247
+ defn_ = "EPSG:#{defn_}" if defn_.is_a?(Integer)
248
+
191
249
  result_ = _create(defn_, opts_[:radians])
192
- result_ = nil unless result_._valid?
250
+ raise RGeo::Error::InvalidProjection unless result_._valid?
251
+
252
+ result_.dimension = result_._axis_count
193
253
  end
194
254
  result_
195
255
  end
256
+ alias create_from_wkt create
196
257
 
197
258
  # Create a new Proj4 object, given a definition, which may be
198
259
  # either a string or a hash. Raises Error::UnsupportedOperation
@@ -221,9 +282,9 @@ module RGeo
221
282
  # Transforms the given coordinate (x, y, [z]) from one proj4
222
283
  # coordinate system to another. Returns an array with either two
223
284
  # or three elements.
224
- def transform_coords(from_proj_, to_proj_, x_, y_, z_ = nil)
225
- crs_to_crs = CRSStore.get(from_proj_, to_proj_)
226
- crs_to_crs.transform_coords(x_, y_, z_)
285
+ def transform_coords(from_proj, to_proj, x, y, z = nil)
286
+ crs_to_crs = CRSStore.get(from_proj, to_proj)
287
+ crs_to_crs.transform_coords(x, y, z)
227
288
  end
228
289
 
229
290
  # Low-level geometry transform method.
@@ -231,9 +292,9 @@ module RGeo
231
292
  # The resulting geometry is constructed using the to_factory.
232
293
  # Any projections associated with the factories themselves are
233
294
  # ignored.
234
- def transform(from_proj_, from_geometry_, to_proj_, to_factory_)
235
- crs_to_crs = CRSStore.get(from_proj_, to_proj_)
236
- crs_to_crs.transform(from_geometry_, to_factory_)
295
+ def transform(from_proj, from_geometry, to_proj, to_factory)
296
+ crs_to_crs = CRSStore.get(from_proj, to_proj)
297
+ crs_to_crs.transform(from_geometry, to_factory)
237
298
  end
238
299
  end
239
300
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RGeo
4
+ # All RGeo errors are members of this namespace.
5
+
6
+ module Error
7
+ # Base class for all RGeo-related exceptions
8
+ class RGeoError < RuntimeError
9
+ end
10
+
11
+ # RGeo error specific to the PROJ library
12
+ class InvalidProjection < RGeoError
13
+ end
14
+ end
15
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RGeo
4
4
  module Proj4
5
- VERSION = "3.1.1"
5
+ VERSION = "4.0.0"
6
6
  end
7
7
  end
data/lib/rgeo/proj4.rb CHANGED
@@ -2,7 +2,46 @@
2
2
 
3
3
  require "rgeo"
4
4
  require "rgeo/proj4/version"
5
+ require "rgeo/coord_sys/proj4_c_impl"
5
6
  require "rgeo/coord_sys/crs_to_crs"
6
7
  require "rgeo/coord_sys/proj4"
7
- require "rgeo/coord_sys/srs_database/proj4_data"
8
- require "rgeo/coord_sys/proj4_c_impl"
8
+ require_relative "./errors"
9
+
10
+ module RGeo
11
+ module CoordSys
12
+ # PROJ uses enums for types, some methods require us to return
13
+ # the name of the type. We will use this as a lookup.
14
+ PROJ_TYPES = %w[
15
+ PJ_TYPE_UNKNOWN
16
+ PJ_TYPE_ELLIPSOID
17
+ PJ_TYPE_PRIME_MERIDIAN
18
+ PJ_TYPE_GEODETIC_REFERENCE_FRAME
19
+ PJ_TYPE_DYNAMIC_GEODETIC_REFERENCE_FRAME
20
+ PJ_TYPE_VERTICAL_REFERENCE_FRAME
21
+ PJ_TYPE_DYNAMIC_VERTICAL_REFERENCE_FRAME
22
+ PJ_TYPE_DATUM_ENSEMBLE
23
+ PJ_TYPE_CRS
24
+ PJ_TYPE_GEODETIC_CRS
25
+ PJ_TYPE_GEOCENTRIC_CRS
26
+ PJ_TYPE_GEOGRAPHIC_CRS
27
+ PJ_TYPE_GEOGRAPHIC_2D_CRS
28
+ PJ_TYPE_GEOGRAPHIC_3D_CRS
29
+ PJ_TYPE_VERTICAL_CRS
30
+ PJ_TYPE_PROJECTED_CRS
31
+ PJ_TYPE_COMPOUND_CRS
32
+ PJ_TYPE_TEMPORAL_CRS
33
+ PJ_TYPE_ENGINEERING_CRS
34
+ PJ_TYPE_BOUND_CRS
35
+ PJ_TYPE_OTHER_CRS
36
+ PJ_TYPE_CONVERSION
37
+ PJ_TYPE_TRANSFORMATION
38
+ PJ_TYPE_CONCATENATED_OPERATION
39
+ PJ_TYPE_OTHER_COORDINATE_OPERATION
40
+ PJ_TYPE_TEMPORAL_DATUM
41
+ PJ_TYPE_ENGINEERING_DATUM
42
+ PJ_TYPE_PARAMETRIC_DATUM
43
+ ].freeze
44
+ end
45
+ end
46
+
47
+ RGeo::CoordSys::CONFIG.default_coord_sys_class = RGeo::CoordSys::Proj4 if RGeo::CoordSys::Proj4.supported?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgeo-proj4
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Tee Parham, Daniel Azuma
7
+ - Tee Parham, Daniel Azuma, Keith Doggett, Ulysse Buonomo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-08 00:00:00.000000000 Z
11
+ date: 2023-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rgeo
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: 3.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: 3.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: minitest
28
+ name: ffi-geos
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.14'
33
+ version: '2.2'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5.14'
40
+ version: '2.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: pry-byebug
42
+ name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.9.0
47
+ version: '5.14'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 3.9.0
54
+ version: '5.14'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,20 +94,37 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 1.8.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby_memcheck
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
97
111
  description: Proj4 extension for rgeo.
98
112
  email:
99
- - parhameter@gmail.com, dazuma@gmail.com
113
+ - parhameter@gmail.com, dazuma@gmail.com, kfdoggett@gmail.com
100
114
  executables: []
101
115
  extensions:
102
116
  - ext/proj4_c_impl/extconf.rb
103
117
  extra_rdoc_files: []
104
118
  files:
105
119
  - LICENSE.txt
120
+ - ext/proj4_c_impl/errors.c
121
+ - ext/proj4_c_impl/errors.h
106
122
  - ext/proj4_c_impl/extconf.rb
107
123
  - ext/proj4_c_impl/main.c
124
+ - ext/proj4_c_impl/preface.h
108
125
  - lib/rgeo/coord_sys/crs_to_crs.rb
109
126
  - lib/rgeo/coord_sys/proj4.rb
110
- - lib/rgeo/coord_sys/srs_database/proj4_data.rb
127
+ - lib/rgeo/errors.rb
111
128
  - lib/rgeo/proj4.rb
112
129
  - lib/rgeo/proj4/version.rb
113
130
  homepage: https://github.com/rgeo/rgeo-proj4
@@ -122,7 +139,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
139
  requirements:
123
140
  - - ">="
124
141
  - !ruby/object:Gem::Version
125
- version: 2.5.0
142
+ version: 2.6.0
126
143
  required_rubygems_version: !ruby/object:Gem::Requirement
127
144
  requirements:
128
145
  - - ">="
@@ -1,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # -----------------------------------------------------------------------------
4
- #
5
- # SRS database interface
6
- #
7
- # -----------------------------------------------------------------------------
8
-
9
- module RGeo
10
- module CoordSys
11
- module SRSDatabase
12
- # A spatial reference database implementation backed by coordinate
13
- # system files installed as part of the proj4 library. For a given
14
- # Proj4Data object, you specify a single file (e.g. the epsg data
15
- # file), and you can retrieve records by ID number.
16
-
17
- class Proj4Data
18
- # Connect to one of the proj4 data files. You should provide the
19
- # file name, optionally the installation directory if it is not
20
- # in a typical location, and several additional options.
21
- #
22
- # These options are recognized:
23
- #
24
- # [<tt>:dir</tt>]
25
- # The path for the share/proj directory that contains the
26
- # requested data file. By default, the Proj4Data class will
27
- # try a number of directories for you, including
28
- # /usr/local/share/proj, /opt/local/share/proj, /usr/share/proj,
29
- # and a few other variants. However, if you have proj4 installed
30
- # elsewhere, you can provide an explicit directory using this
31
- # option. You may also pass nil as the value, in which case all
32
- # the normal lookup paths will be disabled, and you will have to
33
- # provide the full path as the file name.
34
- # [<tt>:cache</tt>]
35
- # If set to true, this class caches previously looked up entries
36
- # so subsequent lookups do not have to reread the file. If set
37
- # to <tt>:read_all</tt>, then ALL values in the file are read in
38
- # and cached the first time a lookup is done. If set to
39
- # <tt>:preload</tt>, then ALL values in the file are read in
40
- # immediately when the database is created. Default is false,
41
- # indicating that the file will be reread on every lookup.
42
- # [<tt>:authority</tt>]
43
- # If set, its value is taken as the authority name for all
44
- # entries. The authority code will be set to the identifier. If
45
- # not set, then the authority fields of entries will be blank.
46
-
47
- def initialize(filename_, opts_ = {})
48
- dir_ = nil
49
- if opts_.include?(:dir)
50
- dir_ = opts_[:dir]
51
- else
52
- ["/usr/local/share/proj", "/usr/local/proj/share/proj", "/usr/local/proj4/share/proj", "/opt/local/share/proj", "/opt/proj/share/proj", "/opt/proj4/share/proj", "/opt/share/proj", "/usr/share/proj"].each do |d_|
53
- if ::File.directory?(d_) && ::File.readable?(d_)
54
- dir_ = d_
55
- break
56
- end
57
- end
58
- end
59
- @path = dir_ ? "#{dir_}/#{filename_}" : filename_
60
- @authority = opts_[:authority]
61
- if opts_[:cache]
62
- @cache = {}
63
- case opts_[:cache]
64
- when :read_all
65
- @populate_state = 1
66
- when :preload
67
- search_file(nil)
68
- @populate_state = 2
69
- else
70
- @populate_state = 0
71
- end
72
- else
73
- @cache = nil
74
- @populate_state = 0
75
- end
76
- end
77
-
78
- # Retrieve the Entry for the given ID number.
79
-
80
- def get(ident_)
81
- ident_ = ident_.to_s
82
- return @cache[ident_] if @cache&.include?(ident_)
83
- result_ = nil
84
- case @populate_state
85
- when 0
86
- data_ = search_file(ident_)
87
- result_ = Entry.new(ident_, authority: @authority, authority_code: @authority ? ident_ : nil, name: data_[1], proj4: data_[2]) if data_
88
- @cache[ident_] = result_ if @cache
89
- when 1
90
- search_file(nil)
91
- result_ = @cache[ident_]
92
- @populate_state = 2
93
- end
94
- result_
95
- end
96
-
97
- # Clear the cache if one exists.
98
-
99
- def clear_cache
100
- @cache&.clear
101
- @populate_state = 1 if @populate_state == 2
102
- end
103
-
104
- private
105
-
106
- def search_file(ident_)
107
- ::File.open(@path) do |file_|
108
- cur_name_ = nil
109
- cur_ident_ = nil
110
- cur_text_ = nil
111
- file_.each do |line_|
112
- line_.strip!
113
- if (comment_delim_ = line_.index("#"))
114
- cur_name_ = line_[comment_delim_ + 1..-1].strip
115
- line_ = line_[0..comment_delim_ - 1].strip
116
- end
117
- if !cur_ident_ && (line_ =~ /^<(\w+)>(.*)/)
118
- cur_ident_ = Regexp.last_match(1)
119
- cur_text_ = []
120
- line_ = Regexp.last_match(2).strip
121
- end
122
- next unless cur_ident_
123
- if line_[-2..-1] == "<>"
124
- cur_text_ << line_[0..-3].strip
125
- cur_text_ = cur_text_.join(" ")
126
- if ident_.nil?
127
- @cache[ident_] = Entry.new(ident_, authority: @authority, authority_code: @authority ? id_ : nil, name: cur_name_, proj4: cur_text_)
128
- end
129
- return [ident_, cur_name_, cur_text_] if cur_ident_ == ident_
130
- cur_ident_ = nil
131
- cur_name_ = nil
132
- cur_text_ = nil
133
- else
134
- cur_text_ << line_
135
- end
136
- end
137
- end
138
- nil
139
- end
140
- end
141
- end
142
- end
143
- end