simple-proj 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []