rgeo-proj4 3.1.1 → 4.0.0.pre.rc.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b578b226ebc3b376a92f58cf080d34f237b5929751e6b856e493d9b6a6daa1ae
4
- data.tar.gz: 84f4953ac2aea3783e7a807542c7aaf102b265dc454a9de97c340d70f04685c1
3
+ metadata.gz: c0a179679b6f6471a9626bf6fbc08758a52b0d60f5ba81fa4ab5119456680470
4
+ data.tar.gz: 2a58dfbbf870d24ea9d4b2880444c1f331ba184dc38862af6b4347fb9cc96366
5
5
  SHA512:
6
- metadata.gz: bb2bddfdc101da5c0a4b2af5d5445ce7e57f8d49505b5bb2f53376e81b5ed392d4d2183c11e6cc1e0d86fc5b2fc83cc1afe1d6a3c72fcf8924d779fbd04fdffb
7
- data.tar.gz: 3f21328f3beff54191cf496f784a432185f9999d4b71ddeab91d772627f26bbc97deb1882cab9d9f997d16432993d2c742c3d2638005d2f372959428201f4e05
6
+ metadata.gz: a3f86ad3fd2ef994a74ebf0df1f6f4d87446f7a28055417d551822ed88384893f74e20d6803200083f129fe152170ae3d887b50769a5861391b3c0447d83c7a5
7
+ data.tar.gz: b41045b6502bd6172632021e942da3214b9de534ffd1461bb4969813c3fbcd60a8c0c7f3074c692609380f1179a1c9b600b99bba9a0c3a3f620ad99a8226b618
@@ -0,0 +1,31 @@
1
+ #ifndef RGEO_PROJ4_ERRORS_INCLUDED
2
+ #define RGEO_PROJ4_ERRORS_INCLUDED
3
+
4
+ #include <ruby.h>
5
+
6
+ #include "preface.h"
7
+
8
+ #ifdef RGEO_PROJ4_SUPPORTED
9
+
10
+ #include "errors.h"
11
+
12
+ RGEO_BEGIN_C
13
+
14
+ VALUE error_module;
15
+ VALUE rb_eRGeoError;
16
+ VALUE rb_eRGeoInvalidProjectionError;
17
+
18
+ void rgeo_init_proj_errors() {
19
+ VALUE rgeo_module;
20
+
21
+ rgeo_module = rb_define_module("RGeo");
22
+ error_module = rb_define_module_under(rgeo_module, "Error");
23
+ rb_eRGeoError = rb_define_class_under(error_module, "RGeoError", rb_eRuntimeError);
24
+ rb_eRGeoInvalidProjectionError = rb_define_class_under(error_module, "InvalidProjection", rb_eRGeoError);
25
+ }
26
+
27
+ RGEO_END_C
28
+
29
+ #endif // RGEO_PROJ4_SUPPORTED
30
+
31
+ #endif // RGEO_GEOS_ERROS_INCLUDED
@@ -0,0 +1,22 @@
1
+ #ifndef RGEO_PROJ4_ERRORS_INCLUDED
2
+ #define RGEO_PROJ4_ERRORS_INCLUDED
3
+
4
+ #include <ruby.h>
5
+
6
+ #ifdef RGEO_PROJ4_SUPPORTED
7
+
8
+ RGEO_BEGIN_C
9
+
10
+ extern VALUE error_module;
11
+ // Main rgeo error type
12
+ extern VALUE rb_eRGeoError;
13
+ // RGeo::Error::InvalidProjection
14
+ extern VALUE rb_eRGeoInvalidProjectionError;
15
+
16
+ void rgeo_init_proj_errors();
17
+
18
+ RGEO_END_C
19
+
20
+ #endif // RGEO_PROJ4_SUPPORTED
21
+
22
+ #endif // RGEO_PROJ4_ERRORS_INCLUDED
@@ -12,7 +12,7 @@ else
12
12
 
13
13
  require "mkmf"
14
14
 
15
- header_dirs_ =
15
+ header_dirs =
16
16
  [
17
17
  ::RbConfig::CONFIG["includedir"],
18
18
  "/usr/local/include",
@@ -26,7 +26,7 @@ else
26
26
  "/Library/Frameworks/PROJ.framework/unix/include",
27
27
  "/usr/include"
28
28
  ]
29
- lib_dirs_ =
29
+ lib_dirs =
30
30
  [
31
31
  ::RbConfig::CONFIG["libdir"],
32
32
  "/usr/local/lib",
@@ -42,28 +42,65 @@ else
42
42
  "/usr/lib",
43
43
  "/usr/lib64"
44
44
  ]
45
- header_dirs_.delete_if { |path_| !::File.directory?(path_) }
46
- lib_dirs_.delete_if { |path_| !::File.directory?(path_) }
45
+ header_dirs.delete_if { |path| !::File.directory?(path) }
46
+ lib_dirs.delete_if { |path| !::File.directory?(path) }
47
47
 
48
- found_proj_ = false
49
- header_dirs_, lib_dirs_ = dir_config("proj", header_dirs_, lib_dirs_)
48
+ found_proj = false
49
+ found_valid_proj_version = false
50
+ header_dirs, lib_dirs = dir_config("proj", header_dirs, lib_dirs)
50
51
  if have_header("proj.h")
51
52
  $libs << " -lproj"
53
+ found_proj = true
52
54
 
53
- if have_func("proj_create", "proj.h")
54
- found_proj_ = true
55
- have_func("proj_create_crs_to_crs_from_pj", "proj.h")
56
- have_func("proj_normalize_for_visualization", "proj.h")
57
- else
58
- $libs.gsub!(" -lproj", "")
55
+ required_proj_funcs = %w[
56
+ proj_create
57
+ proj_create_crs_to_crs_from_pj
58
+ proj_normalize_for_visualization
59
+ ]
60
+ found_valid_proj_version = required_proj_funcs.all? do |func|
61
+ have_func(func, "proj.h")
59
62
  end
60
63
  end
61
64
  have_func("rb_gc_mark_movable")
62
65
 
63
- unless found_proj_
64
- puts "**** WARNING: Unable to find Proj headers or Proj version is too old."
65
- puts "**** Compiling without Proj support."
66
+ unless found_proj
67
+
68
+ install_text = case RUBY_PLATFORM
69
+ when /linux/
70
+ %(
71
+ Please install proj like so:
72
+ apt-get install libproj-dev proj-bin
73
+ )
74
+ when /darwin/
75
+ %(
76
+ Please install proj like so:
77
+ brew install proj
78
+ )
79
+ else
80
+ %(
81
+ Please install proj.
82
+ )
83
+ end
84
+ error_msg = %(
85
+ **** WARNING: Unable to find Proj headers. Ensure that Proj is properly installed.
86
+
87
+ #{install_text}
88
+
89
+ or set the path manually using:
90
+ --with-proj-dir or with the --with-proj-include and --with-proj-lib options
91
+ )
92
+ warn error_msg
93
+ raise
94
+ end
95
+
96
+ unless found_valid_proj_version
97
+ error_msg = %(
98
+ **** WARNING: The found Proj version is not new enough to be used for this version of rgeo-proj4.
99
+ **** Proj 6.2+ is required.
100
+ )
101
+ warn error_msg
102
+ raise
66
103
  end
67
- create_makefile("rgeo/coord_sys/proj4_c_impl")
68
104
 
105
+ create_makefile("rgeo/coord_sys/proj4_c_impl")
69
106
  end
@@ -1,35 +1,14 @@
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
9
  #include <ruby.h>
32
10
  #include <proj.h>
11
+ #include "errors.h"
33
12
 
34
13
  #endif
35
14
 
@@ -60,7 +39,7 @@ typedef struct {
60
39
  static void rgeo_proj4_free(void *ptr)
61
40
  {
62
41
  RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
63
- if(data->pj){
42
+ if (data->pj){
64
43
  proj_destroy(data->pj);
65
44
  }
66
45
  free(data);
@@ -70,7 +49,7 @@ static void rgeo_proj4_free(void *ptr)
70
49
  static void rgeo_crs_to_crs_free(void *ptr)
71
50
  {
72
51
  RGeo_CRSToCRSData *data = (RGeo_CRSToCRSData *)ptr;
73
- if(data->crs_to_crs){
52
+ if (data->crs_to_crs){
74
53
  proj_destroy(data->crs_to_crs);
75
54
  }
76
55
  free(data);
@@ -83,7 +62,7 @@ static size_t rgeo_proj4_memsize(const void *ptr)
83
62
  const RGeo_Proj4Data *data = (const RGeo_Proj4Data *)ptr;
84
63
 
85
64
  size += sizeof(*data);
86
- if(data->pj){
65
+ if (data->pj){
87
66
  size += sizeof(data->pj);
88
67
  }
89
68
  return size;
@@ -94,7 +73,7 @@ static size_t rgeo_crs_to_crs_memsize(const void *ptr)
94
73
  size_t size = 0;
95
74
  const RGeo_CRSToCRSData *data = (const RGeo_CRSToCRSData *)ptr;
96
75
  size += sizeof(*data);
97
- if(data->crs_to_crs){
76
+ if (data->crs_to_crs){
98
77
  size += sizeof(data->crs_to_crs);
99
78
  }
100
79
  return size;
@@ -103,7 +82,7 @@ static size_t rgeo_crs_to_crs_memsize(const void *ptr)
103
82
  static void rgeo_proj4_mark(void *ptr)
104
83
  {
105
84
  RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
106
- if(!NIL_P(data->original_str)){
85
+ if (!NIL_P(data->original_str)){
107
86
  mark(data->original_str);
108
87
  }
109
88
  }
@@ -112,7 +91,7 @@ static void rgeo_proj4_mark(void *ptr)
112
91
  static void rgeo_proj4_compact(void *ptr)
113
92
  {
114
93
  RGeo_Proj4Data *data = (RGeo_Proj4Data *)ptr;
115
- if(data && !NIL_P(data->original_str)){
94
+ if (data && !NIL_P(data->original_str)){
116
95
  data->original_str = rb_gc_location(data->original_str);
117
96
  }
118
97
  }
@@ -120,7 +99,7 @@ static void rgeo_proj4_compact(void *ptr)
120
99
 
121
100
  static void rgeo_proj4_clear_struct(RGeo_Proj4Data *data)
122
101
  {
123
- if(data->pj){
102
+ if (data->pj){
124
103
  proj_destroy(data->pj);
125
104
  data->pj = NULL;
126
105
  data->original_str = Qnil;
@@ -150,7 +129,7 @@ static VALUE rgeo_proj4_data_alloc(VALUE self)
150
129
 
151
130
  result = Qnil;
152
131
 
153
- if(data){
132
+ if (data){
154
133
  data->pj = NULL;
155
134
  data->original_str = Qnil;
156
135
  data->uses_radians = 0;
@@ -167,7 +146,7 @@ static VALUE rgeo_crs_to_crs_data_alloc(VALUE self)
167
146
 
168
147
  result = Qnil;
169
148
 
170
- if(data){
149
+ if (data){
171
150
  data->crs_to_crs = NULL;
172
151
  result = TypedData_Wrap_Struct(self, &rgeo_crs_to_crs_data_type, data);
173
152
  }
@@ -224,13 +203,20 @@ static VALUE method_proj4_get_geographic(VALUE self)
224
203
  VALUE result;
225
204
  RGeo_Proj4Data *new_data;
226
205
  RGeo_Proj4Data *self_data;
206
+ PJ *geographic_proj;
227
207
 
228
208
  result = Qnil;
229
209
  new_data = ALLOC(RGeo_Proj4Data);
230
210
  if (new_data) {
231
211
  TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
232
212
 
233
- new_data->pj = proj_crs_get_geodetic_crs(PJ_DEFAULT_CTX, self_data->pj);
213
+ geographic_proj = proj_crs_get_geodetic_crs(PJ_DEFAULT_CTX, self_data->pj);
214
+ if (geographic_proj == 0) {
215
+ xfree(new_data);
216
+ rb_raise(rb_eRGeoInvalidProjectionError, "Geographic CRS could not be created because the source projection is not a CRS");
217
+ }
218
+
219
+ new_data->pj = geographic_proj;
234
220
  new_data->original_str = Qnil;
235
221
  new_data->uses_radians = self_data->uses_radians;
236
222
  result = TypedData_Wrap_Struct(CLASS_OF(self), &rgeo_proj4_data_type, new_data);
@@ -287,7 +273,7 @@ static VALUE method_proj4_wkt_str(VALUE self)
287
273
  if (pj) {
288
274
  const char *const options[] = {"MULTILINE=NO", NULL};
289
275
  str = proj_as_wkt(PJ_DEFAULT_CTX, pj, WKT_TYPE, options);
290
- if(str){
276
+ if (str){
291
277
  result = rb_str_new2(str);
292
278
  }
293
279
  }
@@ -308,13 +294,67 @@ static VALUE method_proj4_auth_name_str(VALUE self)
308
294
  if (pj) {
309
295
  auth = proj_get_id_auth_name(pj, 0);
310
296
  id = proj_get_id_code(pj, 0);
311
- if(id && auth){
297
+ if (id && auth){
312
298
  result = rb_sprintf("%s:%s", auth, id);
313
299
  }
314
300
  }
315
301
  return result;
316
302
  }
317
303
 
304
+ static VALUE method_proj4_axis_and_unit_info_str(VALUE self, VALUE dimension)
305
+ {
306
+ VALUE result;
307
+ int dimension_index;
308
+ PJ *pj;
309
+ PJ *pj_cs;
310
+ const char *axis_info;
311
+ const char *unit_name;
312
+ RGeo_Proj4Data *data;
313
+
314
+ Check_Type(dimension, T_FIXNUM);
315
+
316
+ dimension_index = FIX2INT(dimension);
317
+ result = Qnil;
318
+
319
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
320
+ pj = data->pj;
321
+ if (pj){
322
+ pj_cs = proj_crs_get_coordinate_system(PJ_DEFAULT_CTX, pj);
323
+ if (pj_cs) {
324
+ if (proj_cs_get_axis_info(PJ_DEFAULT_CTX, pj_cs, dimension_index, &axis_info, NULL, NULL, NULL, &unit_name, NULL, NULL)) {
325
+ result = rb_sprintf("%s:%s", axis_info, unit_name);
326
+ }
327
+
328
+ proj_destroy(pj_cs);
329
+ }
330
+ }
331
+ return result;
332
+ }
333
+
334
+ static VALUE method_proj4_axis_count(VALUE self)
335
+ {
336
+ VALUE result;
337
+ PJ *pj;
338
+ PJ *pj_cs;
339
+ int count;
340
+ RGeo_Proj4Data *data;
341
+
342
+ result = Qnil;
343
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
344
+ pj = data->pj;
345
+ if (pj){
346
+ pj_cs = proj_crs_get_coordinate_system(PJ_DEFAULT_CTX, pj);
347
+ if (pj_cs) {
348
+ count = proj_cs_get_axis_count(PJ_DEFAULT_CTX, pj_cs);
349
+ result = INT2FIX(count);
350
+
351
+ proj_destroy(pj_cs);
352
+ }
353
+ }
354
+ return result;
355
+ }
356
+
357
+
318
358
  static VALUE method_proj4_is_geographic(VALUE self)
319
359
  {
320
360
  VALUE result;
@@ -327,7 +367,7 @@ static VALUE method_proj4_is_geographic(VALUE self)
327
367
  pj = data->pj;
328
368
  if (pj) {
329
369
  proj_type = proj_get_type(pj);
330
- if(proj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || proj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS){
370
+ if (proj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || proj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS){
331
371
  result = Qtrue;
332
372
  } else {
333
373
  result = Qfalse;
@@ -354,6 +394,23 @@ static VALUE method_proj4_is_geocentric(VALUE self)
354
394
  return result;
355
395
  }
356
396
 
397
+ static VALUE method_proj4_is_projected(VALUE self)
398
+ {
399
+ VALUE result;
400
+ PJ *pj;
401
+ PJ_TYPE proj_type;
402
+ RGeo_Proj4Data *data;
403
+
404
+ result = Qnil;
405
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, data);
406
+ pj = data->pj;
407
+ if (pj) {
408
+ proj_type = proj_get_type(pj);
409
+ result = proj_type == PJ_TYPE_PROJECTED_CRS ? Qtrue : Qfalse;
410
+ }
411
+ return result;
412
+ }
413
+
357
414
 
358
415
  static VALUE method_proj4_is_valid(VALUE self)
359
416
  {
@@ -362,6 +419,14 @@ static VALUE method_proj4_is_valid(VALUE self)
362
419
  return data->pj ? Qtrue : Qfalse;
363
420
  }
364
421
 
422
+ static VALUE method_proj4_is_crs(VALUE self)
423
+ {
424
+ RGeo_Proj4Data *self_data;
425
+
426
+ TypedData_Get_Struct(self, RGeo_Proj4Data, &rgeo_proj4_data_type, self_data);
427
+ return proj_is_crs(self_data->pj) ? Qtrue : Qfalse;
428
+ }
429
+
365
430
 
366
431
  static VALUE cmethod_proj4_version(VALUE module)
367
432
  {
@@ -403,11 +468,16 @@ static VALUE cmethod_crs_to_crs_create(VALUE klass, VALUE from, VALUE to)
403
468
  to_pj = to_data->pj;
404
469
  crs_to_crs = proj_create_crs_to_crs_from_pj(PJ_DEFAULT_CTX, from_pj, to_pj, 0, NULL);
405
470
 
471
+ // check for invalid transformation
472
+ if (crs_to_crs == 0) {
473
+ rb_raise(rb_eRGeoInvalidProjectionError, "CRSToCRS could not be created from input projections");
474
+ }
475
+
406
476
  // necessary to use proj_normalize_for_visualization so that we
407
477
  // do not have to worry about the order of coordinates in every
408
478
  // coord system
409
479
  gis_pj = proj_normalize_for_visualization(PJ_DEFAULT_CTX, crs_to_crs);
410
- if(gis_pj){
480
+ if (gis_pj){
411
481
  proj_destroy(crs_to_crs);
412
482
  crs_to_crs = gis_pj;
413
483
  }
@@ -432,7 +502,7 @@ static VALUE method_crs_to_crs_transform(VALUE self, VALUE x, VALUE y, VALUE z)
432
502
  result = Qnil;
433
503
  TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type, crs_to_crs_data);
434
504
  crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
435
- if(crs_to_crs_pj){
505
+ if (crs_to_crs_pj){
436
506
  xval = rb_num2dbl(x);
437
507
  yval = rb_num2dbl(y);
438
508
  zval = NIL_P(z) ? 0.0 : rb_num2dbl(z);
@@ -443,24 +513,113 @@ static VALUE method_crs_to_crs_transform(VALUE self, VALUE x, VALUE y, VALUE z)
443
513
  result = rb_ary_new2(NIL_P(z) ? 2 : 3);
444
514
  rb_ary_push(result, DBL2NUM(output.xyz.x));
445
515
  rb_ary_push(result, DBL2NUM(output.xyz.y));
446
- if(!NIL_P(z)){
516
+ if (!NIL_P(z)){
447
517
  rb_ary_push(result, DBL2NUM(output.xyz.z));
448
518
  }
449
519
  }
450
520
  return result;
451
521
  }
452
522
 
523
+ static VALUE method_crs_to_crs_wkt_str(VALUE self)
524
+ {
525
+ VALUE result;
526
+ RGeo_CRSToCRSData *crs_to_crs_data;
527
+ PJ *crs_to_crs_pj;
528
+ const char *str;
529
+
530
+ result = Qnil;
531
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type, crs_to_crs_data);
532
+ crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
533
+ if (crs_to_crs_pj) {
534
+ const char *const options[] = {"MULTILINE=NO", NULL};
535
+ str = proj_as_wkt(PJ_DEFAULT_CTX, crs_to_crs_pj, WKT_TYPE, options);
536
+ if (str){
537
+ result = rb_str_new2(str);
538
+ }
539
+ }
540
+ return result;
541
+ }
542
+
543
+ static VALUE method_crs_to_crs_area_of_use_str(VALUE self)
544
+ {
545
+ VALUE result;
546
+ RGeo_CRSToCRSData *crs_to_crs_data;
547
+ PJ *crs_to_crs_pj;
548
+ const char *str;
549
+
550
+ result = Qnil;
551
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type, crs_to_crs_data);
552
+ crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
553
+ if (crs_to_crs_pj) {
554
+ if (proj_get_area_of_use(PJ_DEFAULT_CTX, crs_to_crs_pj, NULL, NULL, NULL, NULL, &str)){
555
+ result = rb_str_new2(str);
556
+ }
557
+ }
558
+ return result;
559
+ }
560
+
561
+ static VALUE method_crs_to_crs_proj_type(VALUE self)
562
+ {
563
+ VALUE result;
564
+ RGeo_CRSToCRSData *crs_to_crs_data;
565
+ PJ *crs_to_crs_pj;
566
+ int proj_type;
567
+
568
+ result = Qnil;
569
+ TypedData_Get_Struct(self, RGeo_CRSToCRSData, &rgeo_crs_to_crs_data_type, crs_to_crs_data);
570
+ crs_to_crs_pj = crs_to_crs_data->crs_to_crs;
571
+ if (crs_to_crs_pj) {
572
+ proj_type = proj_get_type(crs_to_crs_pj);
573
+ result = INT2FIX(proj_type);
574
+ }
575
+ return result;
576
+ }
577
+
578
+ static VALUE method_crs_to_crs_identity(VALUE self, VALUE from, VALUE to)
579
+ {
580
+ VALUE result;
581
+ RGeo_Proj4Data *from_data;
582
+ RGeo_Proj4Data *to_data;
583
+ result = Qnil;
584
+ PJ *from_pj;
585
+ PJ *to_pj;
586
+
587
+ result = Qfalse;
588
+
589
+ TypedData_Get_Struct(from, RGeo_Proj4Data, &rgeo_proj4_data_type, from_data);
590
+ TypedData_Get_Struct(to, RGeo_Proj4Data, &rgeo_proj4_data_type, to_data);
591
+ from_pj = from_data->pj;
592
+ to_pj = to_data->pj;
593
+
594
+ if (from_pj && to_pj){
595
+ if (proj_is_equivalent_to(from_pj, to_pj, PJ_COMP_EQUIVALENT)){
596
+ result = Qtrue;
597
+ }
598
+ }
599
+
600
+ return result;
601
+ }
602
+
453
603
  static void rgeo_init_proj4()
454
604
  {
455
605
  VALUE rgeo_module;
456
606
  VALUE coordsys_module;
607
+ VALUE cs_module;
457
608
  VALUE proj4_class;
458
609
  VALUE crs_to_crs_class;
610
+ VALUE cs_base_class;
611
+ VALUE cs_info_class;
612
+ VALUE coordinate_system_class;
613
+ VALUE coordinate_transform_class;
459
614
 
460
615
  rgeo_module = rb_define_module("RGeo");
461
616
  coordsys_module = rb_define_module_under(rgeo_module, "CoordSys");
617
+ cs_module = rb_define_module_under(coordsys_module, "CS");
618
+ cs_base_class = rb_define_class_under(cs_module, "Base", rb_cObject);
619
+ cs_info_class = rb_define_class_under(cs_module, "Info", cs_base_class);
462
620
 
463
- proj4_class = rb_define_class_under(coordsys_module, "Proj4", rb_cObject);
621
+ coordinate_system_class = rb_define_class_under(cs_module, "CoordinateSystem", cs_info_class);
622
+ proj4_class = rb_define_class_under(coordsys_module, "Proj4", coordinate_system_class);
464
623
  rb_define_alloc_func(proj4_class, rgeo_proj4_data_alloc);
465
624
  rb_define_module_function(proj4_class, "_create", cmethod_proj4_create, 2);
466
625
  rb_define_method(proj4_class, "initialize_copy", method_proj4_initialize_copy, 1);
@@ -472,15 +631,24 @@ static void rgeo_init_proj4()
472
631
  rb_define_method(proj4_class, "_valid?", method_proj4_is_valid, 0);
473
632
  rb_define_method(proj4_class, "_geographic?", method_proj4_is_geographic, 0);
474
633
  rb_define_method(proj4_class, "_geocentric?", method_proj4_is_geocentric, 0);
634
+ rb_define_method(proj4_class, "_projected?", method_proj4_is_projected, 0);
475
635
  rb_define_method(proj4_class, "_radians?", method_proj4_uses_radians, 0);
476
636
  rb_define_method(proj4_class, "_get_geographic", method_proj4_get_geographic, 0);
637
+ rb_define_method(proj4_class, "_crs?", method_proj4_is_crs, 0);
638
+ rb_define_method(proj4_class, "_axis_and_unit_info", method_proj4_axis_and_unit_info_str, 1);
639
+ rb_define_method(proj4_class, "_axis_count", method_proj4_axis_count, 0);
477
640
  rb_define_module_function(proj4_class, "_proj_version", cmethod_proj4_version, 0);
478
641
 
642
+ coordinate_transform_class = rb_define_class_under(cs_module, "CoordinateTransform", cs_info_class);
479
643
 
480
- crs_to_crs_class = rb_define_class_under(coordsys_module, "CRSToCRS", rb_cObject);
644
+ crs_to_crs_class = rb_define_class_under(coordsys_module, "CRSToCRS", coordinate_transform_class);
481
645
  rb_define_alloc_func(crs_to_crs_class, rgeo_crs_to_crs_data_alloc);
482
646
  rb_define_module_function(crs_to_crs_class, "_create", cmethod_crs_to_crs_create, 2);
483
647
  rb_define_method(crs_to_crs_class, "_transform_coords", method_crs_to_crs_transform, 3);
648
+ rb_define_method(crs_to_crs_class, "_as_text", method_crs_to_crs_wkt_str, 0);
649
+ rb_define_method(crs_to_crs_class, "_proj_type", method_crs_to_crs_proj_type, 0);
650
+ rb_define_method(crs_to_crs_class, "_area_of_use", method_crs_to_crs_area_of_use_str, 0);
651
+ rb_define_method(crs_to_crs_class, "_identity?", method_crs_to_crs_identity, 2);
484
652
  }
485
653
 
486
654
 
@@ -491,6 +659,7 @@ void Init_proj4_c_impl()
491
659
  {
492
660
  #ifdef RGEO_PROJ4_SUPPORTED
493
661
  rgeo_init_proj4();
662
+ rgeo_init_proj_errors();
494
663
  #endif
495
664
  }
496
665
 
@@ -0,0 +1,23 @@
1
+ #ifdef HAVE_PROJ_H
2
+ #ifdef HAVE_PROJ_CREATE
3
+ #ifdef HAVE_PROJ_CREATE_CRS_TO_CRS_FROM_PJ
4
+ #ifdef HAVE_PROJ_NORMALIZE_FOR_VISUALIZATION
5
+ #define RGEO_PROJ4_SUPPORTED
6
+ #endif
7
+ #endif
8
+ #endif
9
+ #endif
10
+
11
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
12
+ #define mark rb_gc_mark_movable
13
+ #else
14
+ #define mark rb_gc_mark
15
+ #endif
16
+
17
+ #ifdef __cplusplus
18
+ #define RGEO_BEGIN_C extern "C" {
19
+ #define RGEO_END_C }
20
+ #else
21
+ #define RGEO_BEGIN_C
22
+ #define RGEO_END_C
23
+ #endif
@@ -6,25 +6,49 @@ module RGeo
6
6
  # This is a Ruby wrapper around a proj crs_to_crs
7
7
  # A crs_to_crs transformation object is a pipeline between two known coordinate reference systems.
8
8
  # https://proj.org/development/reference/functions.html#c.proj_create_crs_to_crs
9
- class CRSToCRS
10
- attr_writer :from, :to
9
+ #
10
+ # It also inherits from the RGeo::CoordSys::CoordinateTransform abstract class.
11
+ class CRSToCRS < CS::CoordinateTransform
12
+ attr_accessor :source_cs, :target_cs
11
13
 
12
14
  class << self
13
15
  def create(from, to)
14
16
  crs_to_crs = _create(from, to)
15
- crs_to_crs.from = from
16
- crs_to_crs.to = to
17
+ crs_to_crs.source_cs = from
18
+ crs_to_crs.target_cs = to
17
19
  crs_to_crs
18
20
  end
19
21
  end
22
+
23
+ alias from source_cs
24
+ alias to target_cs
25
+ alias to_wkt _as_text
26
+
27
+ def wkt_typename
28
+ wkt_str = to_wkt
29
+ wkt_str[0, wkt_str.index("[")]
30
+ end
31
+
32
+ def transform_type
33
+ PROJ_TYPES[_proj_type]
34
+ end
35
+
36
+ def area_of_use
37
+ _area_of_use
38
+ end
39
+
40
+ def identity?
41
+ _identity?(source_cs, target_cs)
42
+ end
43
+
20
44
  # transform the coordinates from the initial CRS to the destination CRS
21
45
  def transform_coords(x, y, z)
22
- if @from._radians? && @from._geographic?
46
+ if from._radians? && from._geographic?
23
47
  x *= ImplHelper::Math::DEGREES_PER_RADIAN
24
48
  y *= ImplHelper::Math::DEGREES_PER_RADIAN
25
49
  end
26
50
  result = _transform_coords(x, y, z)
27
- if result && @to._radians? && @to._geographic?
51
+ if result && to._radians? && to._geographic?
28
52
  result[0] *= ImplHelper::Math::RADIANS_PER_DEGREE
29
53
  result[1] *= ImplHelper::Math::RADIANS_PER_DEGREE
30
54
  end
@@ -79,6 +103,10 @@ module RGeo
79
103
  int_ = from_polygon_.interior_rings.map { |r_| transform_linear_ring(r_, to_factory_) }
80
104
  to_factory_.polygon(ext_, int_)
81
105
  end
106
+
107
+ def inspect
108
+ "#<#{self.class}:0x#{object_id.to_s(16)} @source_cs=#{source_cs.original_str} @target_cs=#{target_cs.original_str}>"
109
+ end
82
110
  end
83
111
 
84
112
  # Store of all the created CRSToCRS
@@ -19,7 +19,9 @@ module RGeo
19
19
  # option. You may also use this object directly to perform low-level
20
20
  # coordinate transformations.
21
21
 
22
- class Proj4
22
+ class Proj4 < CS::CoordinateSystem
23
+ attr_accessor :dimension
24
+
23
25
  def inspect # :nodoc:
24
26
  "#<#{self.class}:0x#{object_id.to_s(16)} #{canonical_str.inspect}>"
25
27
  end
@@ -110,6 +112,7 @@ module RGeo
110
112
  def as_text
111
113
  _as_text
112
114
  end
115
+ alias to_wkt as_text
113
116
 
114
117
  # Returns the string representing the authority and code of the
115
118
  # CRS if it exists, nil otherwise.
@@ -120,6 +123,18 @@ module RGeo
120
123
  _auth_name
121
124
  end
122
125
 
126
+ # Gets axis details for dimension within coordinate system. Each
127
+ # dimension in the coordinate system has a corresponding axis.
128
+ def get_axis(dimension)
129
+ _axis_and_unit_info(dimension).split(":")[0]
130
+ end
131
+
132
+ # Gets units for dimension within coordinate system. Each
133
+ # dimension in the coordinate system has corresponding units.
134
+ def get_units(dimension)
135
+ _axis_and_unit_info(dimension).split(":")[1]
136
+ end
137
+
123
138
  # Returns true if this Proj4 object is a geographic (lat-long)
124
139
  # coordinate system.
125
140
 
@@ -134,6 +149,13 @@ module RGeo
134
149
  _geocentric?
135
150
  end
136
151
 
152
+ # Returns true if this Proj4 object is a projected
153
+ # coordinate system
154
+
155
+ def projected?
156
+ _projected?
157
+ end
158
+
137
159
  # Returns true if this Proj4 object uses radians rather than degrees
138
160
  # if it is a geographic coordinate system.
139
161
 
@@ -148,6 +170,39 @@ module RGeo
148
170
  def get_geographic
149
171
  _get_geographic
150
172
  end
173
+ alias geographic_coordinate_system get_geographic
174
+
175
+ # Returns true if this Proj4 object represents a CRS.
176
+
177
+ def crs?
178
+ _crs?
179
+ end
180
+
181
+ # Sometimes used to assign SRIDs in factory creation
182
+ # Also in the base CS::Info class that CS::CoordinateSystem
183
+ # inherits from
184
+ #
185
+ # @return [Integer|NilClass] authority code if available
186
+ def authority_code
187
+ auth_name.split(":")[1].to_i if auth_name
188
+ end
189
+
190
+ # Low-level coordinate transform method.
191
+ # Transforms the given coordinate (x, y, [z]) from one proj4
192
+ # coordinate system to another. Returns an array with either two
193
+ # or three elements.
194
+ def transform_coords(to_proj, x, y, z = nil)
195
+ self.class.transform_coords(self, to_proj, x, y, z)
196
+ end
197
+
198
+ # Low-level geometry transform method.
199
+ # Transforms the given geometry between the given two projections.
200
+ # The resulting geometry is constructed using the to_factory.
201
+ # Any projections associated with the factories themselves are
202
+ # ignored.
203
+ def transform(from_geometry, to_proj, to_factory)
204
+ self.class.transform(self, from_geometry, to_proj, to_factory)
205
+ end
151
206
 
152
207
  class << self
153
208
  # Returns true if Proj4 is supported in this installation.
@@ -165,8 +220,9 @@ module RGeo
165
220
  end
166
221
 
167
222
  # Create a new Proj4 object, given a definition, which may be
168
- # either a string or a hash. Returns nil if the given definition
169
- # is invalid or Proj4 is not supported.
223
+ # either a string, hash, or integer. If an integer is given, it
224
+ # assumes that you are using the EPSG SRID that matches that code.
225
+ # Returns nil if the given definition is invalid or Proj4 is not supported.
170
226
  #
171
227
  # Recognized options include:
172
228
  #
@@ -188,11 +244,16 @@ module RGeo
188
244
  defn_ = defn_.map { |k_, v_| v_ ? "+#{k_}=#{v_}" : "+#{k_}" }.join(" ")
189
245
  end
190
246
 
247
+ defn_ = "EPSG:#{defn_}" if defn_.is_a?(Integer)
248
+
191
249
  result_ = _create(defn_, opts_[:radians])
192
- result_ = nil unless result_._valid?
250
+ raise RGeo::Error::InvalidProjection unless result_._valid?
251
+
252
+ result_.dimension = result_._axis_count
193
253
  end
194
254
  result_
195
255
  end
256
+ alias create_from_wkt create
196
257
 
197
258
  # Create a new Proj4 object, given a definition, which may be
198
259
  # either a string or a hash. Raises Error::UnsupportedOperation
@@ -221,9 +282,9 @@ module RGeo
221
282
  # Transforms the given coordinate (x, y, [z]) from one proj4
222
283
  # coordinate system to another. Returns an array with either two
223
284
  # or three elements.
224
- def transform_coords(from_proj_, to_proj_, x_, y_, z_ = nil)
225
- crs_to_crs = CRSStore.get(from_proj_, to_proj_)
226
- crs_to_crs.transform_coords(x_, y_, z_)
285
+ def transform_coords(from_proj, to_proj, x, y, z = nil)
286
+ crs_to_crs = CRSStore.get(from_proj, to_proj)
287
+ crs_to_crs.transform_coords(x, y, z)
227
288
  end
228
289
 
229
290
  # Low-level geometry transform method.
@@ -231,9 +292,9 @@ module RGeo
231
292
  # The resulting geometry is constructed using the to_factory.
232
293
  # Any projections associated with the factories themselves are
233
294
  # ignored.
234
- def transform(from_proj_, from_geometry_, to_proj_, to_factory_)
235
- crs_to_crs = CRSStore.get(from_proj_, to_proj_)
236
- crs_to_crs.transform(from_geometry_, to_factory_)
295
+ def transform(from_proj, from_geometry, to_proj, to_factory)
296
+ crs_to_crs = CRSStore.get(from_proj, to_proj)
297
+ crs_to_crs.transform(from_geometry, to_factory)
237
298
  end
238
299
  end
239
300
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RGeo
4
+ # All RGeo errors are members of this namespace.
5
+
6
+ module Error
7
+ # Base class for all RGeo-related exceptions
8
+ class RGeoError < RuntimeError
9
+ end
10
+
11
+ # RGeo error specific to the PROJ library
12
+ class InvalidProjection < RGeoError
13
+ end
14
+ end
15
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RGeo
4
4
  module Proj4
5
- VERSION = "3.1.1"
5
+ VERSION = "4.0.0-rc.1"
6
6
  end
7
7
  end
data/lib/rgeo/proj4.rb CHANGED
@@ -2,7 +2,46 @@
2
2
 
3
3
  require "rgeo"
4
4
  require "rgeo/proj4/version"
5
+ require "rgeo/coord_sys/proj4_c_impl"
5
6
  require "rgeo/coord_sys/crs_to_crs"
6
7
  require "rgeo/coord_sys/proj4"
7
- require "rgeo/coord_sys/srs_database/proj4_data"
8
- require "rgeo/coord_sys/proj4_c_impl"
8
+ require_relative "./errors"
9
+
10
+ module RGeo
11
+ module CoordSys
12
+ # PROJ uses enums for types, some methods require us to return
13
+ # the name of the type. We will use this as a lookup.
14
+ PROJ_TYPES = %w[
15
+ PJ_TYPE_UNKNOWN
16
+ PJ_TYPE_ELLIPSOID
17
+ PJ_TYPE_PRIME_MERIDIAN
18
+ PJ_TYPE_GEODETIC_REFERENCE_FRAME
19
+ PJ_TYPE_DYNAMIC_GEODETIC_REFERENCE_FRAME
20
+ PJ_TYPE_VERTICAL_REFERENCE_FRAME
21
+ PJ_TYPE_DYNAMIC_VERTICAL_REFERENCE_FRAME
22
+ PJ_TYPE_DATUM_ENSEMBLE
23
+ PJ_TYPE_CRS
24
+ PJ_TYPE_GEODETIC_CRS
25
+ PJ_TYPE_GEOCENTRIC_CRS
26
+ PJ_TYPE_GEOGRAPHIC_CRS
27
+ PJ_TYPE_GEOGRAPHIC_2D_CRS
28
+ PJ_TYPE_GEOGRAPHIC_3D_CRS
29
+ PJ_TYPE_VERTICAL_CRS
30
+ PJ_TYPE_PROJECTED_CRS
31
+ PJ_TYPE_COMPOUND_CRS
32
+ PJ_TYPE_TEMPORAL_CRS
33
+ PJ_TYPE_ENGINEERING_CRS
34
+ PJ_TYPE_BOUND_CRS
35
+ PJ_TYPE_OTHER_CRS
36
+ PJ_TYPE_CONVERSION
37
+ PJ_TYPE_TRANSFORMATION
38
+ PJ_TYPE_CONCATENATED_OPERATION
39
+ PJ_TYPE_OTHER_COORDINATE_OPERATION
40
+ PJ_TYPE_TEMPORAL_DATUM
41
+ PJ_TYPE_ENGINEERING_DATUM
42
+ PJ_TYPE_PARAMETRIC_DATUM
43
+ ].freeze
44
+ end
45
+ end
46
+
47
+ RGeo::CoordSys::CONFIG.default_coord_sys_class = RGeo::CoordSys::Proj4 if RGeo::CoordSys::Proj4.supported?
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: 3.1.1
4
+ version: 4.0.0.pre.rc.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: 2021-11-08 00:00:00.000000000 Z
11
+ date: 2022-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rgeo
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: 3.0.0.pre.rc.3
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: '2.0'
26
+ version: 3.0.0.pre.rc.3
27
27
  - !ruby/object:Gem::Dependency
28
- name: minitest
28
+ name: ffi-geos
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.14'
33
+ version: '2.2'
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: '5.14'
40
+ version: '2.2'
41
41
  - !ruby/object:Gem::Dependency
42
- name: pry-byebug
42
+ name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.9.0
47
+ version: '5.14'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 3.9.0
54
+ version: '5.14'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -103,11 +103,14 @@ extensions:
103
103
  extra_rdoc_files: []
104
104
  files:
105
105
  - LICENSE.txt
106
+ - ext/proj4_c_impl/errors.c
107
+ - ext/proj4_c_impl/errors.h
106
108
  - ext/proj4_c_impl/extconf.rb
107
109
  - ext/proj4_c_impl/main.c
110
+ - ext/proj4_c_impl/preface.h
108
111
  - lib/rgeo/coord_sys/crs_to_crs.rb
109
112
  - lib/rgeo/coord_sys/proj4.rb
110
- - lib/rgeo/coord_sys/srs_database/proj4_data.rb
113
+ - lib/rgeo/errors.rb
111
114
  - lib/rgeo/proj4.rb
112
115
  - lib/rgeo/proj4/version.rb
113
116
  homepage: https://github.com/rgeo/rgeo-proj4
@@ -125,9 +128,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
128
  version: 2.5.0
126
129
  required_rubygems_version: !ruby/object:Gem::Requirement
127
130
  requirements:
128
- - - ">="
131
+ - - ">"
129
132
  - !ruby/object:Gem::Version
130
- version: '0'
133
+ version: 1.3.1
131
134
  requirements: []
132
135
  rubygems_version: 3.1.4
133
136
  signing_key:
@@ -1,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # -----------------------------------------------------------------------------
4
- #
5
- # SRS database interface
6
- #
7
- # -----------------------------------------------------------------------------
8
-
9
- module RGeo
10
- module CoordSys
11
- module SRSDatabase
12
- # A spatial reference database implementation backed by coordinate
13
- # system files installed as part of the proj4 library. For a given
14
- # Proj4Data object, you specify a single file (e.g. the epsg data
15
- # file), and you can retrieve records by ID number.
16
-
17
- class Proj4Data
18
- # Connect to one of the proj4 data files. You should provide the
19
- # file name, optionally the installation directory if it is not
20
- # in a typical location, and several additional options.
21
- #
22
- # These options are recognized:
23
- #
24
- # [<tt>:dir</tt>]
25
- # The path for the share/proj directory that contains the
26
- # requested data file. By default, the Proj4Data class will
27
- # try a number of directories for you, including
28
- # /usr/local/share/proj, /opt/local/share/proj, /usr/share/proj,
29
- # and a few other variants. However, if you have proj4 installed
30
- # elsewhere, you can provide an explicit directory using this
31
- # option. You may also pass nil as the value, in which case all
32
- # the normal lookup paths will be disabled, and you will have to
33
- # provide the full path as the file name.
34
- # [<tt>:cache</tt>]
35
- # If set to true, this class caches previously looked up entries
36
- # so subsequent lookups do not have to reread the file. If set
37
- # to <tt>:read_all</tt>, then ALL values in the file are read in
38
- # and cached the first time a lookup is done. If set to
39
- # <tt>:preload</tt>, then ALL values in the file are read in
40
- # immediately when the database is created. Default is false,
41
- # indicating that the file will be reread on every lookup.
42
- # [<tt>:authority</tt>]
43
- # If set, its value is taken as the authority name for all
44
- # entries. The authority code will be set to the identifier. If
45
- # not set, then the authority fields of entries will be blank.
46
-
47
- def initialize(filename_, opts_ = {})
48
- dir_ = nil
49
- if opts_.include?(:dir)
50
- dir_ = opts_[:dir]
51
- else
52
- ["/usr/local/share/proj", "/usr/local/proj/share/proj", "/usr/local/proj4/share/proj", "/opt/local/share/proj", "/opt/proj/share/proj", "/opt/proj4/share/proj", "/opt/share/proj", "/usr/share/proj"].each do |d_|
53
- if ::File.directory?(d_) && ::File.readable?(d_)
54
- dir_ = d_
55
- break
56
- end
57
- end
58
- end
59
- @path = dir_ ? "#{dir_}/#{filename_}" : filename_
60
- @authority = opts_[:authority]
61
- if opts_[:cache]
62
- @cache = {}
63
- case opts_[:cache]
64
- when :read_all
65
- @populate_state = 1
66
- when :preload
67
- search_file(nil)
68
- @populate_state = 2
69
- else
70
- @populate_state = 0
71
- end
72
- else
73
- @cache = nil
74
- @populate_state = 0
75
- end
76
- end
77
-
78
- # Retrieve the Entry for the given ID number.
79
-
80
- def get(ident_)
81
- ident_ = ident_.to_s
82
- return @cache[ident_] if @cache&.include?(ident_)
83
- result_ = nil
84
- case @populate_state
85
- when 0
86
- data_ = search_file(ident_)
87
- result_ = Entry.new(ident_, authority: @authority, authority_code: @authority ? ident_ : nil, name: data_[1], proj4: data_[2]) if data_
88
- @cache[ident_] = result_ if @cache
89
- when 1
90
- search_file(nil)
91
- result_ = @cache[ident_]
92
- @populate_state = 2
93
- end
94
- result_
95
- end
96
-
97
- # Clear the cache if one exists.
98
-
99
- def clear_cache
100
- @cache&.clear
101
- @populate_state = 1 if @populate_state == 2
102
- end
103
-
104
- private
105
-
106
- def search_file(ident_)
107
- ::File.open(@path) do |file_|
108
- cur_name_ = nil
109
- cur_ident_ = nil
110
- cur_text_ = nil
111
- file_.each do |line_|
112
- line_.strip!
113
- if (comment_delim_ = line_.index("#"))
114
- cur_name_ = line_[comment_delim_ + 1..-1].strip
115
- line_ = line_[0..comment_delim_ - 1].strip
116
- end
117
- if !cur_ident_ && (line_ =~ /^<(\w+)>(.*)/)
118
- cur_ident_ = Regexp.last_match(1)
119
- cur_text_ = []
120
- line_ = Regexp.last_match(2).strip
121
- end
122
- next unless cur_ident_
123
- if line_[-2..-1] == "<>"
124
- cur_text_ << line_[0..-3].strip
125
- cur_text_ = cur_text_.join(" ")
126
- if ident_.nil?
127
- @cache[ident_] = Entry.new(ident_, authority: @authority, authority_code: @authority ? id_ : nil, name: cur_name_, proj4: cur_text_)
128
- end
129
- return [ident_, cur_name_, cur_text_] if cur_ident_ == ident_
130
- cur_ident_ = nil
131
- cur_name_ = nil
132
- cur_text_ = nil
133
- else
134
- cur_text_ << line_
135
- end
136
- end
137
- end
138
- nil
139
- end
140
- end
141
- end
142
- end
143
- end