rgeo-proj4 1.0.0.rc1 → 3.0.1
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 +4 -4
- data/ext/proj4_c_impl/extconf.rb +7 -2
- data/ext/proj4_c_impl/main.c +204 -87
- data/lib/rgeo/coord_sys/proj4.rb +59 -43
- data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +18 -15
- data/lib/rgeo/proj4.rb +2 -0
- data/lib/rgeo/proj4/version.rb +3 -1
- metadata +30 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e899f9ec9d4cb7036400cb716e4d414c87adf5b1b20fbcf081666d869af48ad
|
4
|
+
data.tar.gz: 423a52b4b72050a519b8df4c63f01058b608c9345cb0abc5e1bf2a33729c381b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59fda580463933b22228f0748d7ddbb38deefe04c2b01ea2979d1a2f15a2d565bfad6b3056f0f4ab9a27fa147df69e8eae9dec8dd1cd075c48c108bcce96858b
|
7
|
+
data.tar.gz: 1cd3d716d7c9ba6c832d3703abb2c6ddefa87985e75034ed38458bd447f6afd32e02a72547ff2014db52db0bd0d3c3709c776e97698dc0e0a792eb33168b0314
|
data/ext/proj4_c_impl/extconf.rb
CHANGED
@@ -45,14 +45,19 @@ else
|
|
45
45
|
|
46
46
|
found_proj_ = false
|
47
47
|
header_dirs_, lib_dirs_ = dir_config("proj", header_dirs_, lib_dirs_)
|
48
|
-
if have_header("
|
48
|
+
if have_header("proj.h")
|
49
49
|
$libs << " -lproj"
|
50
|
-
|
50
|
+
|
51
|
+
if have_func("proj_create", "proj.h")
|
51
52
|
found_proj_ = true
|
53
|
+
have_func("proj_create_crs_to_crs_from_pj", "proj.h")
|
54
|
+
have_func("proj_normalize_for_visualization", "proj.h")
|
52
55
|
else
|
53
56
|
$libs.gsub!(" -lproj", "")
|
54
57
|
end
|
55
58
|
end
|
59
|
+
have_func("rb_gc_mark_movable")
|
60
|
+
|
56
61
|
unless found_proj_
|
57
62
|
puts "**** WARNING: Unable to find Proj headers or Proj version is too old."
|
58
63
|
puts "**** Compiling without Proj support."
|
data/ext/proj4_c_impl/main.c
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
/*
|
2
2
|
Main initializer for Proj4 wrapper
|
3
3
|
*/
|
4
|
-
|
5
|
-
#ifdef
|
6
|
-
#ifdef
|
4
|
+
#ifdef HAVE_PROJ_H
|
5
|
+
#ifdef HAVE_PROJ_CREATE
|
6
|
+
#ifdef HAVE_PROJ_CREATE_CRS_TO_CRS_FROM_PJ
|
7
|
+
#ifdef HAVE_PROJ_NORMALIZE_FOR_VISUALIZATION
|
7
8
|
#define RGEO_PROJ4_SUPPORTED
|
8
9
|
#endif
|
9
10
|
#endif
|
11
|
+
#endif
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
15
|
+
#define mark rb_gc_mark_movable
|
16
|
+
#else
|
17
|
+
#define mark rb_gc_mark
|
18
|
+
#endif
|
10
19
|
|
11
20
|
#ifdef __cplusplus
|
12
21
|
#define RGEO_BEGIN_C extern "C" {
|
@@ -20,7 +29,7 @@
|
|
20
29
|
#ifdef RGEO_PROJ4_SUPPORTED
|
21
30
|
|
22
31
|
#include <ruby.h>
|
23
|
-
#include <
|
32
|
+
#include <proj.h>
|
24
33
|
|
25
34
|
#endif
|
26
35
|
|
@@ -30,78 +39,112 @@ RGEO_BEGIN_C
|
|
30
39
|
|
31
40
|
#ifdef RGEO_PROJ4_SUPPORTED
|
32
41
|
|
42
|
+
#if PROJ_VERSION_MAJOR == 6 && PROJ_VERSION_MINOR < 3
|
43
|
+
#define WKT_TYPE PJ_WKT2_2018
|
44
|
+
#else
|
45
|
+
#define WKT_TYPE PJ_WKT2_2019
|
46
|
+
#endif
|
33
47
|
|
34
48
|
typedef struct {
|
35
|
-
|
49
|
+
PJ *pj;
|
36
50
|
VALUE original_str;
|
37
51
|
char uses_radians;
|
38
52
|
} RGeo_Proj4Data;
|
39
53
|
|
40
54
|
|
41
|
-
|
55
|
+
// Destroy function for proj data.
|
56
|
+
static void rgeo_proj4_free(void *ptr)
|
57
|
+
{
|
58
|
+
RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
|
59
|
+
if(data->pj){
|
60
|
+
proj_destroy(data->pj);
|
61
|
+
}
|
62
|
+
free(data);
|
63
|
+
}
|
42
64
|
|
65
|
+
static size_t rgeo_proj4_memsize(const void *ptr)
|
66
|
+
{
|
67
|
+
size_t size = 0;
|
68
|
+
const RGeo_Proj4Data *data = (const RGeo_Proj4Data *)ptr;
|
43
69
|
|
44
|
-
|
70
|
+
size += sizeof(*data);
|
71
|
+
if(data->pj){
|
72
|
+
size += sizeof(data->pj);
|
73
|
+
}
|
74
|
+
return size;
|
75
|
+
}
|
45
76
|
|
46
|
-
static void
|
77
|
+
static void rgeo_proj4_mark(void *ptr)
|
47
78
|
{
|
48
|
-
|
49
|
-
|
79
|
+
RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
|
80
|
+
if(!NIL_P(data->original_str)){
|
81
|
+
mark(data->original_str);
|
50
82
|
}
|
51
|
-
free(data);
|
52
83
|
}
|
53
84
|
|
85
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
86
|
+
static void rgeo_proj4_compact(void *ptr)
|
87
|
+
{
|
88
|
+
RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
|
89
|
+
if(data && !NIL_P(data->original_str)){
|
90
|
+
data->original_str = rb_gc_location(data->original_str);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
#endif
|
54
94
|
|
55
|
-
static void
|
95
|
+
static void rgeo_proj4_clear_struct(RGeo_Proj4Data *data)
|
56
96
|
{
|
57
|
-
if
|
58
|
-
|
97
|
+
if(data->pj){
|
98
|
+
proj_destroy(data->pj);
|
99
|
+
data->pj = NULL;
|
100
|
+
data->original_str = Qnil;
|
59
101
|
}
|
60
102
|
}
|
61
103
|
|
104
|
+
static const rb_data_type_t rgeo_proj4_data_type = {
|
105
|
+
"RGeo::CoordSys::Proj4",
|
106
|
+
{rgeo_proj4_mark, rgeo_proj4_free, rgeo_proj4_memsize,
|
107
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
108
|
+
rgeo_proj4_compact
|
109
|
+
#endif
|
110
|
+
},
|
111
|
+
0, 0,
|
112
|
+
RUBY_TYPED_FREE_IMMEDIATELY};
|
62
113
|
|
63
|
-
static VALUE
|
114
|
+
static VALUE rgeo_proj4_data_alloc(VALUE self)
|
64
115
|
{
|
65
116
|
VALUE result;
|
66
|
-
RGeo_Proj4Data*
|
117
|
+
RGeo_Proj4Data *data = ALLOC(RGeo_Proj4Data);
|
67
118
|
|
68
119
|
result = Qnil;
|
69
|
-
|
70
|
-
if
|
120
|
+
|
121
|
+
if(data){
|
71
122
|
data->pj = NULL;
|
72
123
|
data->original_str = Qnil;
|
73
124
|
data->uses_radians = 0;
|
74
|
-
result =
|
125
|
+
result = TypedData_Wrap_Struct(self, &rgeo_proj4_data_type, data);
|
75
126
|
}
|
76
127
|
return result;
|
77
128
|
}
|
78
129
|
|
79
|
-
|
80
130
|
static VALUE method_proj4_initialize_copy(VALUE self, VALUE orig)
|
81
131
|
{
|
82
|
-
RGeo_Proj4Data*
|
83
|
-
|
84
|
-
|
85
|
-
char* str;
|
132
|
+
RGeo_Proj4Data *self_data;
|
133
|
+
RGeo_Proj4Data *orig_data;
|
134
|
+
const char* str;
|
86
135
|
|
87
136
|
// Clear out any existing value
|
88
|
-
|
89
|
-
|
90
|
-
if (pj) {
|
91
|
-
pj_free(pj);
|
92
|
-
self_data->pj = NULL;
|
93
|
-
self_data->original_str = Qnil;
|
94
|
-
}
|
137
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
|
138
|
+
rgeo_proj4_clear_struct(self_data);
|
95
139
|
|
96
140
|
// Copy value from orig
|
97
|
-
|
141
|
+
TypedData_Get_Struct(orig, RGeo_Proj4Data, &rgeo_proj4_data_type, orig_data);
|
98
142
|
if (!NIL_P(orig_data->original_str)) {
|
99
|
-
self_data->pj =
|
143
|
+
self_data->pj = proj_create(PJ_DEFAULT_CTX, StringValuePtr(orig_data->original_str));
|
100
144
|
}
|
101
145
|
else {
|
102
|
-
str =
|
103
|
-
self_data->pj =
|
104
|
-
pj_dalloc(str);
|
146
|
+
str = proj_as_proj_string(PJ_DEFAULT_CTX, orig_data->pj, PJ_PROJ_4, NULL);
|
147
|
+
self_data->pj = proj_create(PJ_DEFAULT_CTX, str);
|
105
148
|
}
|
106
149
|
self_data->original_str = orig_data->original_str;
|
107
150
|
self_data->uses_radians = orig_data->uses_radians;
|
@@ -112,22 +155,16 @@ static VALUE method_proj4_initialize_copy(VALUE self, VALUE orig)
|
|
112
155
|
|
113
156
|
static VALUE method_proj4_set_value(VALUE self, VALUE str, VALUE uses_radians)
|
114
157
|
{
|
115
|
-
RGeo_Proj4Data*
|
116
|
-
projPJ pj;
|
158
|
+
RGeo_Proj4Data *self_data;
|
117
159
|
|
118
160
|
Check_Type(str, T_STRING);
|
119
161
|
|
120
162
|
// Clear out any existing value
|
121
|
-
|
122
|
-
|
123
|
-
if (pj) {
|
124
|
-
pj_free(pj);
|
125
|
-
self_data->pj = NULL;
|
126
|
-
self_data->original_str = Qnil;
|
127
|
-
}
|
163
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
|
164
|
+
rgeo_proj4_clear_struct(self_data);
|
128
165
|
|
129
166
|
// Set new data
|
130
|
-
self_data->pj =
|
167
|
+
self_data->pj = proj_create(PJ_DEFAULT_CTX, StringValuePtr(str));
|
131
168
|
self_data->original_str = str;
|
132
169
|
self_data->uses_radians = RTEST(uses_radians) ? 1 : 0;
|
133
170
|
|
@@ -138,17 +175,18 @@ static VALUE method_proj4_set_value(VALUE self, VALUE str, VALUE uses_radians)
|
|
138
175
|
static VALUE method_proj4_get_geographic(VALUE self)
|
139
176
|
{
|
140
177
|
VALUE result;
|
141
|
-
RGeo_Proj4Data*
|
142
|
-
RGeo_Proj4Data*
|
178
|
+
RGeo_Proj4Data *new_data;
|
179
|
+
RGeo_Proj4Data *self_data;
|
143
180
|
|
144
181
|
result = Qnil;
|
145
182
|
new_data = ALLOC(RGeo_Proj4Data);
|
146
183
|
if (new_data) {
|
147
|
-
|
148
|
-
|
184
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
|
185
|
+
|
186
|
+
new_data->pj = proj_crs_get_geodetic_crs(PJ_DEFAULT_CTX, self_data->pj);
|
149
187
|
new_data->original_str = Qnil;
|
150
188
|
new_data->uses_radians = self_data->uses_radians;
|
151
|
-
result =
|
189
|
+
result = TypedData_Wrap_Struct(CLASS_OF(self), &rgeo_proj4_data_type, new_data);
|
152
190
|
}
|
153
191
|
return result;
|
154
192
|
}
|
@@ -156,44 +194,97 @@ static VALUE method_proj4_get_geographic(VALUE self)
|
|
156
194
|
|
157
195
|
static VALUE method_proj4_original_str(VALUE self)
|
158
196
|
{
|
159
|
-
|
197
|
+
RGeo_Proj4Data *data;
|
198
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
199
|
+
return data->original_str;
|
160
200
|
}
|
161
201
|
|
162
202
|
|
163
203
|
static VALUE method_proj4_uses_radians(VALUE self)
|
164
204
|
{
|
165
|
-
|
205
|
+
RGeo_Proj4Data *data;
|
206
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
207
|
+
return data->uses_radians ? Qtrue : Qfalse;
|
166
208
|
}
|
167
209
|
|
168
210
|
|
169
211
|
static VALUE method_proj4_canonical_str(VALUE self)
|
170
212
|
{
|
171
213
|
VALUE result;
|
172
|
-
|
173
|
-
char*
|
214
|
+
PJ *pj;
|
215
|
+
const char *str;
|
216
|
+
RGeo_Proj4Data *data;
|
174
217
|
|
175
218
|
result = Qnil;
|
176
|
-
|
219
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
220
|
+
pj = data->pj;
|
177
221
|
if (pj) {
|
178
|
-
str =
|
222
|
+
str = proj_as_proj_string(PJ_DEFAULT_CTX, pj, PJ_PROJ_4, NULL);
|
179
223
|
if (str) {
|
180
224
|
result = rb_str_new2(str);
|
181
|
-
pj_dalloc(str);
|
182
225
|
}
|
183
226
|
}
|
184
227
|
return result;
|
185
228
|
}
|
186
229
|
|
230
|
+
static VALUE method_proj4_wkt_str(VALUE self)
|
231
|
+
{
|
232
|
+
VALUE result;
|
233
|
+
PJ *pj;
|
234
|
+
const char *str;
|
235
|
+
RGeo_Proj4Data *data;
|
236
|
+
|
237
|
+
result = Qnil;
|
238
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
239
|
+
pj = data->pj;
|
240
|
+
if (pj) {
|
241
|
+
const char *const options[] = {"MULTILINE=NO", NULL};
|
242
|
+
str = proj_as_wkt(PJ_DEFAULT_CTX, pj, WKT_TYPE, options);
|
243
|
+
if(str){
|
244
|
+
result = rb_str_new2(str);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
return result;
|
248
|
+
}
|
249
|
+
|
250
|
+
static VALUE method_proj4_auth_name_str(VALUE self)
|
251
|
+
{
|
252
|
+
VALUE result;
|
253
|
+
PJ *pj;
|
254
|
+
const char *id;
|
255
|
+
const char *auth;
|
256
|
+
RGeo_Proj4Data *data;
|
257
|
+
|
258
|
+
result = Qnil;
|
259
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
260
|
+
pj = data->pj;
|
261
|
+
if (pj) {
|
262
|
+
auth = proj_get_id_auth_name(pj, 0);
|
263
|
+
id = proj_get_id_code(pj, 0);
|
264
|
+
if(id && auth){
|
265
|
+
result = rb_sprintf("%s:%s", auth, id);
|
266
|
+
}
|
267
|
+
}
|
268
|
+
return result;
|
269
|
+
}
|
187
270
|
|
188
271
|
static VALUE method_proj4_is_geographic(VALUE self)
|
189
272
|
{
|
190
273
|
VALUE result;
|
191
|
-
|
274
|
+
PJ *pj;
|
275
|
+
PJ_TYPE proj_type;
|
276
|
+
RGeo_Proj4Data *data;
|
192
277
|
|
193
278
|
result = Qnil;
|
194
|
-
|
279
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
280
|
+
pj = data->pj;
|
195
281
|
if (pj) {
|
196
|
-
|
282
|
+
proj_type = proj_get_type(pj);
|
283
|
+
if(proj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || proj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS){
|
284
|
+
result = Qtrue;
|
285
|
+
} else {
|
286
|
+
result = Qfalse;
|
287
|
+
}
|
197
288
|
}
|
198
289
|
return result;
|
199
290
|
}
|
@@ -202,12 +293,16 @@ static VALUE method_proj4_is_geographic(VALUE self)
|
|
202
293
|
static VALUE method_proj4_is_geocentric(VALUE self)
|
203
294
|
{
|
204
295
|
VALUE result;
|
205
|
-
|
296
|
+
PJ *pj;
|
297
|
+
PJ_TYPE proj_type;
|
298
|
+
RGeo_Proj4Data *data;
|
206
299
|
|
207
300
|
result = Qnil;
|
208
|
-
|
301
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
302
|
+
pj = data->pj;
|
209
303
|
if (pj) {
|
210
|
-
|
304
|
+
proj_type = proj_get_type(pj);
|
305
|
+
result = proj_type == PJ_TYPE_GEOCENTRIC_CRS ? Qtrue : Qfalse;
|
211
306
|
}
|
212
307
|
return result;
|
213
308
|
}
|
@@ -215,42 +310,62 @@ static VALUE method_proj4_is_geocentric(VALUE self)
|
|
215
310
|
|
216
311
|
static VALUE method_proj4_is_valid(VALUE self)
|
217
312
|
{
|
218
|
-
|
313
|
+
RGeo_Proj4Data *data;
|
314
|
+
TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
|
315
|
+
return data->pj ? Qtrue : Qfalse;
|
219
316
|
}
|
220
317
|
|
221
318
|
|
222
319
|
static VALUE cmethod_proj4_version(VALUE module)
|
223
320
|
{
|
224
|
-
return
|
321
|
+
return rb_sprintf("%d.%d.%d", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH);
|
225
322
|
}
|
226
323
|
|
227
324
|
|
228
325
|
static VALUE cmethod_proj4_transform(VALUE module, VALUE from, VALUE to, VALUE x, VALUE y, VALUE z)
|
229
326
|
{
|
230
327
|
VALUE result;
|
231
|
-
|
232
|
-
|
328
|
+
RGeo_Proj4Data *from_data;
|
329
|
+
RGeo_Proj4Data *to_data;
|
330
|
+
PJ *from_pj;
|
331
|
+
PJ *to_pj;
|
332
|
+
PJ *crs_to_crs;
|
333
|
+
PJ *gis_pj;
|
233
334
|
double xval, yval, zval;
|
234
|
-
|
335
|
+
PJ_COORD input;
|
336
|
+
PJ_COORD output;
|
235
337
|
|
236
338
|
result = Qnil;
|
237
|
-
|
238
|
-
|
339
|
+
TypedData_Get_Struct(from, RGeo_Proj4Data, &rgeo_proj4_data_type, from_data);
|
340
|
+
TypedData_Get_Struct(to, RGeo_Proj4Data, &rgeo_proj4_data_type, to_data);
|
341
|
+
from_pj = from_data->pj;
|
342
|
+
to_pj = to_data->pj;
|
239
343
|
if (from_pj && to_pj) {
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
344
|
+
crs_to_crs = proj_create_crs_to_crs_from_pj(PJ_DEFAULT_CTX, from_pj, to_pj, 0, NULL);
|
345
|
+
if(crs_to_crs){
|
346
|
+
// necessary to use proj_normalize_for_visualization so that we
|
347
|
+
// do not have to worry about the order of coordinates in every
|
348
|
+
// coord system.
|
349
|
+
gis_pj = proj_normalize_for_visualization(PJ_DEFAULT_CTX, crs_to_crs);
|
350
|
+
if(gis_pj){
|
351
|
+
proj_destroy(crs_to_crs);
|
352
|
+
crs_to_crs = gis_pj;
|
353
|
+
|
354
|
+
xval = rb_num2dbl(x);
|
355
|
+
yval = rb_num2dbl(y);
|
356
|
+
zval = NIL_P(z) ? 0.0 : rb_num2dbl(z);
|
357
|
+
|
358
|
+
input = proj_coord(xval, yval, zval, HUGE_VAL);
|
359
|
+
output = proj_trans(crs_to_crs, PJ_FWD, input);
|
360
|
+
|
361
|
+
result = rb_ary_new2(NIL_P(z) ? 2 : 3);
|
362
|
+
rb_ary_push(result, DBL2NUM(output.xyz.x));
|
363
|
+
rb_ary_push(result, DBL2NUM(output.xyz.y));
|
364
|
+
if(!NIL_P(z)){
|
365
|
+
rb_ary_push(result, DBL2NUM(output.xyz.z));
|
366
|
+
}
|
253
367
|
}
|
368
|
+
proj_destroy(crs_to_crs);
|
254
369
|
}
|
255
370
|
}
|
256
371
|
return result;
|
@@ -266,10 +381,10 @@ static VALUE cmethod_proj4_create(VALUE klass, VALUE str, VALUE uses_radians)
|
|
266
381
|
Check_Type(str, T_STRING);
|
267
382
|
data = ALLOC(RGeo_Proj4Data);
|
268
383
|
if (data) {
|
269
|
-
data->pj =
|
384
|
+
data->pj = proj_create(PJ_DEFAULT_CTX, StringValuePtr(str));
|
270
385
|
data->original_str = str;
|
271
386
|
data->uses_radians = RTEST(uses_radians) ? 1 : 0;
|
272
|
-
result =
|
387
|
+
result = TypedData_Wrap_Struct(klass, &rgeo_proj4_data_type, data);
|
273
388
|
}
|
274
389
|
return result;
|
275
390
|
}
|
@@ -285,12 +400,14 @@ static void rgeo_init_proj4()
|
|
285
400
|
coordsys_module = rb_define_module_under(rgeo_module, "CoordSys");
|
286
401
|
proj4_class = rb_define_class_under(coordsys_module, "Proj4", rb_cObject);
|
287
402
|
|
288
|
-
rb_define_alloc_func(proj4_class,
|
403
|
+
rb_define_alloc_func(proj4_class, rgeo_proj4_data_alloc);
|
289
404
|
rb_define_module_function(proj4_class, "_create", cmethod_proj4_create, 2);
|
290
405
|
rb_define_method(proj4_class, "initialize_copy", method_proj4_initialize_copy, 1);
|
291
406
|
rb_define_method(proj4_class, "_set_value", method_proj4_set_value, 2);
|
292
407
|
rb_define_method(proj4_class, "_original_str", method_proj4_original_str, 0);
|
293
408
|
rb_define_method(proj4_class, "_canonical_str", method_proj4_canonical_str, 0);
|
409
|
+
rb_define_method(proj4_class, "_as_text", method_proj4_wkt_str, 0);
|
410
|
+
rb_define_method(proj4_class, "_auth_name", method_proj4_auth_name_str, 0);
|
294
411
|
rb_define_method(proj4_class, "_valid?", method_proj4_is_valid, 0);
|
295
412
|
rb_define_method(proj4_class, "_geographic?", method_proj4_is_geographic, 0);
|
296
413
|
rb_define_method(proj4_class, "_geocentric?", method_proj4_is_geocentric, 0);
|
data/lib/rgeo/coord_sys/proj4.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# Proj4 wrapper for RGeo
|
@@ -39,10 +41,10 @@ module RGeo
|
|
39
41
|
# there are sometimes multiple ways to express a given coordinate
|
40
42
|
# system.
|
41
43
|
|
42
|
-
def eql?(
|
43
|
-
|
44
|
+
def eql?(other)
|
45
|
+
other.class == self.class && other.canonical_hash == canonical_hash && other._radians? == _radians?
|
44
46
|
end
|
45
|
-
|
47
|
+
alias == eql?
|
46
48
|
|
47
49
|
# Marshal support
|
48
50
|
|
@@ -76,9 +78,7 @@ module RGeo
|
|
76
78
|
def canonical_str
|
77
79
|
unless defined?(@canonical_str)
|
78
80
|
@canonical_str = _canonical_str
|
79
|
-
if @canonical_str.respond_to?(:force_encoding)
|
80
|
-
@canonical_str.force_encoding("US-ASCII")
|
81
|
-
end
|
81
|
+
@canonical_str.force_encoding("US-ASCII") if @canonical_str.respond_to?(:force_encoding)
|
82
82
|
end
|
83
83
|
@canonical_str
|
84
84
|
end
|
@@ -105,6 +105,21 @@ module RGeo
|
|
105
105
|
_original_str
|
106
106
|
end
|
107
107
|
|
108
|
+
# Returns the WKT representation of the CRS.
|
109
|
+
|
110
|
+
def as_text
|
111
|
+
_as_text
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns the string representing the authority and code of the
|
115
|
+
# CRS if it exists, nil otherwise.
|
116
|
+
#
|
117
|
+
# Ex. EPSG:4326
|
118
|
+
|
119
|
+
def auth_name
|
120
|
+
_auth_name
|
121
|
+
end
|
122
|
+
|
108
123
|
# Returns true if this Proj4 object is a geographic (lat-long)
|
109
124
|
# coordinate system.
|
110
125
|
|
@@ -172,9 +187,7 @@ module RGeo
|
|
172
187
|
if defn_.is_a?(::Hash)
|
173
188
|
defn_ = defn_.map { |k_, v_| v_ ? "+#{k_}=#{v_}" : "+#{k_}" }.join(" ")
|
174
189
|
end
|
175
|
-
|
176
|
-
defn_ = defn_.sub(/^(\s*)/, '\1+').gsub(/(\s+)([^+\s])/, '\1+\2')
|
177
|
-
end
|
190
|
+
|
178
191
|
result_ = _create(defn_, opts_[:radians])
|
179
192
|
result_ = nil unless result_._valid?
|
180
193
|
end
|
@@ -200,9 +213,7 @@ module RGeo
|
|
200
213
|
|
201
214
|
def new(defn_, opts_ = {})
|
202
215
|
result_ = create(defn_, opts_)
|
203
|
-
unless result_
|
204
|
-
raise Error::UnsupportedOperation, "Proj4 not supported in this installation"
|
205
|
-
end
|
216
|
+
raise Error::UnsupportedOperation, "Proj4 not supported in this installation" unless result_
|
206
217
|
result_
|
207
218
|
end
|
208
219
|
|
@@ -212,14 +223,15 @@ module RGeo
|
|
212
223
|
# or three elements.
|
213
224
|
|
214
225
|
def transform_coords(from_proj_, to_proj_, x_, y_, z_ = nil)
|
215
|
-
if
|
216
|
-
x_ *= ImplHelper::Math::
|
217
|
-
y_ *= ImplHelper::Math::
|
226
|
+
if from_proj_._radians? && from_proj_._geographic?
|
227
|
+
x_ *= ImplHelper::Math::DEGREES_PER_RADIAN
|
228
|
+
y_ *= ImplHelper::Math::DEGREES_PER_RADIAN
|
218
229
|
end
|
230
|
+
|
219
231
|
result_ = _transform_coords(from_proj_, to_proj_, x_, y_, z_)
|
220
|
-
if result_ &&
|
221
|
-
result_[0] *= ImplHelper::Math::
|
222
|
-
result_[1] *= ImplHelper::Math::
|
232
|
+
if result_ && to_proj_._radians? && to_proj_._geographic?
|
233
|
+
result_[0] *= ImplHelper::Math::RADIANS_PER_DEGREE
|
234
|
+
result_[1] *= ImplHelper::Math::RADIANS_PER_DEGREE
|
223
235
|
end
|
224
236
|
result_
|
225
237
|
end
|
@@ -233,27 +245,29 @@ module RGeo
|
|
233
245
|
def transform(from_proj_, from_geometry_, to_proj_, to_factory_)
|
234
246
|
case from_geometry_
|
235
247
|
when Feature::Point
|
236
|
-
|
248
|
+
transform_point(from_proj_, from_geometry_, to_proj_, to_factory_)
|
237
249
|
when Feature::Line
|
238
|
-
to_factory_.line(from_geometry_.points.map { |p_|
|
250
|
+
to_factory_.line(from_geometry_.points.map { |p_| transform_point(from_proj_, p_, to_proj_, to_factory_) })
|
239
251
|
when Feature::LinearRing
|
240
|
-
|
252
|
+
transform_linear_ring(from_proj_, from_geometry_, to_proj_, to_factory_)
|
241
253
|
when Feature::LineString
|
242
|
-
to_factory_.line_string(from_geometry_.points.map { |p_|
|
254
|
+
to_factory_.line_string(from_geometry_.points.map { |p_| transform_point(from_proj_, p_, to_proj_, to_factory_) })
|
243
255
|
when Feature::Polygon
|
244
|
-
|
256
|
+
transform_polygon(from_proj_, from_geometry_, to_proj_, to_factory_)
|
245
257
|
when Feature::MultiPoint
|
246
|
-
to_factory_.multi_point(from_geometry_.map { |p_|
|
258
|
+
to_factory_.multi_point(from_geometry_.map { |p_| transform_point(from_proj_, p_, to_proj_, to_factory_) })
|
247
259
|
when Feature::MultiLineString
|
248
260
|
to_factory_.multi_line_string(from_geometry_.map { |g_| transform(from_proj_, g_, to_proj_, to_factory_) })
|
249
261
|
when Feature::MultiPolygon
|
250
|
-
to_factory_.multi_polygon(from_geometry_.map { |p_|
|
262
|
+
to_factory_.multi_polygon(from_geometry_.map { |p_| transform_polygon(from_proj_, p_, to_proj_, to_factory_) })
|
251
263
|
when Feature::GeometryCollection
|
252
264
|
to_factory_.collection(from_geometry_.map { |g_| transform(from_proj_, g_, to_proj_, to_factory_) })
|
253
265
|
end
|
254
266
|
end
|
255
267
|
|
256
|
-
|
268
|
+
private
|
269
|
+
|
270
|
+
def transform_point(from_proj_, from_point_, to_proj_, to_factory_)
|
257
271
|
from_factory_ = from_point_.factory
|
258
272
|
from_has_z_ = from_factory_.property(:has_z_coordinate)
|
259
273
|
from_has_m_ = from_factory_.property(:has_m_coordinate)
|
@@ -261,30 +275,32 @@ module RGeo
|
|
261
275
|
to_has_m_ = to_factory_.property(:has_m_coordinate)
|
262
276
|
x_ = from_point_.x
|
263
277
|
y_ = from_point_.y
|
264
|
-
if
|
265
|
-
x_ *= ImplHelper::Math::
|
266
|
-
y_ *= ImplHelper::Math::
|
278
|
+
if from_proj_._radians? && from_proj_._geographic?
|
279
|
+
x_ *= ImplHelper::Math::DEGREES_PER_RADIAN
|
280
|
+
y_ *= ImplHelper::Math::DEGREES_PER_RADIAN
|
267
281
|
end
|
268
282
|
coords_ = _transform_coords(from_proj_, to_proj_, x_, y_, from_has_z_ ? from_point_.z : nil)
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
283
|
+
return unless coords_
|
284
|
+
|
285
|
+
if to_proj_._radians? && to_proj_._geographic?
|
286
|
+
coords_[0] *= ImplHelper::Math::RADIANS_PER_DEGREE
|
287
|
+
coords_[1] *= ImplHelper::Math::RADIANS_PER_DEGREE
|
288
|
+
end
|
289
|
+
extras_ = []
|
290
|
+
extras_ << coords_[2].to_f if to_has_z_
|
291
|
+
if to_has_m_
|
292
|
+
extras_ << from_has_m_ ? from_point_.m : 0.0
|
278
293
|
end
|
294
|
+
to_factory_.point(coords_[0], coords_[1], *extras_)
|
279
295
|
end
|
280
296
|
|
281
|
-
def
|
282
|
-
to_factory_.linear_ring(from_ring_.points[0..-2].map { |p_|
|
297
|
+
def transform_linear_ring(from_proj_, from_ring_, to_proj_, to_factory_)
|
298
|
+
to_factory_.linear_ring(from_ring_.points[0..-2].map { |p_| transform_point(from_proj_, p_, to_proj_, to_factory_) })
|
283
299
|
end
|
284
300
|
|
285
|
-
def
|
286
|
-
ext_ =
|
287
|
-
int_ = from_polygon_.interior_rings.map { |r_|
|
301
|
+
def transform_polygon(from_proj_, from_polygon_, to_proj_, to_factory_)
|
302
|
+
ext_ = transform_linear_ring(from_proj_, from_polygon_.exterior_ring, to_proj_, to_factory_)
|
303
|
+
int_ = from_polygon_.interior_rings.map { |r_| transform_linear_ring(from_proj_, r_, to_proj_, to_factory_) }
|
288
304
|
to_factory_.polygon(ext_, int_)
|
289
305
|
end
|
290
306
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -----------------------------------------------------------------------------
|
2
4
|
#
|
3
5
|
# SRS database interface
|
@@ -62,7 +64,7 @@ module RGeo
|
|
62
64
|
when :read_all
|
63
65
|
@populate_state = 1
|
64
66
|
when :preload
|
65
|
-
|
67
|
+
search_file(nil)
|
66
68
|
@populate_state = 2
|
67
69
|
else
|
68
70
|
@populate_state = 0
|
@@ -77,14 +79,15 @@ module RGeo
|
|
77
79
|
|
78
80
|
def get(ident_)
|
79
81
|
ident_ = ident_.to_s
|
80
|
-
return @cache[ident_] if @cache
|
82
|
+
return @cache[ident_] if @cache&.include?(ident_)
|
81
83
|
result_ = nil
|
82
|
-
|
83
|
-
|
84
|
+
case @populate_state
|
85
|
+
when 0
|
86
|
+
data_ = search_file(ident_)
|
84
87
|
result_ = Entry.new(ident_, authority: @authority, authority_code: @authority ? ident_ : nil, name: data_[1], proj4: data_[2]) if data_
|
85
88
|
@cache[ident_] = result_ if @cache
|
86
|
-
|
87
|
-
|
89
|
+
when 1
|
90
|
+
search_file(nil)
|
88
91
|
result_ = @cache[ident_]
|
89
92
|
@populate_state = 2
|
90
93
|
end
|
@@ -94,27 +97,27 @@ module RGeo
|
|
94
97
|
# Clear the cache if one exists.
|
95
98
|
|
96
99
|
def clear_cache
|
97
|
-
@cache
|
100
|
+
@cache&.clear
|
98
101
|
@populate_state = 1 if @populate_state == 2
|
99
102
|
end
|
100
103
|
|
101
|
-
|
104
|
+
private
|
105
|
+
|
106
|
+
def search_file(ident_)
|
102
107
|
::File.open(@path) do |file_|
|
103
108
|
cur_name_ = nil
|
104
109
|
cur_ident_ = nil
|
105
110
|
cur_text_ = nil
|
106
111
|
file_.each do |line_|
|
107
112
|
line_.strip!
|
108
|
-
if (comment_delim_ = line_.index(
|
113
|
+
if (comment_delim_ = line_.index("#"))
|
109
114
|
cur_name_ = line_[comment_delim_ + 1..-1].strip
|
110
115
|
line_ = line_[0..comment_delim_ - 1].strip
|
111
116
|
end
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
line_ = Regexp.last_match(2).strip
|
117
|
-
end
|
117
|
+
if !cur_ident_ && (line_ =~ /^<(\w+)>(.*)/)
|
118
|
+
cur_ident_ = Regexp.last_match(1)
|
119
|
+
cur_text_ = []
|
120
|
+
line_ = Regexp.last_match(2).strip
|
118
121
|
end
|
119
122
|
next unless cur_ident_
|
120
123
|
if line_[-2..-1] == "<>"
|
data/lib/rgeo/proj4.rb
CHANGED
data/lib/rgeo/proj4/version.rb
CHANGED
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:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tee Parham, Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rgeo
|
@@ -16,42 +16,56 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '2.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:
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '5.14'
|
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: '
|
40
|
+
version: '5.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.9.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.9.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '13.0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '13.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake-compiler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,19 +81,19 @@ dependencies:
|
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '1.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: rubocop
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
89
|
+
version: 1.8.1
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
96
|
+
version: 1.8.1
|
83
97
|
description: Proj4 extension for rgeo.
|
84
98
|
email:
|
85
99
|
- parhameter@gmail.com, dazuma@gmail.com
|
@@ -107,15 +121,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
121
|
requirements:
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: 2.
|
124
|
+
version: 2.5.0
|
111
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
126
|
requirements:
|
113
|
-
- - "
|
127
|
+
- - ">="
|
114
128
|
- !ruby/object:Gem::Version
|
115
|
-
version:
|
129
|
+
version: '0'
|
116
130
|
requirements: []
|
117
|
-
|
118
|
-
rubygems_version: 2.7.0
|
131
|
+
rubygems_version: 3.1.4
|
119
132
|
signing_key:
|
120
133
|
specification_version: 4
|
121
134
|
summary: Proj4 extension for rgeo.
|