rgeo-proj4 3.1.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,42 +1,19 @@
1
1
  /*
2
2
  Main initializer for Proj4 wrapper
3
3
  */
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
8
- #define RGEO_PROJ4_SUPPORTED
9
- #endif
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
19
-
20
- #ifdef __cplusplus
21
- #define RGEO_BEGIN_C extern "C" {
22
- #define RGEO_END_C }
23
- #else
24
- #define RGEO_BEGIN_C
25
- #define RGEO_END_C
26
- #endif
27
4
 
5
+ #include "preface.h"
28
6
 
29
7
  #ifdef RGEO_PROJ4_SUPPORTED
30
8
 
31
- #include <ruby.h>
9
+ #include "errors.h"
32
10
  #include <proj.h>
11
+ #include <ruby.h>
33
12
 
34
13
  #endif
35
14
 
36
-
37
15
  RGEO_BEGIN_C
38
16
 
39
-
40
17
  #ifdef RGEO_PROJ4_SUPPORTED
41
18
 
42
19
  #if PROJ_VERSION_MAJOR == 6 && PROJ_VERSION_MINOR < 3
@@ -55,72 +32,63 @@ typedef struct {
55
32
  PJ *crs_to_crs;
56
33
  } RGeo_CRSToCRSData;
57
34
 
58
-
59
35
  // Destroy function for proj data.
