rgeo-proj4 3.1.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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