simple-proj 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2e3c3bb3834d7d494e1e0dc220c5ca30e6a9387e0cfea7a30223535ad44e6ec9
4
+ data.tar.gz: 96148f842f3f3334424705f1256acbd46699cbe3a11f4c492033f371967a7b70
5
+ SHA512:
6
+ metadata.gz: 9359cd9bf7da8619a17d04ad615e713e70c89ccf56bf44f1f967b9324343481294de4dc5ba707a277f380784862cffce79dcb91d2bc466b75b0d938fb14fb4bb
7
+ data.tar.gz: e384f056f0a3a919dbc5e2d63d441a2c1222eff579583a442bbd327c974de1afcad4f4c2a88899f8b101268fb318b72edef5d32b99b49a3f65aa93b51c8550d4
data/API.md ADDED
@@ -0,0 +1,111 @@
1
+ PROJ4R
2
+ =======
3
+
4
+ Notes for the forward or inverse transformations
5
+
6
+ Proj
7
+ forward : (lon, lat) -> (x, y)
8
+ inverse : (x, y) -> (lon, lat)
9
+
10
+ Proj.transform
11
+ forward : (src, dst, x, y, z) -> (x', y', z')
12
+ inverse : (dst, src, x, y, z) -> (x', y', z')
13
+
14
+ If src = latlong, dst = projection, they work like Proj#forward, Proj#inverse.
15
+ In the cases, use lon as x, lat as y.
16
+
17
+ Geod
18
+ forward : (lat1, lon1, az12, dist) -> (lat2, lon2, az21)
19
+ inverse : (lat1, lon1, lat2, lon2) -> (dist, az12, az21)
20
+
21
+ Notes for the order of geographic coordinate (lon,lat) or (lat,lon)
22
+
23
+ PROJ4::Proj -> (lon, lat)
24
+ PROJ4.transform -> (lon, lat)
25
+ PROJ4::Geod -> (lat, lon)
26
+
27
+ These differences originate from Proj.4 C API.
28
+
29
+ Proj
30
+ ----
31
+
32
+ ### Constructor
33
+
34
+ pj = PROJ4::Proj.new("+proj=latlon +ellps=WGS84 units=km")
35
+
36
+ ### Attributes
37
+
38
+ pj.definition
39
+ pj.latlong?
40
+ pj.geocent?
41
+
42
+ ### Replication
43
+
44
+ pj.to_latlong
45
+
46
+ ### forward
47
+
48
+ x, y = pj.forward(lon, lat)
49
+
50
+ ### inverse
51
+
52
+ lon, lat = *pj.inverse(x, y)
53
+
54
+ p pj.to_latlong.definition
55
+
56
+ Transformation
57
+ --------------
58
+
59
+
60
+ Geod
61
+ ----
62
+
63
+ ### Constructor
64
+
65
+ geod = PROJ4::Geod.new() ### [+ellps=WGS84, units=m]
66
+ geod = PROJ4::Geod.new(6378137.0, 1/298.257223563) ### [+ellps=WGS84, units=m]
67
+ geod = PROJ4::Geod.new("+ellps=WGS84 units=m")
68
+
69
+ ### forward
70
+
71
+ lat2, lon2, az21 = *geod.forward(lat1, lon1, az12, dist)
72
+
73
+ input:
74
+ lat1: latitude of original point in degree
75
+ lon1: longitudde of original point in degree
76
+ az12: azimuth point to target point at origninal point in degree
77
+ dist: distance from original point to target point in units defined in constructor
78
+
79
+ output:
80
+ lat2: latitude of target point in degree
81
+ lon1: longitude of target point in degree
82
+ az21: azimuth point to original point at target point in degree
83
+
84
+ ### inverse
85
+
86
+ dist, az12, az21 = *geod.inverse(lat1, lon1, lat2, lon2)
87
+
88
+ input:
89
+ lat1: latitude of original point in degree
90
+ lon1: longitude of original point in degree
91
+ lat2: latitude of target point in degree
92
+ lon2: longitude of target point in degree
93
+
94
+ output:
95
+ dist: distance between original and target points in units defined in constructor
96
+ az12: azimuth point to target point at origninal point in degree
97
+ az21: azimuth point to original point at target point in degree
98
+
99
+ ### distance
100
+
101
+ dist = *geod.distance(lat1, lon1, lat2, lon2)
102
+
103
+ input:
104
+ lat1: latitude of original point in degree
105
+ lon1: longitude of original point in degree
106
+ lat2: latitude of target point in degree
107
+ lon2: longitude of target point in degree
108
+
109
+ output:
110
+ dist: distance between original and target points in units defined in constructor
111
+
data/README.md ADDED
@@ -0,0 +1,120 @@
1
+ Simple PROJ
2
+ ===========
3
+
4
+ This is a ruby extension library for map projection conversion using PROJ.
5
+ Note that this library is not a verbatim wrapper for all functions in PROJ.
6
+
7
+ Installation
8
+ ------------
9
+
10
+ gem install simple-proj
11
+
12
+ ### Requirement
13
+
14
+ * PROJ version 6 or 7
15
+
16
+ Features
17
+ --------
18
+
19
+ * Conversion of latitude and longitude to map projection coordinates (forward transformation)
20
+ * Conversion of map projection coordinates to latitude and longitude (inverse transformation)
21
+ * Transformation a map projection coordinate to another map projection coordinate
22
+
23
+
24
+ Usage
25
+ -----
26
+
27
+ ### Constructor
28
+
29
+ PROJ.new(PROJ_STRING) ### transform defined by proj-string
30
+ PROJ.new(CRS1, CRS2) ### transform from CRS1 to CRS2
31
+ PROJ.new(CRS2) ### CRS1 is assumed to be "+proj=latlong +type=crs"
32
+
33
+ The arguments should be String objects one of
34
+
35
+ * a proj-string,
36
+ * a WKT string,
37
+ * an object code (like 'EPSG:4326', 'urn:ogc:def:crs:EPSG::4326',
38
+ 'urn:ogc:def:coordinateOperation:EPSG::1671'),
39
+ * a OGC URN combining references for compound coordinate reference
40
+ systems (e.g 'urn:ogc:def:crs,crs:EPSG::2393,crs:EPSG::5717' or
41
+ custom abbreviated syntax 'EPSG:2393+5717'),
42
+ * a OGC URN combining references for concatenated operations (e.g.
43
+ 'urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,
44
+ coordinateOperation:EPSG::1618')
45
+
46
+ ### Transformation
47
+
48
+ Forward transformation.
49
+
50
+ PROJ#transform(x1, y1, z1=nil) => x2, y2[, z2]
51
+ PROJ#transform_forward(x1, y1, z1=nil) => x2, y2[, z2] ### alias of #transform
52
+
53
+ Inverse transformation.
54
+
55
+ PROJ#transform_inverse(x1, y1, z1=nil) => x2, y2[, z2]
56
+
57
+
58
+ ### Special methods for transformation from geodetic coordinates and other coordinates.
59
+
60
+ These are special methods provided to avoid converting
61
+ between latitude and longitude units between degrees and radians.
62
+
63
+ PROJ#forward(lon1, lat1, z1=nil) => x2, y2[, z2]
64
+ PROJ#inverse(x1, y1, z1=nil) => lon2, lat2[, z2]
65
+
66
+ The units of input parameters for PROJ#forward are degrees.
67
+ Internally, these units are converted to radians and passed to proj_trans().
68
+ Similarly, the units of output parameters for PROJ#inverse are degrees.
69
+
70
+ ```ruby
71
+ proj = PROJ.new("+proj=webmerc")
72
+
73
+ x, y = proj.forward(135, 35)
74
+ p [x, y] ### => [15028131.257091932, 4163881.144064294]
75
+
76
+ lon, lat = proj.inverse(x, y)
77
+ p [lon, lat] ### => [135.0, 35.000000000000014]
78
+
79
+ ```
80
+
81
+ Note:
82
+ This method should not be used for the PROJ object initialized with the proj-string that do not expect geodetic coordinates in radians for the source CRS. In such case, use #transform_forward and #transform_inverse instead of #forward and #inverse.
83
+ This is an example for *invalid* usage.
84
+
85
+ ```ruby
86
+ pj = PROJ.new("+proj=unitconvert +xy_in=deg +xy_out=rad")
87
+
88
+ p pj.forward(135, 35) ### does not work as expected
89
+ # => [0.041123351671205656, 0.0106616096925348]
90
+
91
+ p pj.transform(135, 35) ### works as expected
92
+ # => [2.356194490192345, 0.6108652381980153]
93
+ ```
94
+
95
+ Examples
96
+ --------
97
+
98
+ ### Conversion between 'EPSG:4326' and 'EPSG:3857'
99
+
100
+ For EPSG:4326 (in PROJ), the geographic coordinates are in the order of latitude and longitude.
101
+ Then, the transformation from EPSG:4326 requires the arguments in the order of latitude and longitude.
102
+
103
+ ```ruby
104
+ #########################################
105
+ # EPSG:4326 <-> EPSG:3857
106
+ #########################################
107
+
108
+ proj = PROJ.new("EPSG:4326", "EPSG:3857")
109
+
110
+ x, y = proj.transform(35, 135)
111
+
112
+ p [x, y] ### => [15028131.257091932, 4163881.144064294]
113
+
114
+ lat, lon = proj.transform_inverse(x, y)
115
+
116
+ p [lat, lon] ### => [35.00000000000001, 135.0]
117
+ ```
118
+
119
+
120
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ GEMSPEC = "simple-proj.gemspec"
2
+
3
+ task :install do
4
+ spec = eval File.read(GEMSPEC)
5
+ system %{
6
+ gem build #{GEMSPEC}; gem install #{spec.full_name}.gem
7
+ }
8
+ end
data/ext/extconf.rb ADDED
@@ -0,0 +1,12 @@
1
+ require "mkmf"
2
+ require 'carray/mkmf'
3
+ require "open-uri"
4
+
5
+ dir_config("proj", possible_includes, possible_libs)
6
+
7
+ if have_header("proj.h") and have_library("proj")
8
+ have_carray()
9
+ create_makefile("simple_proj")
10
+ end
11
+
12
+
data/ext/rb_proj.c ADDED
@@ -0,0 +1,832 @@
1
+ #include "ruby.h"
2
+ #include "rb_proj.h"
3
+
4
+ VALUE rb_cProj;
5
+ VALUE rb_cCrs;
6
+ VALUE rb_mCommon;
7
+
8
+ ID id_forward;
9
+ ID id_inverse;
10
+
11
+ static VALUE
12
+ rb_proj_info (VALUE klass)
13
+ {
14
+ volatile VALUE vout;
15
+ PJ_INFO info;
16
+
17
+ info = proj_info();
18
+
19
+ vout = rb_hash_new();
20
+ rb_hash_aset(vout, rb_str_new2("major"), INT2NUM(info.major));
21
+ rb_hash_aset(vout, rb_str_new2("minor"), INT2NUM(info.minor));
22
+ rb_hash_aset(vout, rb_str_new2("patch"), INT2NUM(info.patch));
23
+ rb_hash_aset(vout, rb_str_new2("release"), rb_str_new2(info.release));
24
+ rb_hash_aset(vout, rb_str_new2("version"), rb_str_new2(info.version));
25
+ rb_hash_aset(vout, rb_str_new2("searchpath"), rb_str_new2(info.searchpath));
26
+
27
+ return vout;
28
+ }
29
+
30
+ static void
31
+ free_proj (Proj *proj)
32
+ {
33
+ if ( proj->ref ) {
34
+ proj_destroy(proj->ref);
35
+ }
36
+ free(proj);
37
+ }
38
+
39
+ static VALUE
40
+ rb_proj_s_allocate (VALUE klass)
41
+ {
42
+ Proj *proj;
43
+ return Data_Make_Struct(klass, Proj, 0, free_proj, proj);
44
+ }
45
+
46
+ /*
47
+ Constructs a transformation object with one or two arguments.
48
+ The arguments should be PROJ::CRS objects or String objects one of
49
+
50
+ * a proj-string,
51
+ * a WKT string,
52
+ * an object code (like “EPSG:4326”, “urn:ogc:def:crs:EPSG::4326”,
53
+ “urn:ogc:def:coordinateOperation:EPSG::1671”),
54
+ * a OGC URN combining references for compound coordinate reference
55
+ systems (e.g “urn:ogc:def:crs,crs:EPSG::2393,crs:EPSG::5717” or
56
+ custom abbreviated syntax “EPSG:2393+5717”),
57
+ * a OGC URN combining references for concatenated operations (e.g.
58
+ “urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,
59
+ coordinateOperation:EPSG::1618”)
60
+
61
+ If two arguments are given, the first is the source CRS definition and the
62
+ second is the target CRS definition. If only one argument is given, the
63
+ following two cases are possible.
64
+
65
+ * a proj-string, which represents a transformation.
66
+ * a CRS defintion, in which case the latlong coordinates are implicitly
67
+ used as the source CRS definition.
68
+ * a PROJ::CRS object
69
+
70
+ @overload initialize(def1, def2=nil)
71
+ @param def1 [String] proj-string or other CRS definition (see above description).
72
+ @param def2 [String, nil] proj-string or other CRS definition (see above description).
73
+
74
+ @example
75
+ # Transformation from EPSG:4326 to EPSG:3857
76
+ pj = PROJ.new("EPSG:4326", "EPSG:3857")
77
+
78
+ # Transformation from (lat,lon) to WEB Mercator.
79
+ pj = PROJ.new("+proj=webmerc")
80
+
81
+ # Transformation from (lat,lon) to EPSG:3857
82
+ pj = PROJ.new("EPSG:3857")
83
+
84
+ # Using PROJ::CRS objects
85
+ epsg_3857 = PROJ::CRS.new("EPSG:3857")
86
+ pj = PROJ.new(epsg_3857)
87
+ pj = PROJ.new("EPSG:4326", epsg_3857)
88
+ pj = PROJ.new(epsg_3857, "EPSG:4326")
89
+
90
+ */
91
+
92
+ static VALUE
93
+ rb_proj_initialize (int argc, VALUE *argv, VALUE self)
94
+ {
95
+ volatile VALUE vdef1, vdef2;
96
+ Proj *proj, *crs;
97
+ PJ *ref, *src;
98
+ PJ_TYPE type;
99
+ int errno;
100
+
101
+ rb_scan_args(argc, argv, "11", (VALUE *)&vdef1, (VALUE *)&vdef2);
102
+
103
+ Data_Get_Struct(self, Proj, proj);
104
+
105
+ if ( NIL_P(vdef2) ) {
106
+ if ( rb_obj_is_kind_of(vdef1, rb_cCrs) ) {
107
+ Data_Get_Struct(vdef1, Proj, crs);
108
+ vdef1 = rb_str_new2(proj_as_proj_string(PJ_DEFAULT_CTX, crs->ref, PJ_PROJ_5, NULL));
109
+ }
110
+ else {
111
+ Check_Type(vdef1, T_STRING);
112
+ }
113
+ ref = proj_create(PJ_DEFAULT_CTX, StringValuePtr(vdef1));
114
+ if ( proj_is_crs(ref) ) {
115
+ proj_destroy(ref);
116
+ ref = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "+proj=latlong +type=crs", StringValuePtr(vdef1), NULL);
117
+ proj->ref = ref;
118
+ proj->is_src_latlong = 2;
119
+ }
120
+ else {
121
+ proj->ref = ref;
122
+ proj->is_src_latlong = 1;
123
+ }
124
+ }
125
+ else {
126
+ if ( rb_obj_is_kind_of(vdef1, rb_cCrs) ) {
127
+ Data_Get_Struct(vdef1, Proj, crs);
128
+ vdef1 = rb_str_new2(proj_as_proj_string(PJ_DEFAULT_CTX, crs->ref, PJ_PROJ_5, NULL));
129
+ }
130
+ else {
131
+ Check_Type(vdef1, T_STRING);
132
+ }
133
+ if ( rb_obj_is_kind_of(vdef2, rb_cCrs) ) {
134
+ Data_Get_Struct(vdef2, Proj, crs);
135
+ vdef2 = rb_str_new2(proj_as_proj_string(PJ_DEFAULT_CTX, crs->ref, PJ_PROJ_5, NULL));
136
+ }
137
+ else {
138
+ Check_Type(vdef2, T_STRING);
139
+ }
140
+ ref = proj_create_crs_to_crs(PJ_DEFAULT_CTX, StringValuePtr(vdef1), StringValuePtr(vdef2), NULL);
141
+ proj->ref = ref;
142
+ src = proj_get_source_crs(PJ_DEFAULT_CTX, ref);
143
+ type = proj_get_type(src);
144
+ if ( type == PJ_TYPE_GEOGRAPHIC_2D_CRS ||
145
+ type == PJ_TYPE_GEOGRAPHIC_3D_CRS ) {
146
+ proj->is_src_latlong = 2;
147
+ }
148
+ else {
149
+ proj->is_src_latlong = 0;
150
+ }
151
+ }
152
+
153
+ if ( ! ref ) {
154
+ errno = proj_context_errno(PJ_DEFAULT_CTX);
155
+ rb_raise(rb_eRuntimeError, "%s", proj_errno_string(errno));
156
+ }
157
+
158
+ return Qnil;
159
+ }
160
+
161
+ /*
162
+ Normalizes the axis order which is the one expected for visualization purposes.
163
+ If the axis order of its source or target CRS is
164
+ northing, easting, then an axis swap operation will be inserted.
165
+
166
+ @return [self]
167
+ */
168
+ static VALUE
169
+ rb_proj_normalize_for_visualization (VALUE self)
170
+ {
171
+ Proj *proj;
172
+ PJ *ref, *orig;
173
+ int errno;
174
+
175
+ Data_Get_Struct(self, Proj, proj);
176
+ orig = proj->ref;
177
+
178
+ ref = proj_normalize_for_visualization(PJ_DEFAULT_CTX, orig);
179
+ if ( ! ref ) {
180
+ errno = proj_context_errno(PJ_DEFAULT_CTX);
181
+ rb_raise(rb_eRuntimeError, "%s", proj_errno_string(errno));
182
+ }
183
+
184
+ proj->ref = ref;
185
+
186
+ proj_destroy(orig);
187
+
188
+ return self;
189
+ }
190
+
191
+ /*
192
+ Returns source CRS as PROJ::CRS object.
193
+
194
+ @return [PROJ, nil]
195
+ */
196
+ static VALUE
197
+ rb_proj_source_crs (VALUE self)
198
+ {
199
+ Proj *proj;
200
+ PJ *crs;
201
+
202
+ Data_Get_Struct(self, Proj, proj);
203
+ crs = proj_get_source_crs(PJ_DEFAULT_CTX, proj->ref);
204
+
205
+ if ( ! crs ) {
206
+ return Qnil;
207
+ }
208
+
209
+ return rb_crs_new(crs);
210
+ }
211
+
212
+ /*
213
+ Returns target CRS as PROJ::CRS object.
214
+
215
+ @return [PROJ, nil]
216
+ */
217
+ static VALUE
218
+ rb_proj_target_crs (VALUE self)
219
+ {
220
+ Proj *proj;
221
+ PJ *crs;
222
+
223
+ Data_Get_Struct(self, Proj, proj);
224
+ crs = proj_get_target_crs(PJ_DEFAULT_CTX, proj->ref);
225
+
226
+ if ( ! crs ) {
227
+ return Qnil;
228
+ }
229
+
230
+ return rb_crs_new(crs);
231
+ }
232
+
233
+ /*
234
+ Checks if a operation expects input in radians or not.
235
+
236
+ @return [Boolean]
237
+ */
238
+
239
+ static VALUE
240
+ rb_proj_angular_input (VALUE self, VALUE direction)
241
+ {
242
+ Proj *proj;
243
+
244
+ Data_Get_Struct(self, Proj, proj);
245
+
246
+ if ( rb_to_id(direction) == id_forward ) {
247
+ return proj_angular_input(proj->ref, PJ_FWD) == 1 ? Qtrue : Qfalse;
248
+ }
249
+ else if ( rb_to_id(direction) == id_inverse ) {
250
+ return proj_angular_input(proj->ref, PJ_INV) == 1 ? Qtrue : Qfalse;
251
+ }
252
+ else {
253
+ rb_raise(rb_eArgError, "invalid direction");
254
+ }
255
+ }
256
+
257
+ /*
258
+ Checks if an operation returns output in radians or not.
259
+
260
+ @return [Boolean]
261
+ */
262
+
263
+ static VALUE
264
+ rb_proj_angular_output (VALUE self, VALUE direction)
265
+ {
266
+ Proj *proj;
267
+
268
+ Data_Get_Struct(self, Proj, proj);
269
+
270
+ if ( rb_to_id(direction) == id_forward ) {
271
+ return proj_angular_output(proj->ref, PJ_FWD) == 1 ? Qtrue : Qfalse;
272
+ }
273
+ else if ( rb_to_id(direction) == id_inverse ) {
274
+ return proj_angular_output(proj->ref, PJ_INV) == 1 ? Qtrue : Qfalse;
275
+ }
276
+ else {
277
+ rb_raise(rb_eArgError, "invalid direction");
278
+ }
279
+ }
280
+
281
+ static VALUE
282
+ rb_proj_pj_info (VALUE self)
283
+ {
284
+ volatile VALUE vout;
285
+ Proj *proj;
286
+ PJ_PROJ_INFO info;
287
+
288
+ Data_Get_Struct(self, Proj, proj);
289
+ info = proj_pj_info(proj->ref);
290
+
291
+ vout = rb_hash_new();
292
+ rb_hash_aset(vout, rb_str_new2("id"), (info.id) ? rb_str_new2(info.id) : Qnil);
293
+ rb_hash_aset(vout, rb_str_new2("description"), rb_str_new2(info.description));
294
+ rb_hash_aset(vout, rb_str_new2("definition"), rb_str_new2(info.definition));
295
+ rb_hash_aset(vout, rb_str_new2("has_inverse"), INT2NUM(info.has_inverse));
296
+ rb_hash_aset(vout, rb_str_new2("accuracy"), rb_float_new(info.accuracy));
297
+
298
+ return vout;
299
+ }
300
+
301
+
302
+ static VALUE
303
+ rb_proj_factors (VALUE self, VALUE vlon, VALUE vlat)
304
+ {
305
+ Proj *proj;
306
+ PJ_COORD pos;
307
+ PJ_FACTORS factors;
308
+
309
+ Data_Get_Struct(self, Proj, proj);
310
+
311
+ pos.lp.lam = proj_torad(NUM2DBL(vlon));
312
+ pos.lp.phi = proj_torad(NUM2DBL(vlat));
313
+
314
+ factors = proj_factors(proj->ref, pos);
315
+
316
+ return rb_str_new((const char *) &factors, sizeof(PJ_FACTORS));
317
+ }
318
+
319
+
320
+ /*
321
+ Transforms coordinates forwardly from (lat1, lon1, z1) to (x1, y2, z2).
322
+ The order of coordinates arguments should be longitude, latitude, and height.
323
+ The input longitude and latitude should be in units 'degrees'.
324
+
325
+ @overload forward(lon1, lat1, z1 = nil)
326
+ @param lon1 [Numeric] longitude in degrees.
327
+ @param lat1 [Numeric] latitude in degrees.
328
+ @param z1 [Numeric, nil] vertical coordinate.
329
+
330
+ @return x2, y2[, z2]
331
+
332
+ @example
333
+ x2, y2 = pj.forward(lon1, lat1)
334
+ x2, y2, z2 = pj.forward(lon1, lat1, z1)
335
+
336
+ */
337
+ static VALUE
338
+ rb_proj_forward (int argc, VALUE *argv, VALUE self)
339
+ {
340
+ volatile VALUE vlon, vlat, vz;
341
+ Proj *proj;
342
+ PJ_COORD data_in, data_out;
343
+ int errno;
344
+
345
+ rb_scan_args(argc, argv, "21", (VALUE*) &vlon, (VALUE*) &vlat, (VALUE*) &vz);
346
+
347
+ Data_Get_Struct(self, Proj, proj);
348
+
349
+ if ( ! proj->is_src_latlong ) {
350
+ rb_raise(rb_eRuntimeError, "requires latlong src crs. use #transform_forward instead of #forward.");
351
+ }
352
+
353
+ if ( proj_angular_input(proj->ref, PJ_FWD) == 1 ) {
354
+ data_in.lpz.lam = proj_torad(NUM2DBL(vlon));
355
+ data_in.lpz.phi = proj_torad(NUM2DBL(vlat));
356
+ data_in.lpz.z = NIL_P(vz) ? 0.0 : NUM2DBL(vz);
357
+ }
358
+ else {
359
+ data_in.xyz.x = NUM2DBL(vlon);
360
+ data_in.xyz.y = NUM2DBL(vlat);
361
+ data_in.xyz.z = NIL_P(vz) ? 0.0 : NUM2DBL(vz);
362
+ }
363
+
364
+ data_out = proj_trans(proj->ref, PJ_FWD, data_in);
365
+
366
+ if ( data_out.xyz.x == HUGE_VAL ) {
367
+ errno = proj_context_errno(PJ_DEFAULT_CTX);
368
+ rb_raise(rb_eRuntimeError, "%s", proj_errno_string(errno));
369
+ }
370
+
371
+ if ( NIL_P(vz) ) {
372
+ return rb_assoc_new(rb_float_new(data_out.xyz.x),
373
+ rb_float_new(data_out.xyz.y));
374
+ } else {
375
+ return rb_ary_new3(3, rb_float_new(data_out.xyz.x),
376
+ rb_float_new(data_out.xyz.y),
377
+ rb_float_new(data_out.xyz.z));
378
+ }
379
+ }
380
+
381
+ /*
382
+ Transforms coordinates inversely from (x1, y1, z1) to (lon2, lat2, z2).
383
+ The order of output coordinates is longitude, latitude and height.
384
+ The returned longitude and latitude are in units 'degrees'.
385
+
386
+ @overload inverse(x1, y1, z1 = nil)
387
+ @param x1 [Numeric]
388
+ @param y1 [Numeric]
389
+ @param z1 [Numeric, nil]
390
+
391
+ @return lon2, lat2, [, z2]
392
+
393
+ @example
394
+ lon2, lat2 = pj.inverse(x1, y1)
395
+ lon2, lat2, z2 = pj.inverse(x1, y1, z1)
396
+
397
+ */
398
+ static VALUE
399
+ rb_proj_inverse (int argc, VALUE *argv, VALUE self)
400
+ {
401
+ volatile VALUE vx, vy, vz;
402
+ Proj *proj;
403
+ PJ_COORD data_in, data_out;
404
+ int errno;
405
+
406
+ rb_scan_args(argc, argv, "21", (VALUE *)&vx, (VALUE *)&vy, (VALUE *)&vz);
407
+ Data_Get_Struct(self, Proj, proj);
408
+
409
+ if ( ! proj->is_src_latlong ) {
410
+ rb_raise(rb_eRuntimeError, "requires latlong src crs. use #transform_inverse instead of #inverse.");
411
+ }
412
+
413
+ data_in.xyz.x = NUM2DBL(vx);
414
+ data_in.xyz.y = NUM2DBL(vy);
415
+ data_in.xyz.z = NIL_P(vz) ? 0.0 : NUM2DBL(vz);
416
+
417
+ data_out = proj_trans(proj->ref, PJ_INV, data_in);
418
+
419
+ if ( data_out.lpz.lam == HUGE_VAL ) {
420
+ errno = proj_errno(proj->ref);
421
+ rb_raise(rb_eRuntimeError, "%s", proj_errno_string(errno));
422
+ }
423
+
424
+ if ( proj_angular_output(proj->ref, PJ_INV) == 1 ) {
425
+ if ( NIL_P(vz) ) {
426
+ return rb_assoc_new(rb_float_new(proj_todeg(data_out.lpz.lam)),
427
+ rb_float_new(proj_todeg(data_out.lpz.phi)));
428
+ } else {
429
+ return rb_ary_new3(3, rb_float_new(proj_todeg(data_out.lpz.lam)),
430
+ rb_float_new(proj_todeg(data_out.lpz.phi)),
431
+ rb_float_new(data_out.lpz.z));
432
+ }
433
+ }
434
+ else {
435
+ if ( NIL_P(vz) ) {
436
+ return rb_assoc_new(rb_float_new(data_out.xyz.x),
437
+ rb_float_new(data_out.xyz.y));
438
+ } else {
439
+ return rb_ary_new3(3, rb_float_new(data_out.xyz.x),
440
+ rb_float_new(data_out.xyz.y),
441
+ rb_float_new(data_out.xyz.z));
442
+ }
443
+ }
444
+ }
445
+
446
+ static VALUE
447
+ rb_proj_transform_i (int argc, VALUE *argv, VALUE self, PJ_DIRECTION direction)
448
+ {
449
+ VALUE vx, vy, vz;
450
+ Proj *trans;
451
+ PJ_COORD c_in, c_out;
452
+ int errno;
453
+
454
+ rb_scan_args(argc, argv, "21", (VALUE*)&vx, (VALUE*)&vy, (VALUE*)&vz);
455
+
456
+ Data_Get_Struct(self, Proj, trans);
457
+
458
+ c_in.xyz.x = NUM2DBL(vx);
459
+ c_in.xyz.y = NUM2DBL(vy);
460
+ c_in.xyz.z = NIL_P(vz) ? 0.0 : NUM2DBL(vz);
461
+
462
+ c_out = proj_trans(trans->ref, direction, c_in);
463
+
464
+ if ( c_out.xyz.x == HUGE_VAL ) {
465
+ errno = proj_errno(trans->ref);
466
+ rb_raise(rb_eRuntimeError, "%s", proj_errno_string(errno));
467
+ }
468
+
469
+ if ( NIL_P(vz) ) {
470
+ return rb_ary_new3(2,
471
+ rb_float_new(c_out.xyz.x),
472
+ rb_float_new(c_out.xyz.y));
473
+ }
474
+ else {
475
+ return rb_ary_new3(3,
476
+ rb_float_new(c_out.xyz.x),
477
+ rb_float_new(c_out.xyz.y),
478
+ rb_float_new(c_out.xyz.z));
479
+ }
480
+
481
+ }
482
+
483
+ /*
484
+ Transforms coordinates forwardly from (x1, y1, z1) to (x1, y2, z2).
485
+ The order of coordinates arguments are according to source and target CRSs.
486
+
487
+ @overload transform_forward(x1, y1, z1 = nil)
488
+ @param x1 [Numeric]
489
+ @param y1 [Numeric]
490
+ @param z1 [Numeric, nil]
491
+
492
+ @return x2, y2[, z2] (Numeric)
493
+
494
+ @example
495
+ x2, y2 = pj.transform(x1, y1)
496
+ x2, y2, z2 = pj.transform(x1, y1, z1)
497
+
498
+ */
499
+ static VALUE
500
+ rb_proj_transform_forward (int argc, VALUE *argv, VALUE self)
501
+ {
502
+ return rb_proj_transform_i(argc, argv, self, PJ_FWD);
503
+ }
504
+
505
+ /*
506
+ Transforms coordinates inversely from (x1, y1, z1) to (x1, y2, z2).
507
+ The order of coordinates arguments are according to source and target CRSs.
508
+
509
+ @overload transform_inverse(x1, y1, z1 = nil)
510
+ @param x1 [Numeric]
511
+ @param y1 [Numeric]
512
+ @param z1 [Numeric]
513
+ @return x2, y2[, z2] (Numeric)
514
+
515
+ @example
516
+ x2, y2 = pj.transform_inverse(x1, y1)
517
+ x2, y2, z2 = pj.transform_inverse(x1, y1, z1)
518
+
519
+ */
520
+ static VALUE
521
+ rb_proj_transform_inverse (int argc, VALUE *argv, VALUE self)
522
+ {
523
+ return rb_proj_transform_i(argc, argv, self, PJ_INV);
524
+ }
525
+
526
+ /*
527
+ Constructs a CRS object with an argument.
528
+ The argument should be a String object one of
529
+
530
+ * a proj-string,
531
+ * a WKT string,
532
+ * an object code (like “EPSG:4326”, “urn:ogc:def:crs:EPSG::4326”,
533
+ “urn:ogc:def:coordinateOperation:EPSG::1671”),
534
+ * a OGC URN combining references for compound coordinate reference
535
+ systems (e.g “urn:ogc:def:crs,crs:EPSG::2393,crs:EPSG::5717” or
536
+ custom abbreviated syntax “EPSG:2393+5717”),
537
+ * a OGC URN combining references for concatenated operations (e.g.
538
+ “urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,
539
+ coordinateOperation:EPSG::1618”)
540
+
541
+ @overload initialize(definition)
542
+ @param definition [String] proj-string or other CRS definition (see above description).
543
+
544
+ @example
545
+ # Create a PROJ::CRS object
546
+ epsg_3857 = PROJ::CRS.new("EPSG:3857")
547
+
548
+ */
549
+
550
+ static VALUE
551
+ rb_crs_initialize (VALUE self, VALUE vdef1)
552
+ {
553
+ Proj *proj;
554
+ PJ *ref;
555
+ int errno;
556
+
557
+ Data_Get_Struct(self, Proj, proj);
558
+
559
+ ref = proj_create(PJ_DEFAULT_CTX, StringValuePtr(vdef1));
560
+
561
+ if ( ! ref ) {
562
+ errno = proj_context_errno(PJ_DEFAULT_CTX);
563
+ rb_raise(rb_eRuntimeError, "%s", proj_errno_string(errno));
564
+ }
565
+
566
+ if ( proj_is_crs(ref) ) {
567
+ proj->ref = ref;
568
+ }
569
+ else {
570
+ rb_raise(rb_eRuntimeError, "should be crs definition");
571
+ }
572
+
573
+ return Qnil;
574
+ }
575
+
576
+ VALUE
577
+ rb_crs_new (PJ *ref)
578
+ {
579
+ volatile VALUE vcrs;
580
+ Proj *proj;
581
+
582
+ vcrs = rb_proj_s_allocate(rb_cCrs);
583
+ Data_Get_Struct(vcrs, Proj, proj);
584
+
585
+ proj->ref = ref;
586
+
587
+ return vcrs;
588
+ }
589
+
590
+
591
+ static VALUE
592
+ rb_proj_initialize_copy (VALUE self, VALUE obj)
593
+ {
594
+ Proj *proj, *other;
595
+
596
+ Data_Get_Struct(self, Proj, proj);
597
+
598
+ if ( rb_obj_is_kind_of(obj, rb_cProj) || rb_obj_is_kind_of(obj, rb_cCrs) ) {
599
+ Data_Get_Struct(obj, Proj, other);
600
+ proj->ref = proj_clone(PJ_DEFAULT_CTX, other->ref);
601
+ }
602
+ else {
603
+ rb_raise(rb_eArgError, "invalid class of argument object");
604
+ }
605
+
606
+ return self;
607
+ }
608
+
609
+ /*
610
+ Gets the name of the object.
611
+
612
+ @return [String]
613
+ */
614
+ static VALUE
615
+ rb_proj_get_name (VALUE self)
616
+ {
617
+ Proj *proj;
618
+
619
+ Data_Get_Struct(self, Proj, proj);
620
+
621
+ return rb_str_new2(proj_get_name(proj->ref));
622
+ }
623
+
624
+ /*
625
+ Gets the authority name / codespace of an identifier of the object.
626
+
627
+ @overload id_auth_name (index=nil)
628
+ @param index [Integer] index of the identifier (0 = first identifier)
629
+
630
+ @return [String, nil]
631
+ */
632
+
633
+ static VALUE
634
+ rb_proj_get_id_auth_name (int argc, VALUE *argv, VALUE self)
635
+ {
636
+ volatile VALUE vidx;
637
+ Proj *proj;
638
+ const char *string;
639
+
640
+ rb_scan_args(argc, argv, "01", (VALUE *)&vidx);
641
+
642
+ Data_Get_Struct(self, Proj, proj);
643
+
644
+ if ( NIL_P(vidx) ) {
645
+ string = proj_get_id_auth_name(proj->ref, 0);
646
+ }
647
+ else {
648
+ string = proj_get_id_auth_name(proj->ref, NUM2INT(vidx));
649
+ }
650
+
651
+ return (string) ? rb_str_new2(string) : Qnil;
652
+ }
653
+
654
+ /*
655
+ Gets the code of an identifier of the object.
656
+
657
+ @overload id_code (index=nil)
658
+ @param index [Integer] index of the identifier (0 = first identifier)
659
+
660
+ @return [String, nil]
661
+ */
662
+
663
+ static VALUE
664
+ rb_proj_get_id_code (int argc, VALUE *argv, VALUE self)
665
+ {
666
+ volatile VALUE vidx;
667
+ Proj *proj;
668
+ const char *string;
669
+
670
+ rb_scan_args(argc, argv, "01", (VALUE *)&vidx);
671
+
672
+ Data_Get_Struct(self, Proj, proj);
673
+
674
+ if ( NIL_P(vidx) ) {
675
+ string = proj_get_id_code(proj->ref, 0);
676
+ }
677
+ else {
678
+ string = proj_get_id_code(proj->ref, NUM2INT(vidx));
679
+ }
680
+
681
+ return (string) ? rb_str_new2(string) : Qnil;
682
+ }
683
+
684
+ /*
685
+ Gets a PROJJSON string representation of the object.
686
+
687
+ This method may return nil if the object is not compatible
688
+ with an export to the requested type.
689
+
690
+ @return [String,nil]
691
+ */
692
+ static VALUE
693
+ rb_proj_as_projjson (VALUE self)
694
+ {
695
+ Proj *proj;
696
+ const char *json;
697
+
698
+ Data_Get_Struct(self, Proj, proj);
699
+ json = proj_as_projjson(PJ_DEFAULT_CTX, proj->ref, NULL);
700
+ if ( ! json ) {
701
+ return Qnil;
702
+ }
703
+ return rb_str_new2(json);
704
+ }
705
+
706
+
707
+ /*
708
+ Gets a PROJ string representation of the object.
709
+ This method may return nil if the object is not compatible with
710
+ an export to the requested type.
711
+
712
+ @return [String,nil]
713
+ */
714
+ static VALUE
715
+ rb_proj_as_proj_string (VALUE self)
716
+ {
717
+ Proj *proj;
718
+ const char *string;
719
+
720
+ Data_Get_Struct(self, Proj, proj);
721
+ string = proj_as_proj_string(PJ_DEFAULT_CTX, proj->ref, PJ_PROJ_5, NULL);
722
+ if ( ! string ) {
723
+ return Qnil;
724
+ }
725
+ return rb_str_new2(string);
726
+ }
727
+
728
+ static VALUE
729
+ rb_proj_ellipsoid_get_parameters (VALUE self)
730
+ {
731
+ Proj *proj;
732
+ PJ *ellps;
733
+ double a, b, invf;
734
+ int computed;
735
+
736
+ Data_Get_Struct(self, Proj, proj);
737
+ ellps = proj_get_ellipsoid(PJ_DEFAULT_CTX, proj->ref);
738
+ proj_ellipsoid_get_parameters(PJ_DEFAULT_CTX, ellps, &a, &b, &computed, &invf);
739
+ return rb_ary_new3(4,
740
+ rb_float_new(a),
741
+ rb_float_new(b),
742
+ INT2NUM(computed),
743
+ rb_float_new(invf));
744
+ }
745
+
746
+ /*
747
+ Gets a WKT expression of CRS definition of the object.
748
+
749
+ @return [String]
750
+ */
751
+ static VALUE
752
+ rb_proj_as_wkt (int argc, VALUE *argv, VALUE self)
753
+ {
754
+ volatile VALUE vidx;
755
+ Proj *proj;
756
+ const char *wkt;
757
+
758
+ rb_scan_args(argc, argv, "01", (VALUE *)&vidx);
759
+
760
+ Data_Get_Struct(self, Proj, proj);
761
+
762
+ if ( NIL_P(vidx) ) {
763
+ wkt = proj_as_wkt(PJ_DEFAULT_CTX, proj->ref, PJ_WKT2_2018, NULL);
764
+ }
765
+ else {
766
+ wkt = proj_as_wkt(PJ_DEFAULT_CTX, proj->ref, NUM2INT(vidx), NULL);
767
+ }
768
+
769
+ if ( ! wkt ) {
770
+ return Qnil;
771
+ }
772
+ else {
773
+ return rb_str_new2(wkt);
774
+ }
775
+ }
776
+
777
+
778
+ void
779
+ Init_simple_proj ()
780
+ {
781
+ id_forward = rb_intern("forward");
782
+ id_inverse = rb_intern("inverse");
783
+
784
+ rb_cProj = rb_define_class("PROJ", rb_cObject);
785
+ rb_cCrs = rb_define_class_under(rb_cProj, "CRS", rb_cObject);
786
+ rb_mCommon = rb_define_module_under(rb_cProj, "Common");
787
+
788
+ rb_include_module(rb_cProj, rb_mCommon);
789
+ rb_include_module(rb_cCrs, rb_mCommon);
790
+
791
+ rb_define_singleton_method(rb_cProj, "_info", rb_proj_info, 0);
792
+
793
+ rb_define_alloc_func(rb_cProj, rb_proj_s_allocate);
794
+ rb_define_method(rb_cProj, "initialize", rb_proj_initialize, -1);
795
+ rb_define_method(rb_cProj, "source_crs", rb_proj_source_crs, 0);
796
+ rb_define_method(rb_cProj, "target_crs", rb_proj_target_crs, 0);
797
+ rb_define_method(rb_cProj, "angular_input?", rb_proj_angular_input, 1);
798
+ rb_define_method(rb_cProj, "angular_output?", rb_proj_angular_output, 1);
799
+ rb_define_method(rb_cProj, "normalize_for_visualization", rb_proj_normalize_for_visualization, 0);
800
+ rb_define_method(rb_cProj, "forward", rb_proj_forward, -1);
801
+ rb_define_method(rb_cProj, "inverse", rb_proj_inverse, -1);
802
+ rb_define_method(rb_cProj, "transform", rb_proj_transform_forward, -1);
803
+ rb_define_method(rb_cProj, "transform_inverse", rb_proj_transform_inverse, -1);
804
+ rb_define_private_method(rb_cProj, "_pj_info", rb_proj_pj_info, 0);
805
+ rb_define_private_method(rb_cProj, "_factors", rb_proj_factors, 2);
806
+
807
+ rb_define_alloc_func(rb_cCrs, rb_proj_s_allocate);
808
+ rb_define_method(rb_cCrs, "initialize", rb_crs_initialize, 1);
809
+ rb_define_method(rb_cCrs, "normalize_for_visualization", rb_proj_normalize_for_visualization, 0);
810
+
811
+ rb_define_method(rb_mCommon, "initialize_copy", rb_proj_initialize_copy, 1);
812
+ rb_define_method(rb_mCommon, "name", rb_proj_get_name, 0);
813
+ rb_define_method(rb_mCommon, "id_auth_name", rb_proj_get_id_auth_name, -1);
814
+ rb_define_method(rb_mCommon, "id_code", rb_proj_get_id_code, -1);
815
+ rb_define_method(rb_mCommon, "to_proj_string", rb_proj_as_proj_string, 0);
816
+ rb_define_method(rb_mCommon, "to_projjson", rb_proj_as_projjson, 0);
817
+ rb_define_method(rb_mCommon, "ellipsoid_parameters", rb_proj_ellipsoid_get_parameters, 0);
818
+ rb_define_method(rb_mCommon, "to_wkt", rb_proj_as_wkt, -1);
819
+
820
+ rb_define_const(rb_cProj, "WKT2_2015", INT2NUM(PJ_WKT2_2015));
821
+ rb_define_const(rb_cProj, "WKT2_2015_SIMPLIFIED", INT2NUM(PJ_WKT2_2015_SIMPLIFIED));
822
+ #ifdef WKT2_2018
823
+ rb_define_const(rb_cProj, "WKT2_2018", INT2NUM(PJ_WKT2_2018));
824
+ rb_define_const(rb_cProj, "WKT2_2018_SIMPLIFIED", INT2NUM(PJ_WKT2_2018_SIMPLIFIED));
825
+ #endif
826
+ #ifdef WKT2_2019
827
+ rb_define_const(rb_cProj, "WKT2_2019", INT2NUM(PJ_WKT2_2019));
828
+ rb_define_const(rb_cProj, "WKT2_2019_SIMPLIFIED", INT2NUM(PJ_WKT2_2019_SIMPLIFIED));
829
+ #endif
830
+ rb_define_const(rb_cProj, "WKT1_GDAL", INT2NUM(PJ_WKT1_GDAL));
831
+ rb_define_const(rb_cProj, "WKT1_ESRI", INT2NUM(PJ_WKT1_ESRI));
832
+ }
data/ext/rb_proj.h ADDED
@@ -0,0 +1,18 @@
1
+ #ifndef RB_PROJ_H
2
+ #define RB_PROJ_H
3
+
4
+ #include <proj.h>
5
+
6
+ typedef struct {
7
+ PJ *ref;
8
+ int is_src_latlong;
9
+ } Proj;
10
+
11
+ extern PJ* PJ_DEFAULT_LONGLAT;
12
+
13
+ extern VALUE rb_cProj;
14
+ extern VALUE rb_cCrs;
15
+
16
+ VALUE rb_crs_new(PJ *);
17
+
18
+ #endif
@@ -0,0 +1,165 @@
1
+ require 'simple_proj.so'
2
+ require 'json'
3
+ require 'bindata'
4
+ require 'ostruct'
5
+
6
+ class PROJ
7
+
8
+ # Returns PROJ info
9
+ #
10
+ # @return [OpenStruct]
11
+ def self.info
12
+ return OpenStruct.new(_info)
13
+ end
14
+
15
+ alias transform_forward transform
16
+
17
+ alias forward_lonlat forward
18
+
19
+ # A variant of #forward which accept the axis order as (lat, lon).
20
+ def forward_latlon (lat, lon, z = nil)
21
+ return forward(lon, lat, z)
22
+ end
23
+
24
+ alias inverse_lonlat inverse
25
+
26
+ # A variant of #inverse which return the output with the axis order in (lat, lon).
27
+ def inverse_latlon (x, y, z = nil)
28
+ return inverse_latlon(x, y, z)
29
+ end
30
+
31
+ # Returns a internal information of the object
32
+ #
33
+ # @return [OpenStruct]
34
+ def pj_info
35
+ info = _pj_info
36
+ if info["id"] == "unknown"
37
+ transform(0,0)
38
+ info = _pj_info
39
+ if info["id"] == "unknown"
40
+ return OpenStruct.new(info)
41
+ else
42
+ return pj_info
43
+ end
44
+ else
45
+ info["definition"] = info["definition"].strip.split(/\s+/).map{|s| "+"+s}.join(" ")
46
+ return OpenStruct.new(info)
47
+ end
48
+ end
49
+
50
+ # Returns a definition of the object
51
+ #
52
+ # @return [OpenStruct]
53
+ def definition
54
+ return pj_info.definition
55
+ end
56
+
57
+ ENDIAN = ( [1].pack("I") == [1].pack("N") ) ? :big : :little
58
+
59
+ # A class represents PJ_FACTORS structure defined using BinData::Record
60
+ #
61
+ # This structure has members,
62
+ #
63
+ # * meridional_scale
64
+ # * parallel_scale
65
+ # * areal_scale
66
+ # * angular_distortion
67
+ # * meridian_parallel_angle
68
+ # * meridian_convergence
69
+ # * tissot_semimajor
70
+ # * tissot_semiminor
71
+ # * dx_dlam
72
+ # * dx_dphi
73
+ # * dy_dlam
74
+ # * dy_dphi
75
+ #
76
+ class FACTORS < BinData::Record
77
+ endian ENDIAN
78
+ double :meridional_scale
79
+ double :parallel_scale
80
+ double :areal_scale
81
+ double :angular_distortion
82
+ double :meridian_parallel_angle
83
+ double :meridian_convergence
84
+ double :tissot_semimajor
85
+ double :tissot_semiminor
86
+ double :dx_dlam
87
+ double :dx_dphi
88
+ double :dy_dlam
89
+ double :dy_dphi
90
+ end
91
+
92
+ # Returns PROJ::FACTORS object
93
+ #
94
+ # @retrun [PROJ::FACTORS]
95
+ def factors (lon, lat)
96
+ return FACTORS.read(_factors(lon, lat))
97
+ end
98
+
99
+ end
100
+
101
+ class PROJ
102
+
103
+ module Common
104
+
105
+ # Gets a EPSG code of the object
106
+ #
107
+ # @return [String, nil]
108
+ def to_epsg_code
109
+ auth = id_auth_name
110
+ code = id_code
111
+ if auth and code
112
+ return auth + ":" + code
113
+ else
114
+ return nil
115
+ end
116
+ end
117
+
118
+ # Gets a Hash object parsed from the PROJJSON expression of the object
119
+ #
120
+ # @return [Hash, nil]
121
+ def to_projjson_as_hash
122
+ json = to_projjson
123
+ if json
124
+ return JSON.parse(json)
125
+ else
126
+ return nil
127
+ end
128
+ end
129
+
130
+ def to_wkt2_2015
131
+ return to_wkt(WKT2_2015)
132
+ end
133
+
134
+ def to_wkt2_2015_simplified
135
+ return to_wkt(WKT2_2015_SIMPLIFIED)
136
+ end
137
+
138
+ def to_wkt2_2018
139
+ return to_wkt(WKT2_2018)
140
+ end
141
+
142
+ def to_wkt2_2018_simplified
143
+ if defined? WKT2_2018_SIMPLIFIED
144
+ return to_wkt(WKT2_2018_SIMPLIFIED)
145
+ else
146
+ raise "WKT2_2018 not defined. Check PROJ version."
147
+ end
148
+ end
149
+
150
+ def to_wkt_gdal
151
+ return to_wkt(WKT1_GDAL)
152
+ end
153
+
154
+ def to_wkt_esri
155
+ return to_wkt(WKT1_ESRI)
156
+ end
157
+
158
+ end
159
+
160
+ end
161
+
162
+ begin
163
+ require "simple-proj-carray"
164
+ rescue LoadError
165
+ end
@@ -0,0 +1,25 @@
1
+
2
+ Gem::Specification::new do |s|
3
+ version = "1.0.0"
4
+
5
+ files = Dir.glob("**/*") - [
6
+ Dir.glob("simple-proj-*.gem"),
7
+ Dir.glob("doc/**/*"),
8
+ Dir.glob("examples/**/*"),
9
+ ].flatten
10
+
11
+ s.platform = Gem::Platform::RUBY
12
+ s.name = "simple-proj"
13
+ s.summary = "Ruby extension library for PROJ 7"
14
+ s.description = <<-HERE
15
+ Ruby extension library for PROJ 7
16
+ HERE
17
+ s.version = version
18
+ s.license = 'MIT'
19
+ s.author = "Hiroki Motoyoshi"
20
+ s.email = ""
21
+ s.homepage = 'https://github.com/himotoyoshi/simple-proj'
22
+ s.files = files
23
+ s.extensions = [ "ext/extconf.rb" ]
24
+ s.required_ruby_version = ">= 2.4.0"
25
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple-proj
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hiroki Motoyoshi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-10-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: " Ruby extension library for PROJ 7\n"
14
+ email: ''
15
+ executables: []
16
+ extensions:
17
+ - ext/extconf.rb
18
+ extra_rdoc_files: []
19
+ files:
20
+ - API.md
21
+ - README.md
22
+ - Rakefile
23
+ - ext/extconf.rb
24
+ - ext/rb_proj.c
25
+ - ext/rb_proj.h
26
+ - lib/simple-proj.rb
27
+ - simple-proj.gemspec
28
+ homepage: https://github.com/himotoyoshi/simple-proj
29
+ licenses:
30
+ - MIT
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.4.0
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 2.7.6
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: Ruby extension library for PROJ 7
52
+ test_files: []