60
- static void rgeo_proj4_free(void *ptr)
61
- {
36
+ static void rgeo_proj4_free(void *ptr) {
62
37
  RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
63
- if(data->pj){
38
+ if (data->pj) {
64
39
  proj_destroy(data->pj);
65
40
  }
66
- free(data);
41
+ FREE(data);
67
42
  }
68
43
 
69
44
  // Destroy function for crs_to_crs data.
70
- static void rgeo_crs_to_crs_free(void *ptr)
71
- {
45
+ static void rgeo_crs_to_crs_free(void *ptr) {
72
46
  RGeo_CRSToCRSData *data = (RGeo_CRSToCRSData *)ptr;
73
- if(data->crs_to_crs){
47
+ if (data->crs_to_crs) {
74
48
  proj_destroy(data->crs_to_crs);
75
49
  }
76
- free(data);
50
+ FREE(data);
77
51
  }
78
52
 
79
-
80
- static size_t rgeo_proj4_memsize(const void *ptr)
81
- {
53
+ static size_t rgeo_proj4_memsize(const void *ptr) {
82
54
  size_t size = 0;
83
55
  const RGeo_Proj4Data *data = (const RGeo_Proj4Data *)ptr;
84
56
 
85
57
  size += sizeof(*data);
86
- if(data->pj){
58
+ if (data->pj) {
87
59
  size += sizeof(data->pj);
88
60
  }
89
61
  return size;
90
62
  }
91
63
 
92
- static size_t rgeo_crs_to_crs_memsize(const void *ptr)
93
- {
64
+ static size_t rgeo_crs_to_crs_memsize(const void *ptr) {
94
65
  size_t size = 0;
95
66
  const RGeo_CRSToCRSData *data = (const RGeo_CRSToCRSData *)ptr;
96
67
  size += sizeof(*data);
97
- if(data->crs_to_crs){
68
+ if (data->crs_to_crs) {
98
69
  size += sizeof(data->crs_to_crs);
99
70
  }
100
71
  return size;
101
72
  }
102
73
 
103
- static void rgeo_proj4_mark(void *ptr)
104
- {
74
+ static void rgeo_proj4_mark(void *ptr) {
105
75
  RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
106
- if(!NIL_P(data->original_str)){
76
+ if (!NIL_P(data->original_str)) {
107
77
  mark(data->original_str);
108
78
  }
109
79
  }
110
80
 
111
81
  #ifdef HAVE_RB_GC_MARK_MOVABLE
112
- static void rgeo_proj4_compact(void *ptr)
113
- {
82
+ static void rgeo_proj4_compact(void *ptr) {
114
83
  RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
115
- if(data && !NIL_P(data->original_str)){
84
+ if (data && !NIL_P(data->original_str)) {
116
85
  data->original_str = rb_gc_location(data->original_str);
117
86
  }
118
87
  }
119
88
  #endif
120
89
 
121
- static void rgeo_proj4_clear_struct(RGeo_Proj4Data *data)
122
- {
123
- if(data->pj){
90
+ static void rgeo_proj4_clear_struct(RGeo_Proj4Data *data) {
91
+ if (data->pj) {
124
92
  proj_destroy(data->pj);
125
93
  data->pj = NULL;
126
94
  data->original_str = Qnil;
@@ -131,26 +99,27 @@ static const rb_data_type_t rgeo_proj4_data_type = {
131
99
  "RGeo::CoordSys::Proj4",
132
100
  {rgeo_proj4_mark, rgeo_proj4_free, rgeo_proj4_memsize,
133
101
  #ifdef HAVE_RB_GC_MARK_MOVABLE
134
- rgeo_proj4_compact
102
+ rgeo_proj4_compact
135
103
  #endif
136
104
  },
137
- 0, 0,
105
+ 0,
106
+ 0,
138
107
  RUBY_TYPED_FREE_IMMEDIATELY};
139
108
 
140
109
  static const rb_data_type_t rgeo_crs_to_crs_data_type = {
141
110
  "RGeo::CoordSys::CRSToCRS",
142
111
  {0, rgeo_crs_to_crs_free, rgeo_crs_to_crs_memsize},
143
- 0, 0,
112
+ 0,
113
+ 0,
144
114
  RUBY_TYPED_FREE_IMMEDIATELY};
145
115
 
146
- static VALUE rgeo_proj4_data_alloc(VALUE self)
147
- {
116
+ static VALUE rgeo_proj4_data_alloc(VALUE self) {
148
117
  VALUE result;
149
118
  RGeo_Proj4Data *data = ALLOC(RGeo_Proj4Data);
150
119
 
151
120
  result = Qnil;
152
121
 
153
- if(data){
122
+ if (data) {
154
123
  data->pj = NULL;
155
124
  data->original_str = Qnil;
156
125
  data->uses_radians = 0;
@@ -159,26 +128,23 @@ static VALUE rgeo_proj4_data_alloc(VALUE self)
159
128
  return result;
160
129
  }
161
130
 
162
-
163
- static VALUE rgeo_crs_to_crs_data_alloc(VALUE self)
164
- {
131
+ static VALUE rgeo_crs_to_crs_data_alloc(VALUE self) {
165
132
  VALUE result;
166
133
  RGeo_CRSToCRSData *data = ALLOC(RGeo_CRSToCRSData);
167
134
 
168
135
  result = Qnil;
169
136
 
170
- if(data){
137
+ if (data) {
171
138
  data->crs_to_crs = NULL;
172
139
  result = TypedData_Wrap_Struct(self, &rgeo_crs_to_crs_data_type, data);
173
140
  }
174
141
  return result;
175
142
  }
176
143
 
177
- static VALUE method_proj4_initialize_copy(VALUE self, VALUE orig)
178
- {
144
+ static VALUE method_proj4_initialize_copy(VALUE self, VALUE orig) {
179
145
  RGeo_Proj4Data *self_data;
180
146
  RGeo_Proj4Data *orig_data;
181
- const char* str;
147
+ const char *str;
182
148
 
183
149
  // Clear out any existing value
184
150
  TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
@@ -187,9 +153,9 @@ static VALUE method_proj4_initialize_copy(VALUE self, VALUE orig)
187
153
  // Copy value from orig
188
154
  TypedData_Get_Struct(orig, RGeo_Proj4Data, &rgeo_proj4_data_type, orig_data);
189
155
  if (!NIL_P(orig_data->original_str)) {
190
- self_data->pj = proj_create(PJ_DEFAULT_CTX, StringValuePtr(orig_data->original_str));
191
- }
192
- else {
156
+ self_data->pj =
157
+ proj_create(PJ_DEFAULT_CTX, StringValuePtr(orig_data->original_str));
158
+ } else {
193
159
  str = proj_as_proj_string(PJ_DEFAULT_CTX, orig_data->pj, PJ_PROJ_4, NULL);
194
160
  self_data->pj = proj_create(PJ_DEFAULT_CTX, str);
195
161
  }
@@ -199,9 +165,7 @@ static VALUE method_proj4_initialize_copy(VALUE self, VALUE orig)
199
165
  return self;
200
166
  }
201
167
 
202
-
203
- static VALUE method_proj4_set_value(VALUE self, VALUE str, VALUE uses_radians)
204
- {
168
+ static VALUE method_proj4_set_value(VALUE self, VALUE str, VALUE uses_radians) {
205
169
  RGeo_Proj4Data *self_data;
206
170
 
207
171
  Check_Type(str, T_STRING);
@@ -218,45 +182,48 @@ static VALUE method_proj4_set_value(VALUE self, VALUE str, VALUE uses_radians)
218
182
  return self;
219
183
  }
220
184
 
221
-
222
- static VALUE method_proj4_get_geographic(VALUE self)
223
- {
185
+ static VALUE method_proj4_get_geographic(VALUE self) {
224
186
  VALUE result;
225
187
  RGeo_Proj4Data *new_data;
226
188
  RGeo_Proj4Data *self_data;
189
+ PJ *geographic_proj;
227
190
 
228
191
  result = Qnil;
229
192
  new_data = ALLOC(RGeo_Proj4Data);
230
193
  if (new_data) {
231
- TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
194
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type,
195
+ self_data);
196
+
197
+ geographic_proj = proj_crs_get_geodetic_crs(PJ_DEFAULT_CTX, self_data->pj);
198
+ if (geographic_proj == 0) {
199
+ FREE(new_data);
200
+ rb_raise(rb_eRGeoInvalidProjectionError,
201
+ "Geographic CRS could not be created because the source "
202
+ "projection is not a CRS");
203
+ }
232
204
 
233
- new_data->pj = proj_crs_get_geodetic_crs(PJ_DEFAULT_CTX, self_data->pj);
205
+ new_data->pj = geographic_proj;
234
206
  new_data->original_str = Qnil;
235
207
  new_data->uses_radians = self_data->uses_radians;
236
- result = TypedData_Wrap_Struct(CLASS_OF(self), &rgeo_proj4_data_type, new_data);
208
+ result =
209
+ TypedData_Wrap_Struct(CLASS_OF(self), &rgeo_proj4_data_type, new_data);
237
210
  }
238
211
  return result;
239
212
  }
240
213
 
241
-
242
- static VALUE method_proj4_original_str(VALUE self)
243
- {
214
+ static VALUE method_proj4_original_str(VALUE self) {
244
215
  RGeo_Proj4Data *data;
245
216
  TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
246
217
  return data->original_str;
247
218
  }
248
219
 
249
-
250
- static VALUE method_proj4_uses_radians(VALUE self)
251
- {
220
+ static VALUE method_proj4_uses_radians(VALUE self) {
252
221
  RGeo_Proj4Data *data;
253
222
  TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
254
223
  return data->uses_radians ? Qtrue : Qfalse;
255
224
  }
256
225
 
257
-
258
- static VALUE method_proj4_canonical_str(VALUE self)
259
- {
226
+ static VALUE method_proj4_canonical_str(VALUE self) {
260
227
  VALUE result;
261
228
  PJ *pj;
262
229
  const char *str;
@@ -274,8 +241,7 @@ static VALUE method_proj4_canonical_str(VALUE self)
274
241
  return result;
275
242
  }
276
243
 
277
- static VALUE method_proj4_wkt_str(VALUE self)
278
- {
244
+ static VALUE method_proj4_wkt_str(VALUE self) {
279
245
  VALUE result;
280
246
  PJ *pj;
281
247
  const char *str;
@@ -287,15 +253,14 @@ static VALUE method_proj4_wkt_str(VALUE self)
287
253
  if (pj) {
288
254
  const char *const options[] = {"MULTILINE=NO", NULL};
289
255
  str = proj_as_wkt(PJ_DEFAULT_CTX, pj, WKT_TYPE, options);
290
- if(str){
256
+ if (str) {
291
257
  result = rb_str_new2(str);
292
258
  }
293
259
  }
294
260
  return result;
295
261
  }
296
262
 
297
- static VALUE method_proj4_auth_name_str(VALUE self)
298
- {
263
+ static VALUE method_proj4_auth_name_str(VALUE self) {
299
264
  VALUE result;
300
265
  PJ *pj;
301
266
  const char *id;
@@ -308,15 +273,67 @@ static VALUE method_proj4_auth_name_str(VALUE self)
308
273
  if (pj) {
309
274
  auth = proj_get_id_auth_name(pj, 0);
310
275
  id = proj_get_id_code(pj, 0);
311
- if(id && auth){
276
+ if (id && auth) {
312
277
  result = rb_sprintf("%s:%s", auth, id);
313
278
  }
314
279
  }
315
280
  return result;
316
281
  }
317
282
 
318
- static VALUE method_proj4_is_geographic(VALUE self)
319
- {
283
+ static VALUE method_proj4_axis_and_unit_info_str(VALUE self, VALUE dimension) {
284
+ VALUE result;
285
+ int dimension_index;
286
+ PJ *pj;
287
+ PJ *pj_cs;
288
+ const char *axis_info;
289
+ const char *unit_name;
290
+ RGeo_Proj4Data *data;
291
+
292
+ Check_Type(dimension, T_FIXNUM);
293
+
294
+ dimension_index = FIX2INT(dimension);
295
+ result = Qnil;
296
+
297
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
298
+ pj = data->pj;
299
+ if (pj) {
300
+ pj_cs = proj_crs_get_coordinate_system(PJ_DEFAULT_CTX, pj);
301
+ if (pj_cs) {
302
+ if (proj_cs_get_axis_info(PJ_DEFAULT_CTX, pj_cs, dimension_index,
303
+ &axis_info, NULL, NULL, NULL, &unit_name, NULL,
304
+ NULL)) {
305
+ result = rb_sprintf("%s:%s", axis_info, unit_name);
306
+ }
307
+
308
+ proj_destroy(pj_cs);
309
+ }
310
+ }
311
+ return result;
312
+ }
313
+
314
+ static VALUE method_proj4_axis_count(VALUE self) {
315
+ VALUE result;
316
+ PJ *pj;
317
+ PJ *pj_cs;
318
+ int count;
319
+ RGeo_Proj4Data *data;
320
+
321
+ result = Qnil;
322
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
323
+ pj = data->pj;
324
+ if (pj) {
325
+ pj_cs = proj_crs_get_coordinate_system(PJ_DEFAULT_CTX, pj);
326
+ if (pj_cs) {
327
+ count = proj_cs_get_axis_count(PJ_DEFAULT_CTX, pj_cs);
328
+ result = INT2FIX(count);
329
+
330
+ proj_destroy(pj_cs);
331
+ }
332
+ }
333
+ return result;
334
+ }
335
+
336
+ static VALUE method_proj4_is_geographic(VALUE self) {
320
337
  VALUE result;
321
338
  PJ *pj;
322
339
  PJ_TYPE proj_type;
@@ -327,7 +344,8 @@ static VALUE method_proj4_is_geographic(VALUE self)
327
344
  pj = data->pj;
328
345
  if (pj) {
329
346
  proj_type = proj_get_type(pj);
330
- if(proj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || proj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS){
347
+ if (proj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS ||
348
+ proj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS) {
331
349
  result = Qtrue;
332
350
  } else {
333
351
  result = Qfalse;
@@ -336,9 +354,7 @@ static VALUE method_proj4_is_geographic(VALUE self)
336
354
  return result;
337
355
  }
338
356
 
339
-
340
- static VALUE method_proj4_is_geocentric(VALUE self)
341
- {
357
+ static VALUE method_proj4_is_geocentric(VALUE self) {
342
358
  VALUE result;
343
359
  PJ *pj;
344
360
  PJ_TYPE proj_type;
@@ -354,24 +370,43 @@ static VALUE method_proj4_is_geocentric(VALUE self)
354
370
  return result;
355
371
  }
356
372
 
373
+ static VALUE method_proj4_is_projected(VALUE self) {
374
+ VALUE result;
375
+ PJ *pj;
376
+ PJ_TYPE proj_type;
377
+ RGeo_Proj4Data *data;
378
+
379
+ result = Qnil;
380
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
381
+ pj = data->pj;
382
+ if (pj) {
383
+ proj_type = proj_get_type(pj);
384
+ result = proj_type == PJ_TYPE_PROJECTED_CRS ? Qtrue : Qfalse;
385
+ }
386
+ return result;
387
+ }
357
388
 
358
- static VALUE method_proj4_is_valid(VALUE self)
359
- {
389
+ static VALUE method_proj4_is_valid(VALUE self) {
360
390
  RGeo_Proj4Data *data;
361
391
  TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
362
392
  return data->pj ? Qtrue : Qfalse;
363
393
  }
364
394
 
395
+ static VALUE method_proj4_is_crs(VALUE self) {
396
+ RGeo_Proj4Data *self_data;
365
397
 
366
- static VALUE cmethod_proj4_version(VALUE module)
367
- {
368
- return rb_sprintf("%d.%d.%d", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH);
398
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
399
+ return proj_is_crs(self_data->pj) ? Qtrue : Qfalse;
400
+ }
401
+
402
+ static VALUE cmethod_proj4_version(VALUE module) {
403
+ return rb_sprintf("%d.%d.%d", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR,
404
+ PROJ_VERSION_PATCH);
369
405
  }
370
406
 
371
- static VALUE cmethod_proj4_create(VALUE klass, VALUE str, VALUE uses_radians)
372
- {
407
+ static VALUE cmethod_proj4_create(VALUE klass, VALUE str, VALUE uses_radians) {
373
408
  VALUE result;
374
- RGeo_Proj4Data* data;
409
+ RGeo_Proj4Data *data;
375
410
 
376
411
  result = Qnil;
377
412
  Check_Type(str, T_STRING);
@@ -385,8 +420,7 @@ static VALUE cmethod_proj4_create(VALUE klass, VALUE str, VALUE uses_radians)
385
420
  return result;
386
421
  }
387
422
 
388
- static VALUE cmethod_crs_to_crs_create(VALUE klass, VALUE from, VALUE to)
389
- {
423
+ static VALUE cmethod_crs_to_crs_create(VALUE klass, VALUE from, VALUE to) {
390
424
  VALUE result;
391
425
  RGeo_Proj4Data *from_data;
392
426
  RGeo_Proj4Data *to_data;
@@ -395,33 +429,39 @@ static VALUE cmethod_crs_to_crs_create(VALUE klass, VALUE from, VALUE to)
395
429
  PJ *to_pj;
396
430
  PJ *gis_pj;
397
431
  PJ *crs_to_crs;
398
- RGeo_CRSToCRSData* data;
432
+ RGeo_CRSToCRSData *data;
399
433
 
400
434
  TypedData_Get_Struct(from, RGeo_Proj4Data, &rgeo_proj4_data_type, from_data);
401
435
  TypedData_Get_Struct(to, RGeo_Proj4Data, &rgeo_proj4_data_type, to_data);
402
436
  from_pj = from_data->pj;
403
437
  to_pj = to_data->pj;
404
- crs_to_crs = proj_create_crs_to_crs_from_pj(PJ_DEFAULT_CTX, from_pj, to_pj, 0, NULL);
438
+ crs_to_crs =
439
+ proj_create_crs_to_crs_from_pj(PJ_DEFAULT_CTX, from_pj, to_pj, 0, NULL);
440
+
441
+ // check for invalid transformation
442
+ if (crs_to_crs == 0) {
443
+ rb_raise(rb_eRGeoInvalidProjectionError,
444
+ "CRSToCRS could not be created from input projections");
445
+ }
405
446
 
406
447
  // necessary to use proj_normalize_for_visualization so that we
407
448
  // do not have to worry about the order of coordinates in every
408
449
  // coord system
409
450
  gis_pj = proj_normalize_for_visualization(PJ_DEFAULT_CTX, crs_to_crs);
410
- if(gis_pj){
451
+ if (gis_pj) {
411
452
  proj_destroy(crs_to_crs);
412
453
  crs_to_crs = gis_pj;
413
454
  }
414
455
  data = ALLOC(RGeo_CRSToCRSData);
415
- if (data){
456
+ if (data) {
416
457
  data->crs_to_crs = crs_to_crs;
417
458
  result = TypedData_Wrap_Struct(klass, &rgeo_crs_to_crs_data_type, data);
418
459
  }
419
460
  return result;
420
461
  }
421
462
 
422
-
423
- static VALUE method_crs_to_crs_transform(VALUE self, VALUE x, VALUE y, VALUE z)
424
- {
463
+ static VALUE method_crs_to_crs_transform(VALUE self, VALUE x, VALUE y,
464
+ VALUE z) {
425
465
  VALUE result;
426
466
  RGeo_CRSToCRSData *crs_to_crs_data;
427
467
  PJ *crs_to_crs_pj;
@@ -430,9 +470,10 @@ static VALUE method_crs_to_crs_transform(VALUE self, VALUE x, VALUE y, VALUE z)
430
470
  PJ_COORD output;
431
471
 
432
472
  result = Qnil;
433
- TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type, crs_to_crs_data);
473
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type,
474
+ crs_to_crs_data);
434
475
  crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
435
- if(crs_to_crs_pj){
476
+ if (crs_to_crs_pj) {
436
477
  xval = rb_num2dbl(x);
437
478
  yval = rb_num2dbl(y);
438
479
  zval = NIL_P(z) ? 0.0 : rb_num2dbl(z);
@@ -443,56 +484,164 @@ static VALUE method_crs_to_crs_transform(VALUE self, VALUE x, VALUE y, VALUE z)
443
484
  result = rb_ary_new2(NIL_P(z) ? 2 : 3);
444
485
  rb_ary_push(result, DBL2NUM(output.xyz.x));
445
486
  rb_ary_push(result, DBL2NUM(output.xyz.y));
446
- if(!NIL_P(z)){
487
+ if (!NIL_P(z)) {
447
488
  rb_ary_push(result, DBL2NUM(output.xyz.z));
448
489
  }
449
490
  }
450
491
  return result;
451
492
  }
452
493
 
453
- static void rgeo_init_proj4()
454
- {
494
+ static VALUE method_crs_to_crs_wkt_str(VALUE self) {
495
+ VALUE result;
496
+ RGeo_CRSToCRSData *crs_to_crs_data;
497
+ PJ *crs_to_crs_pj;
498
+ const char *str;
499
+
500
+ result = Qnil;
501
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type,
502
+ crs_to_crs_data);
503
+ crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
504
+ if (crs_to_crs_pj) {
505
+ const char *const options[] = {"MULTILINE=NO", NULL};
506
+ str = proj_as_wkt(PJ_DEFAULT_CTX, crs_to_crs_pj, WKT_TYPE, options);
507
+ if (str) {
508
+ result = rb_str_new2(str);
509
+ }
510
+ }
511
+ return result;
512
+ }
513
+
514
+ static VALUE method_crs_to_crs_area_of_use_str(VALUE self) {
515
+ VALUE result;
516
+ RGeo_CRSToCRSData *crs_to_crs_data;
517
+ PJ *crs_to_crs_pj;
518
+ const char *str;
519
+
520
+ result = Qnil;
521
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type,
522
+ crs_to_crs_data);
523
+ crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
524
+ if (crs_to_crs_pj) {
525
+ if (proj_get_area_of_use(PJ_DEFAULT_CTX, crs_to_crs_pj, NULL, NULL, NULL,
526
+ NULL, &str)) {
527
+ result = rb_str_new2(str);
528
+ }
529
+ }
530
+ return result;
531
+ }
532
+
533
+ static VALUE method_crs_to_crs_proj_type(VALUE self) {
534
+ VALUE result;
535
+ RGeo_CRSToCRSData *crs_to_crs_data;
536
+ PJ *crs_to_crs_pj;
537
+ int proj_type;
538
+
539
+ result = Qnil;
540
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type,
541
+ crs_to_crs_data);
542
+ crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
543
+ if (crs_to_crs_pj) {
544
+ proj_type = proj_get_type(crs_to_crs_pj);
545
+ result = INT2FIX(proj_type);
546
+ }
547
+ return result;
548
+ }
549
+
550
+ static VALUE method_crs_to_crs_identity(VALUE self, VALUE from, VALUE to) {
551
+ VALUE result;
552
+ RGeo_Proj4Data *from_data;
553
+ RGeo_Proj4Data *to_data;
554
+ result = Qnil;
555
+ PJ *from_pj;
556
+ PJ *to_pj;
557
+
558
+ result = Qfalse;
559
+
560
+ TypedData_Get_Struct(from, RGeo_Proj4Data, &rgeo_proj4_data_type, from_data);
561
+ TypedData_Get_Struct(to, RGeo_Proj4Data, &rgeo_proj4_data_type, to_data);
562
+ from_pj = from_data->pj;
563
+ to_pj = to_data->pj;
564
+
565
+ if (from_pj && to_pj) {
566
+ if (proj_is_equivalent_to(from_pj, to_pj, PJ_COMP_EQUIVALENT)) {
567
+ result = Qtrue;
568
+ }
569
+ }
570
+
571
+ return result;
572
+ }
573
+
574
+ static void rgeo_init_proj4() {
455
575
  VALUE rgeo_module;
456
576
  VALUE coordsys_module;
577
+ VALUE cs_module;
457
578
  VALUE proj4_class;
458
579
  VALUE crs_to_crs_class;
580
+ VALUE cs_base_class;
581
+ VALUE cs_info_class;
582
+ VALUE coordinate_system_class;
583
+ VALUE coordinate_transform_class;
459
584
 
460
585
  rgeo_module = rb_define_module("RGeo");
461
586
  coordsys_module = rb_define_module_under(rgeo_module, "CoordSys");
462
-
463
- proj4_class = rb_define_class_under(coordsys_module, "Proj4", rb_cObject);
587
+ cs_module = rb_define_module_under(coordsys_module, "CS");
588
+ cs_base_class = rb_define_class_under(cs_module, "Base", rb_cObject);
589
+ cs_info_class = rb_define_class_under(cs_module, "Info", cs_base_class);
590
+
591
+ coordinate_system_class =
592
+ rb_define_class_under(cs_module, "CoordinateSystem", cs_info_class);
593
+ proj4_class =
594
+ rb_define_class_under(coordsys_module, "Proj4", coordinate_system_class);
464
595
  rb_define_alloc_func(proj4_class, rgeo_proj4_data_alloc);
465
596
  rb_define_module_function(proj4_class, "_create", cmethod_proj4_create, 2);
466
- rb_define_method(proj4_class, "initialize_copy", method_proj4_initialize_copy, 1);
597
+ rb_define_method(proj4_class, "initialize_copy", method_proj4_initialize_copy,
598
+ 1);
467
599
  rb_define_method(proj4_class, "_set_value", method_proj4_set_value, 2);
468
600
  rb_define_method(proj4_class, "_original_str", method_proj4_original_str, 0);
469
- rb_define_method(proj4_class, "_canonical_str", method_proj4_canonical_str, 0);
601
+ rb_define_method(proj4_class, "_canonical_str", method_proj4_canonical_str,
602
+ 0);
470
603
  rb_define_method(proj4_class, "_as_text", method_proj4_wkt_str, 0);
471
604
  rb_define_method(proj4_class, "_auth_name", method_proj4_auth_name_str, 0);
472
605
  rb_define_method(proj4_class, "_valid?", method_proj4_is_valid, 0);
473
606
  rb_define_method(proj4_class, "_geographic?", method_proj4_is_geographic, 0);
474
607
  rb_define_method(proj4_class, "_geocentric?", method_proj4_is_geocentric, 0);
608
+ rb_define_method(proj4_class, "_projected?", method_proj4_is_projected, 0);
475
609
  rb_define_method(proj4_class, "_radians?", method_proj4_uses_radians, 0);
476
- rb_define_method(proj4_class, "_get_geographic", method_proj4_get_geographic, 0);
477
- rb_define_module_function(proj4_class, "_proj_version", cmethod_proj4_version, 0);
478
-
479
-
480
- crs_to_crs_class = rb_define_class_under(coordsys_module, "CRSToCRS", rb_cObject);
610
+ rb_define_method(proj4_class, "_get_geographic", method_proj4_get_geographic,
611
+ 0);
612
+ rb_define_method(proj4_class, "_crs?", method_proj4_is_crs, 0);
613
+ rb_define_method(proj4_class, "_axis_and_unit_info",
614
+ method_proj4_axis_and_unit_info_str, 1);
615
+ rb_define_method(proj4_class, "_axis_count", method_proj4_axis_count, 0);
616
+ rb_define_module_function(proj4_class, "_proj_version", cmethod_proj4_version,
617
+ 0);
618
+
619
+ coordinate_transform_class =
620
+ rb_define_class_under(cs_module, "CoordinateTransform", cs_info_class);
621
+
622
+ crs_to_crs_class = rb_define_class_under(coordsys_module, "CRSToCRS",
623
+ coordinate_transform_class);
481
624
  rb_define_alloc_func(crs_to_crs_class, rgeo_crs_to_crs_data_alloc);
482
- rb_define_module_function(crs_to_crs_class, "_create", cmethod_crs_to_crs_create, 2);
483
- rb_define_method(crs_to_crs_class, "_transform_coords", method_crs_to_crs_transform, 3);
625
+ rb_define_module_function(crs_to_crs_class, "_create",
626
+ cmethod_crs_to_crs_create, 2);
627
+ rb_define_method(crs_to_crs_class, "_transform_coords",
628
+ method_crs_to_crs_transform, 3);
629
+ rb_define_method(crs_to_crs_class, "_as_text", method_crs_to_crs_wkt_str, 0);
630
+ rb_define_method(crs_to_crs_class, "_proj_type", method_crs_to_crs_proj_type,
631
+ 0);
632
+ rb_define_method(crs_to_crs_class, "_area_of_use",
633
+ method_crs_to_crs_area_of_use_str, 0);
634
+ rb_define_method(crs_to_crs_class, "_identity?", method_crs_to_crs_identity,
635
+ 2);
484
636
  }
485
637
 
486
-
487
638
  #endif
488
639
 
489
-
490
- void Init_proj4_c_impl()
491
- {
640
+ void Init_proj4_c_impl() {
492
641
  #ifdef RGEO_PROJ4_SUPPORTED
493
642
  rgeo_init_proj4();
643
+ rgeo_init_proj_errors();
494
644
  #endif
495
645
  }
496
646
 
497
-
498
647
  RGEO_END_C