rgeo-proj4 3.1.1 → 4.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.
@@ -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