rd_nap_to_etrs 0.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed1d95dc0cfa6f936dd15391d4afe7891d9c60d5
4
- data.tar.gz: 8d21cb146abe0b11fed80b550ae4c9d272e4ef02
3
+ metadata.gz: 7afe3db817825d8e8d61de87bfb3c2a2ba615273
4
+ data.tar.gz: 5126fc5d429d97b0b46d7f81a93d3de7a96e5d77
5
5
  SHA512:
6
- metadata.gz: c9ef73aee6810318cc14be0d3ea8b0715d636a009daf97b1ca0a7906a206cf561b86230b24663f28375eb907abe9af1e56af2baa6ba2ee149c572c03277798e4
7
- data.tar.gz: 442d077cb067548674a0b5879e1626c9c416144c2baf69dfad470cb87e771b25b16ae4fb33bfa05aae1158bde441bdf9d8ac095ddc273a33e5fb25b4ede165fd
6
+ metadata.gz: 8ea2ee463311c12bdef6712d37e3ad3de3772553715cd8300c34771fb511ec397e52855932aa3794d8614ccb14e10f311303be057ac8938fc6495e0ff7daf182
7
+ data.tar.gz: 92bd6e8c7ab3e9fa9d8ae461d19c7897713b0164b08a83896023a17e22ff54998b190b3016a658266ef562c134a6263c02c8ce3f556aabb5b248ac2698faeb1a
@@ -0,0 +1,1535 @@
1
+ /*
2
+ **--------------------------------------------------------------
3
+ ** RDNAPTRANS(TM)2008
4
+ **
5
+ ** Authors: Jochem Lesparre, Joop van Buren, Marc Crombaghs, Frank Dentz, Arnoud Pol, Sander Oude Elberink
6
+ ** http://www.rdnap.nl
7
+ ** Based on RDNAPTRANS2004
8
+ ** Ruby bindings added by: Benjamin ter Kuile
9
+ ** Main changes:
10
+ ** - 7 similarity transformation parameters
11
+ ** - 0.0088 offset in the transformation between ellipsoidal height (h) and orthometric heights (NAP)
12
+ ** - coordinates are computed also outside the validity regions of the grid files x2c.grd, y2c.grd and nlgeo04.grd
13
+ **--------------------------------------------------------------
14
+ */
15
+
16
+ /*
17
+ **--------------------------------------------------------------
18
+ ** Include statements and namespace
19
+ **--------------------------------------------------------------
20
+ */
21
+ #include <ruby.h>
22
+ #include <iostream>
23
+ #include <iomanip>
24
+ #include <cmath>
25
+ #include <string>
26
+ #include <fstream>
27
+ #include <cstdlib>
28
+ using namespace std;
29
+
30
+ /*
31
+ **--------------------------------------------------------------
32
+ ** Static data declarations
33
+ ** Mathematical constant pi = 3.14...
34
+ **--------------------------------------------------------------
35
+ */
36
+ const double PI = 2.0 * asin(1.0);
37
+ /*
38
+ **--------------------------------------------------------------
39
+ ** Continuation of static data declarations
40
+ ** Geographic NL-Bessel coordinates of Amersfoort (pivot point and projection base point)
41
+ ** phi latitude in decimal degrees
42
+ ** lambda longitude in decimal degrees
43
+ ** h ellipsoidal height in meters
44
+ ** Source of constants:
45
+ ** Hk.J. Heuvelink, "De stereografische kaartprojectie in hare toepassing bij de Rijksdriehoeksmeting". Delft: Rijkscommissie voor Graadmeting en Waterpassing, 1918.
46
+ ** HTW, "Handleiding voor de Technische Werkzaamheden van het Kadaster". Apeldoorn: Kadaster, 1996.
47
+ **--------------------------------------------------------------
48
+ */
49
+ const double PHI_AMERSFOORT_BESSEL = 52.0+ 9.0/60.0+22.178/3600.0;
50
+ const double LAMBDA_AMERSFOORT_BESSEL = 5.0+23.0/60.0+15.500/3600.0;
51
+ const double H_AMERSFOORT_BESSEL = 0.0;
52
+ /*
53
+ **--------------------------------------------------------------
54
+ ** Continuation of static data declarations
55
+ ** Parameters of ellipsoids Bessel1841 and GRS80
56
+ ** a half major axis in meters
57
+ ** inv_f inverse flattening
58
+ ** Source of constants: HTW, "Handleiding voor de Technische Werkzaamheden van het Kadaster". Apeldoorn: Kadaster, 1996.
59
+ **--------------------------------------------------------------
60
+ */
61
+ const double A_BESSEL = 6377397.155;
62
+ const double INV_F_BESSEL = 299.1528128;
63
+ const double A_ETRS = 6378137;
64
+ const double INV_F_ETRS = 298.257222101;
65
+ /*
66
+ **--------------------------------------------------------------
67
+ ** Continuation of static data declarations
68
+ ** Transformation parameters relative to pivot point Amersfoort. Note: Do NOT confuse with parameters for the center of the ellipsoid!
69
+ ** tx translation in direction of x axis in meters
70
+ ** ty translation in direction of y axis in meters
71
+ ** tz translation in direction of z axis in meters
72
+ ** alpha rotation around x axis in radials
73
+ ** beta rotation around y axis in radials
74
+ ** gamma rotation around z axis in radials
75
+ ** delta scale parameter (scale = 1 + delta)
76
+ ** Source of constants: A. de Bruijne, J. van Buren, A. Kösters and H. van der Marel, "De geodetische referentiestelsels van Nederland; Definitie en vastlegging van ETRS89, RD en NAP en hun onderlinge relatie". Delft: Nederlandse Commissie voor Geodesie (NCG), to be published in 2005.
77
+ **--------------------------------------------------------------
78
+ */
79
+ const double TX_BESSEL_ETRS = 593.0248;
80
+ const double TY_BESSEL_ETRS = 25.9984;
81
+ const double TZ_BESSEL_ETRS = 478.7459;
82
+ const double ALPHA_BESSEL_ETRS = 1.9342e-6;
83
+ const double BETA_BESSEL_ETRS = -1.6677e-6;
84
+ const double GAMMA_BESSEL_ETRS = 9.1019e-6;
85
+ const double DELTA_BESSEL_ETRS = 4.0725e-6;
86
+
87
+ const double TX_ETRS_BESSEL = -593.0248;
88
+ const double TY_ETRS_BESSEL = -25.9984;
89
+ const double TZ_ETRS_BESSEL = -478.7459;
90
+ const double ALPHA_ETRS_BESSEL = -1.9342e-6;
91
+ const double BETA_ETRS_BESSEL = 1.6677e-6;
92
+ const double GAMMA_ETRS_BESSEL = -9.1019e-6;
93
+ const double DELTA_ETRS_BESSEL = -4.0725e-6;
94
+ /*
95
+ **--------------------------------------------------------------
96
+ ** Continuation of static data declarations
97
+ ** Parameters of RD projection
98
+ ** scale scale factor (k in some notations)
99
+ ** this factor was first defined by Hk.J. Heuvelink as pow(10,-400e-7), nowadays we define it as exactly 0.9999079
100
+ ** x_amersfoort false Easting
101
+ ** y_amersfoort false Northing
102
+ ** Source of constants:
103
+ ** G. Bakker, J.C. de Munck and G.L. Strang van Hees, "Radio Positioning at Sea". Delft University of Technology, 1995.
104
+ ** G. Strang van Hees, "Globale en lokale geodetische systemen". Delft: Nederlandse Commissie voor Geodesie (NCG), 1997.
105
+ **--------------------------------------------------------------
106
+ */
107
+ const double SCALE_RD = 0.9999079;
108
+ const double X_AMERSFOORT_RD = 155000;
109
+ const double Y_AMERSFOORT_RD = 463000;
110
+ /*
111
+ **--------------------------------------------------------------
112
+ ** Continuation of static data declarations
113
+ ** Names of grd files
114
+ **
115
+ ** Grd files are binary grid files in the format of the program Surfer(R)
116
+ ** The header contains information on the number of grid points, bounding box and extreme values.
117
+ **
118
+ ** RD-corrections in x and y
119
+ **
120
+ ** -8000 meters < RD Easting (stepsize 1 km) < 301000 meters
121
+ ** 288000 meters < RD Northing (stepsize 1 km) < 630000 meters
122
+ **
123
+ ** Geoid model NLGEO2004
124
+ **
125
+ ** 50.525 degrees < ETRS89 latitude (stepsize 0.050000 degrees) < 53.675 degrees
126
+ ** 3.20833 degrees < ETRS89 longitude (stepsize 0.083333 degrees) < 7.45833 degrees
127
+ **
128
+ ** Alternative notation:
129
+ ** 50° 31' 30" < ETRS89_latitude (stepsize 0° 3' 0") < 53° 40' 30"
130
+ ** 3° 12' 30" < ETRS89_longitude (stepsize 0° 5' 0") < 7° 27' 30"
131
+ **
132
+ ** The stepsizes correspond to about 5,5 km x 5,5 km in the Netherlands.
133
+ **--------------------------------------------------------------
134
+ */
135
+ const string GRID_FILE_DX = "x2c.grd";
136
+ const string GRID_FILE_DY = "y2c.grd";
137
+ const string GRID_FILE_GEOID = "nlgeo04.grd";
138
+ /*
139
+ **--------------------------------------------------------------
140
+ ** Continuation of static data declarations
141
+ ** Precision parameters for iterations (respectively in meters and degrees)
142
+ **--------------------------------------------------------------
143
+ */
144
+ const double PRECISION = 0.0001;
145
+ const double DEG_PRECISION = PRECISION/40e6*360;
146
+ /*
147
+ **--------------------------------------------------------------
148
+ ** Continuation of static data declarations
149
+ ** Mean difference between NAP and ellipsoidal Bessel height. This is only used for getting from x, y in RD to phi, lambda in ETRS89.
150
+ **--------------------------------------------------------------
151
+ */
152
+ const double MEAN_GEOID_HEIGHT_BESSEL = 0.0;
153
+
154
+ /*
155
+ **--------------------------------------------------------------
156
+ ** Functions
157
+ **--------------------------------------------------------------
158
+ */
159
+
160
+ /*
161
+ **--------------------------------------------------------------
162
+ ** Function name: deg_sin
163
+ ** Description: sine for angles in degrees
164
+ **
165
+ ** Parameter Type In/Out Req/Opt Default
166
+ ** alpha double in req none
167
+ **
168
+ ** Additional explanation of the meaning of parameters
169
+ ** none
170
+ **
171
+ ** Return value: (besides the standard return values)
172
+ ** sin(alpha)
173
+ **--------------------------------------------------------------
174
+ */
175
+ double deg_sin(double alpha)
176
+ {
177
+ return sin(alpha/180.0*PI);
178
+ }
179
+
180
+ /*
181
+ **--------------------------------------------------------------
182
+ ** Function name: deg_cos
183
+ ** Description: cosine for angles in degrees
184
+ **
185
+ ** Parameter Type In/Out Req/Opt Default
186
+ ** alpha double in req none
187
+ **
188
+ ** Additional explanation of the meaning of parameters
189
+ ** none
190
+ **
191
+ ** Return value: (besides the standard return values)
192
+ ** cos(alpha)
193
+ **--------------------------------------------------------------
194
+ */
195
+ double deg_cos(double alpha)
196
+ {
197
+ return cos(alpha/180.0*PI);
198
+ }
199
+
200
+ /*
201
+ **--------------------------------------------------------------
202
+ ** Function name: deg_tan
203
+ ** Description: tangent for angles in degrees
204
+ **
205
+ ** Parameter Type In/Out Req/Opt Default
206
+ ** alpha double in req none
207
+ **
208
+ ** Additional explanation of the meaning of parameters
209
+ ** none
210
+ **
211
+ ** Return value: (besides the standard return values)
212
+ ** tan(alpha)
213
+ **--------------------------------------------------------------
214
+ */
215
+ double deg_tan(double alpha)
216
+ {
217
+ return tan(alpha/180.0*PI);
218
+ }
219
+
220
+ /*
221
+ **--------------------------------------------------------------
222
+ ** Function name: deg_asin
223
+ ** Description: inverse sine for angles in degrees
224
+ **
225
+ ** Parameter Type In/Out Req/Opt Default
226
+ ** a double in req none
227
+ **
228
+ ** Additional explanation of the meaning of parameters
229
+ ** none
230
+ **
231
+ ** Return value: (besides the standard return values)
232
+ ** asin(a)
233
+ **--------------------------------------------------------------
234
+ */
235
+ double deg_asin(double a)
236
+ {
237
+ return (asin(a)*180.0/PI);
238
+ }
239
+
240
+ /*
241
+ **--------------------------------------------------------------
242
+ ** Function name: deg_atan
243
+ ** Description: inverse tangent for angles in degrees
244
+ **
245
+ ** Parameter Type In/Out Req/Opt Default
246
+ ** a double in req none
247
+ **
248
+ ** Additional explanation of the meaning of parameters
249
+ ** none
250
+ **
251
+ ** Return value: (besides the standard return values)
252
+ ** atan(a)
253
+ **--------------------------------------------------------------
254
+ */
255
+ double deg_atan(double a)
256
+ {
257
+ return (atan(a)*180.0/PI);
258
+ }
259
+
260
+ /*
261
+ **--------------------------------------------------------------
262
+ ** Function name: atanh
263
+ ** Description: inverse hyperbolic tangent
264
+ **
265
+ ** Parameter Type In/Out Req/Opt Default
266
+ ** a double in req none
267
+ **
268
+ ** Additional explanation of the meaning of parameters
269
+ ** none
270
+ **
271
+ ** Return value: (besides the standard return values)
272
+ ** atanh(a)
273
+ **--------------------------------------------------------------
274
+ */
275
+ double atanh(double a)
276
+ {
277
+ return (0.5*log((1.0+a)/(1.0-a)));
278
+ }
279
+
280
+ /*
281
+ **--------------------------------------------------------------
282
+ ** Function name: deg_min_sec2decimal
283
+ ** Description: converts from degrees, minutes and seconds to decimal degrees
284
+ **
285
+ ** Parameter Type In/Out Req/Opt Default
286
+ ** deg double in req none
287
+ ** min double in req none
288
+ ** sec double in req none
289
+ ** dec_deg double out - none
290
+ **
291
+ ** Additional explanation of the meaning of parameters
292
+ ** All parameters are doubles, so one can also enter decimal minutes or degrees.
293
+ ** Note: Nonsense input is accepted too.
294
+ **
295
+ ** Return value: (besides the standard return values)
296
+ ** none
297
+ **--------------------------------------------------------------
298
+ */
299
+ void deg_min_sec2decimal(double deg, double min, double sec, double& dec_deg)
300
+ {
301
+ dec_deg = (deg+min/60.0+sec/3600.0);
302
+ }
303
+
304
+ /*
305
+ **--------------------------------------------------------------
306
+ ** Function name: decimal2deg_min_sec
307
+ ** Description: converts from decimal degrees to degrees, minutes and seconds
308
+ **
309
+ ** Parameter Type In/Out Req/Opt Default
310
+ ** dec_deg double in req none
311
+ ** deg int out - none
312
+ ** min int out - none
313
+ ** sec double out - none
314
+ **
315
+ ** Additional explanation of the meaning of parameters
316
+ ** none
317
+ **
318
+ ** Return value: (besides the standard return values)
319
+ ** none
320
+ **--------------------------------------------------------------
321
+ */
322
+ void decimal2deg_min_sec(double dec_deg, int& deg, int& min, double& sec)
323
+ {
324
+ deg = int(dec_deg);
325
+ min = int((dec_deg-deg)*60.0);
326
+ sec = ((dec_deg-deg)*60.0-min)*60.0;
327
+ }
328
+
329
+ /*
330
+ **--------------------------------------------------------------
331
+ ** Function name: geographic2cartesian
332
+ ** Description: from geographic coordinates to cartesian coordinates
333
+ **
334
+ ** Parameter Type In/Out Req/Opt Default
335
+ ** phi double in req none
336
+ ** lambda double in req none
337
+ ** h double in req none
338
+ ** a double in req none
339
+ ** inv_f double in req none
340
+ ** x double out - none
341
+ ** y double out - none
342
+ ** z double out - none
343
+ **
344
+ ** Additional explanation of the meaning of parameters
345
+ ** phi latitude in degrees
346
+ ** lambda longitude in degrees
347
+ ** h ellipsoidal height
348
+ ** a half major axis of the ellisoid
349
+ ** inv_f inverse flattening of the ellipsoid
350
+ ** x, y, z output of cartesian coordinates
351
+ **
352
+ ** Return value: (besides the standard return values)
353
+ ** none
354
+ **--------------------------------------------------------------
355
+ */
356
+ void geographic2cartesian(double phi, double lambda, double h,
357
+ double a, double inv_f,
358
+ double& x, double& y, double& z )
359
+ {
360
+ /*
361
+ **--------------------------------------------------------------
362
+ ** Source: G. Bakker, J.C. de Munck and G.L. Strang van Hees, "Radio Positioning at Sea". Delft University of Technology, 1995.
363
+ **--------------------------------------------------------------
364
+ */
365
+
366
+ /*
367
+ **--------------------------------------------------------------
368
+ ** Explanation of the meaning of variables:
369
+ ** f flattening of the ellipsoid
370
+ ** ee first eccentricity squared (e squared in some notations)
371
+ ** n second (East West) principal radius of curvature (N in some notations)
372
+ **--------------------------------------------------------------
373
+ */
374
+ double f = 1.0/inv_f;
375
+ double ee = f*(2.0-f);
376
+ double n = a/sqrt(1.0-ee*pow(deg_sin(phi),2));
377
+ x = (n+h)*deg_cos(phi)*deg_cos(lambda);
378
+ y = (n+h)*deg_cos(phi)*deg_sin(lambda);
379
+ z = (n*(1.0-ee)+h)*deg_sin(phi);
380
+ }
381
+
382
+ /*
383
+ **--------------------------------------------------------------
384
+ ** Function name: cartesian2geographic
385
+ ** Description: from cartesian coordinates to geographic coordinates
386
+ **
387
+ ** Parameter Type In/Out Req/Opt Default
388
+ ** x double in req none
389
+ ** y double in req none
390
+ ** z double in req none
391
+ ** a double in req none
392
+ ** inv_f double in req none
393
+ ** phi double out - none
394
+ ** lambda double out - none
395
+ ** h double out - none
396
+ **
397
+ ** Additional explanation of the meaning of parameters
398
+ ** x, y, z input of cartesian coordinates
399
+ ** a half major axis of the ellisoid
400
+ ** inv_f inverse flattening of the ellipsoid
401
+ ** phi output latitude in degrees
402
+ ** lambda output longitude in degrees
403
+ ** h output ellipsoidal height
404
+ **
405
+ ** Return value: (besides the standard return values)
406
+ ** none
407
+ **--------------------------------------------------------------
408
+ */
409
+ void cartesian2geographic(double x, double y, double z,
410
+ double a, double inv_f,
411
+ double& phi, double& lambda, double& h )
412
+ {
413
+ /*
414
+ **--------------------------------------------------------------
415
+ ** Source: G. Bakker, J.C. de Munck and G.L. Strang van Hees, "Radio Positioning at Sea". Delft University of Technology, 1995.
416
+ **--------------------------------------------------------------
417
+ */
418
+
419
+ /*
420
+ **--------------------------------------------------------------
421
+ ** Explanation of the meaning of variables:
422
+ ** f flattening of the ellipsoid
423
+ ** ee first eccentricity squared (e squared in some notations)
424
+ ** rho distance to minor axis
425
+ ** n second (East West) principal radius of curvature (N in some notations)
426
+ **--------------------------------------------------------------
427
+ */
428
+ double f = 1.0/inv_f;
429
+ double ee = f*(2.0-f);
430
+ double rho = sqrt(x*x+y*y);
431
+ double n;
432
+
433
+ /*
434
+ **--------------------------------------------------------------
435
+ ** Iterative calculation of phi
436
+ **--------------------------------------------------------------
437
+ */
438
+ phi=0;
439
+ double previous;
440
+ double diff=90;
441
+ while (diff>DEG_PRECISION)
442
+ {
443
+ previous = phi;
444
+ n = a/sqrt(1.0-ee*pow(deg_sin(phi),2));
445
+ phi = deg_atan(z/rho+n*ee*deg_sin(phi)/rho);
446
+ diff = fabs(phi-previous);
447
+ }
448
+
449
+ /*
450
+ **--------------------------------------------------------------
451
+ ** Calculation of lambda and h
452
+ **--------------------------------------------------------------
453
+ */
454
+ lambda = deg_atan(y/x);
455
+ h = rho*deg_cos(phi)+z*deg_sin(phi)-n*(1.0-ee*pow(deg_sin(phi),2));
456
+ }
457
+
458
+ /*
459
+ **--------------------------------------------------------------
460
+ ** Function name: sim_trans
461
+ ** Description: 3 dimensional similarity transformation (7 parameters) around another pivot point "a" than the origin
462
+ **
463
+ ** Parameter Type In/Out Req/Opt Default
464
+ ** x_in double in req none
465
+ ** y_in double in req none
466
+ ** z_in double in req none
467
+ ** tx double in req none
468
+ ** ty double in req none
469
+ ** tz double in req none
470
+ ** alpha double in req none
471
+ ** beta double in req none
472
+ ** gamma double in req none
473
+ ** delta double in req none
474
+ ** xa double in req none
475
+ ** ya double in req none
476
+ ** za double in req none
477
+ ** x_out double out - none
478
+ ** y_out double out - none
479
+ ** z_out double out - none
480
+ **
481
+ ** Additional explanation of the meaning of parameters
482
+ ** x_in, y_in, z_in input coordinates
483
+ ** tx translation in direction of x axis
484
+ ** ty translation in direction of y axis
485
+ ** tz translation in direction of z axis
486
+ ** alpha rotation around x axis in radials
487
+ ** beta rotation around y axis in radials
488
+ ** gamma rotation around z axis in radials
489
+ ** delta scale parameter (scale = 1 + delta)
490
+ ** xa, ya, za coordinates of pivot point a (in case of rotation around the center of the ellipsoid these parameters are zero)
491
+ ** x_out, y_out, z_out output coordinates
492
+ **
493
+ ** Return value: (besides the standard return values)
494
+ ** none
495
+ **--------------------------------------------------------------
496
+ */
497
+ void sim_trans(double x_in, double y_in, double z_in,
498
+ double tx, double ty, double tz,
499
+ double alpha, double beta, double gamma,
500
+ double delta,
501
+ double xa, double ya, double za,
502
+ double& x_out, double& y_out, double& z_out)
503
+
504
+ {
505
+ /*
506
+ **--------------------------------------------------------------
507
+ ** Source: HTW, "Handleiding voor de Technische Werkzaamheden van het Kadaster". Apeldoorn: Kadaster, 1996.
508
+ **--------------------------------------------------------------
509
+ */
510
+
511
+ /*
512
+ **--------------------------------------------------------------
513
+ ** Calculate the elements of the rotation_matrix:
514
+ **
515
+ ** a b c
516
+ ** d e f
517
+ ** g h i
518
+ **
519
+ **--------------------------------------------------------------
520
+ */
521
+ double a = cos(gamma)*cos(beta);
522
+ double b = cos(gamma)*sin(beta)*sin(alpha)+sin(gamma)*cos(alpha);
523
+ double c = -cos(gamma)*sin(beta)*cos(alpha)+sin(gamma)*sin(alpha);
524
+ double d = -sin(gamma)*cos(beta);
525
+ double e = -sin(gamma)*sin(beta)*sin(alpha)+cos(gamma)*cos(alpha);
526
+ double f = sin(gamma)*sin(beta)*cos(alpha)+cos(gamma)*sin(alpha);
527
+ double g = sin(beta);
528
+ double h = -cos(beta)*sin(alpha);
529
+ double i = cos(beta)*cos(alpha);
530
+
531
+ /*
532
+ **--------------------------------------------------------------
533
+ ** Calculate the elements of the vector input_point:
534
+ ** point_2 = input_point - pivot_point
535
+ **--------------------------------------------------------------
536
+ */
537
+ double x = x_in-xa;
538
+ double y = y_in-ya;
539
+ double z = z_in-za;
540
+
541
+ /*
542
+ **--------------------------------------------------------------
543
+ ** Calculate the elements of the output vector:
544
+ ** output_point = scale * rotation_matrix * point_2 + translation_vector + pivot_point
545
+ **--------------------------------------------------------------
546
+ */
547
+ x_out = (1.0+delta)*(a*x+b*y+c*z)+tx+xa;
548
+ y_out = (1.0+delta)*(d*x+e*y+f*z)+ty+ya;
549
+ z_out = (1.0+delta)*(g*x+h*y+i*z)+tz+za;
550
+ }
551
+
552
+ /*
553
+ **--------------------------------------------------------------
554
+ ** Function name: rd_projection
555
+ ** Description: stereographic double projection
556
+ **
557
+ ** Parameter Type In/Out Req/Opt Default
558
+ ** phi double in req none
559
+ ** lambda double in req none
560
+ ** x_rd double out - none
561
+ ** y_rd double out - none
562
+ **
563
+ ** Additional explanation of the meaning of parameters
564
+ ** phi input Bessel latitude in degrees
565
+ ** lambda input Bessel longitude in degrees
566
+ ** x_rd, rd_y output RD coordinates
567
+ **
568
+ ** Return value: (besides the standard return values)
569
+ ** none
570
+ **--------------------------------------------------------------
571
+ */
572
+ void rd_projection(double phi, double lambda,
573
+ double& x_rd, double& y_rd)
574
+ {
575
+ /*
576
+ **--------------------------------------------------------------
577
+ ** Source: G. Bakker, J.C. de Munck and G.L. Strang van Hees, "Radio Positioning at Sea". Delft University of Technology, 1995.
578
+ ** G. Strang van Hees, "Globale en lokale geodetische systemen". Delft: Nederlandse Commissie voor Geodesie (NCG), 1997.
579
+ **--------------------------------------------------------------
580
+ */
581
+
582
+ /*
583
+ **--------------------------------------------------------------
584
+ ** Explanation of the meaning of constants:
585
+ ** f flattening of the ellipsoid
586
+ ** ee first eccentricity squared (e squared in some notations)
587
+ ** e first eccentricity
588
+ ** eea second eccentricity squared (e' squared in some notations)
589
+ **
590
+ ** phi_amersfoort_sphere latitude of projection base point Amersfoort on sphere in degrees
591
+ ** lambda_amersfoort_sphere longitude of projection base point Amersfoort on sphere in degrees
592
+ **
593
+ ** r1 first (North South) principal radius of curvature in Amersfoort (M in some notations)
594
+ ** r2 second (East West) principal radius of curvature in Amersfoort (N in some notations)
595
+ ** r_sphere radius of sphere
596
+ **
597
+ ** n constant of Gaussian projection n = 1.000475...
598
+ ** q_amersfoort isometric latitude of Amersfoort on ellipsiod
599
+ ** w_amersfoort isometric latitude of Amersfoort on sphere
600
+ ** m constant of Gaussian projection m = 0.003773... (also named c in some notations)
601
+ **--------------------------------------------------------------
602
+ */
603
+ const double f=1/INV_F_BESSEL;
604
+ const double ee=f*(2-f);
605
+ const double e=sqrt(ee);
606
+ const double eea = ee/(1.0-ee);
607
+
608
+ const double phi_amersfoort_sphere = deg_atan(deg_tan(PHI_AMERSFOORT_BESSEL)/sqrt(1+eea*pow(deg_cos(PHI_AMERSFOORT_BESSEL),2)));
609
+ const double lambda_amersfoort_sphere = LAMBDA_AMERSFOORT_BESSEL;
610
+
611
+ const double r1 = A_BESSEL*(1-ee)/pow(sqrt(1-ee*pow(deg_sin(PHI_AMERSFOORT_BESSEL),2)),3);
612
+ const double r2 = A_BESSEL/sqrt(1.0-ee*pow(deg_sin(PHI_AMERSFOORT_BESSEL),2));
613
+ const double r_sphere = sqrt(r1*r2);
614
+
615
+ const double n = sqrt(1+eea*pow(deg_cos(PHI_AMERSFOORT_BESSEL),4));
616
+ const double q_amersfoort = atanh(deg_sin(PHI_AMERSFOORT_BESSEL))-e*atanh(e*deg_sin(PHI_AMERSFOORT_BESSEL));
617
+ const double w_amersfoort = log(deg_tan(45+0.5*phi_amersfoort_sphere));
618
+ const double m = w_amersfoort-n*q_amersfoort;
619
+
620
+ /*
621
+ **--------------------------------------------------------------
622
+ ** Explanation of the meaning of variables:
623
+ ** q isometric latitude on ellipsiod
624
+ ** w isometric latitude on sphere
625
+ ** phi_sphere latitide on sphere in degrees
626
+ ** delta_lambda_sphere difference in longitude on sphere with Amersfoort in degrees
627
+ ** psi distance angle from Amersfoort on sphere
628
+ ** alpha azimuth from Amersfoort
629
+ ** r distance from Amersfoort in projection plane
630
+ **--------------------------------------------------------------
631
+ */
632
+ double q = atanh(deg_sin(phi))-e*atanh(e*deg_sin(phi));
633
+ double w = n*q+m;
634
+ double phi_sphere = 2*deg_atan(exp(w))-90;
635
+ double delta_lambda_sphere = n*(lambda-lambda_amersfoort_sphere);
636
+ double sin_half_psi_squared = pow(deg_sin(0.5*(phi_sphere-phi_amersfoort_sphere)),2)+pow(deg_sin(0.5*delta_lambda_sphere),2)*deg_cos(phi_sphere)*deg_cos(phi_amersfoort_sphere);
637
+ double sin_half_psi = sqrt(sin_half_psi_squared);
638
+ double cos_half_psi = sqrt(1-sin_half_psi_squared);
639
+ double tan_half_psi = sin_half_psi/cos_half_psi;
640
+ double sin_psi = 2*sin_half_psi*cos_half_psi;
641
+ double cos_psi = 1-2*sin_half_psi_squared;
642
+ double sin_alpha = deg_sin(delta_lambda_sphere)*(deg_cos(phi_sphere)/sin_psi);
643
+ double cos_alpha = (deg_sin(phi_sphere)-deg_sin(phi_amersfoort_sphere)*cos_psi)/(deg_cos(phi_amersfoort_sphere)*sin_psi);
644
+ double r = 2*SCALE_RD*r_sphere*tan_half_psi;
645
+
646
+ x_rd = r*sin_alpha+X_AMERSFOORT_RD;
647
+ y_rd = r*cos_alpha+Y_AMERSFOORT_RD;
648
+ }
649
+
650
+ /*
651
+ **--------------------------------------------------------------
652
+ ** Function name: inv_rd_projection
653
+ ** Description: inverse stereographic double projection
654
+ **
655
+ ** Parameter Type In/Out Req/Opt Default
656
+ ** x_rd double in req none
657
+ ** y_rd double in req none
658
+ ** phi double out - none
659
+ ** lambda double out - none
660
+ **
661
+ ** Additional explanation of the meaning of parameters
662
+ ** x_rd, rd_y input RD coordinates
663
+ ** phi output Bessel latitude in degrees
664
+ ** lambda output Bessel longitude in degrees
665
+ **
666
+ ** Return value: (besides the standard return values)
667
+ ** none
668
+ **--------------------------------------------------------------
669
+ */
670
+ void inv_rd_projection(double x_rd, double y_rd,
671
+ double& phi, double& lambda)
672
+ {
673
+ /*
674
+ **--------------------------------------------------------------
675
+ ** Source: G. Bakker, J.C. de Munck and G.L. Strang van Hees, "Radio Positioning at Sea". Delft University of Technology, 1995.
676
+ ** G. Strang van Hees, "Globale en lokale geodetische systemen". Delft: Nederlandse Commissie voor Geodesie (NCG), 1997.
677
+ **--------------------------------------------------------------
678
+ */
679
+
680
+ /*
681
+ **--------------------------------------------------------------
682
+ ** Explanation of the meaning of constants:
683
+ ** f flattening of the ellipsoid
684
+ ** ee first eccentricity squared (e squared in some notations)
685
+ ** e first eccentricity
686
+ ** eea second eccentricity squared (e' squared in some notations)
687
+ **
688
+ ** phi_amersfoort_sphere latitude of projection base point Amersfoort on sphere in degrees
689
+ **
690
+ ** r1 first (North South) principal radius of curvature in Amersfoort (M in some notations)
691
+ ** r2 second (East West) principal radius of curvature in Amersfoort (N in some notations)
692
+ ** r_sphere radius of sphere
693
+ **
694
+ ** n constant of Gaussian projection n = 1.000475...
695
+ ** q_amersfoort isometric latitude of Amersfoort on ellipsiod
696
+ ** w_amersfoort isometric latitude of Amersfoort on sphere
697
+ ** m constant of Gaussian projection m = 0.003773... (also named c in some notations)
698
+ **--------------------------------------------------------------
699
+ */
700
+ const double f = 1/INV_F_BESSEL;
701
+ const double ee = f*(2-f);
702
+ const double e = sqrt(ee);
703
+ const double eea = ee/(1.0-ee);
704
+
705
+ const double phi_amersfoort_sphere = deg_atan(deg_tan(PHI_AMERSFOORT_BESSEL)/sqrt(1+eea*pow(deg_cos(PHI_AMERSFOORT_BESSEL),2)));
706
+
707
+ const double r1 = A_BESSEL*(1-ee)/pow(sqrt(1-ee*pow(deg_sin(PHI_AMERSFOORT_BESSEL),2)),3);
708
+ const double r2 = A_BESSEL/sqrt(1.0-ee*pow(deg_sin(PHI_AMERSFOORT_BESSEL),2));
709
+ const double r_sphere = sqrt(r1*r2);
710
+
711
+ const double n = sqrt(1+eea*pow(deg_cos(PHI_AMERSFOORT_BESSEL),4));
712
+ const double q_amersfoort = atanh(deg_sin(PHI_AMERSFOORT_BESSEL))-e*atanh(e*deg_sin(PHI_AMERSFOORT_BESSEL));
713
+ const double w_amersfoort = log(deg_tan(45+0.5*phi_amersfoort_sphere));
714
+ const double m = w_amersfoort-n*q_amersfoort;
715
+
716
+ /*
717
+ **--------------------------------------------------------------
718
+ ** Explanation of the meaning of variables:
719
+ ** r distance from Amersfoort in projection plane
720
+ ** alpha azimuth from Amersfoort
721
+ ** psi distance angle from Amersfoort on sphere in degrees
722
+ ** phi_sphere latitide on sphere in degrees
723
+ ** delta_lambda_sphere difference in longitude on sphere with Amersfoort in degrees
724
+ ** w isometric latitude on sphere
725
+ ** q isometric latitude on ellipsiod
726
+ **--------------------------------------------------------------
727
+ */
728
+ double r = sqrt(pow(x_rd-X_AMERSFOORT_RD,2)+pow(y_rd-Y_AMERSFOORT_RD,2));
729
+ double sin_alpha = (x_rd-X_AMERSFOORT_RD)/r;
730
+ if (r<PRECISION) sin_alpha = 0;
731
+ double cos_alpha = (y_rd-Y_AMERSFOORT_RD)/r;
732
+ if (r<PRECISION) cos_alpha = 1;
733
+ double psi = 2*deg_atan(r/(2*SCALE_RD*r_sphere));
734
+ double phi_sphere = deg_asin(cos_alpha*deg_cos(phi_amersfoort_sphere)*deg_sin(psi)+deg_sin(phi_amersfoort_sphere)*deg_cos(psi));
735
+ double delta_lambda_sphere = deg_asin((sin_alpha*deg_sin(psi))/deg_cos(phi_sphere));
736
+
737
+ lambda = delta_lambda_sphere/n+LAMBDA_AMERSFOORT_BESSEL;
738
+
739
+ double w = atanh(deg_sin(phi_sphere));
740
+ double q = (w-m)/n;
741
+
742
+ /*
743
+ **--------------------------------------------------------------
744
+ ** Iterative calculation of phi
745
+ **--------------------------------------------------------------
746
+ */
747
+ phi=0;
748
+ double previous;
749
+ double diff=90;
750
+ while (diff>DEG_PRECISION)
751
+ {
752
+ previous = phi;
753
+ phi = 2*deg_atan(exp(q+0.5*e*log((1+e*deg_sin(phi))/(1-e*deg_sin(phi)))))-90;
754
+ diff = fabs(phi-previous);
755
+ }
756
+ }
757
+
758
+ /*
759
+ **--------------------------------------------------------------
760
+ ** Function name: read_grd_file_header
761
+ ** Description: reads the header of a grd file
762
+ **
763
+ ** Parameter Type In/Out Req/Opt Default
764
+ ** filename string in req none
765
+ ** size_x short int out - none
766
+ ** size_y short int out - none
767
+ ** min_x double out - none
768
+ ** max_x double out - none
769
+ ** min_y double out - none
770
+ ** max_y double out - none
771
+ ** min_value double out - none
772
+ ** max_value double out - none
773
+ **
774
+ ** Additional explanation of the meaning of parameters
775
+ ** filename name of the to be read binary file
776
+ ** size_x number of grid values in x direction (row)
777
+ ** size_y number of grid values in y direction (col)
778
+ ** min_x minimum of x
779
+ ** max_x maximum of x
780
+ ** min_y minimum of y
781
+ ** max_y maximum of x
782
+ ** min_value minimum value in grid (besides the error values)
783
+ ** max_value maximum value in grid (besides the error values)
784
+ **
785
+ ** Return value: (besides the standard return values)
786
+ ** none
787
+ **--------------------------------------------------------------
788
+ */
789
+ int read_grd_file_header(string filename,
790
+ short int& size_x, short int& size_y,
791
+ double& min_x, double& max_x,
792
+ double& min_y, double& max_y,
793
+ double& min_value, double& max_value)
794
+ {
795
+ /*
796
+ **--------------------------------------------------------------
797
+ ** Grd files are binary grid files in the format of the program Surfer(R)
798
+ **--------------------------------------------------------------
799
+ */
800
+
801
+ fstream file(filename.c_str(), ios::in | ios::binary);
802
+
803
+ /*
804
+ **--------------------------------------------------------------
805
+ ** Read file id
806
+ **--------------------------------------------------------------
807
+ */
808
+ char id[5];
809
+ for (int i=0; i<4; i=i+1)
810
+ {
811
+ file.seekg(i, ios::beg);
812
+ file.read((char *)(&id[i]), 1);
813
+ }
814
+ id[4] = '\0';
815
+ string id_string = string(id);
816
+
817
+ /*
818
+ **--------------------------------------------------------------
819
+ ** Checks
820
+ **--------------------------------------------------------------
821
+ */
822
+ if (!file)
823
+ {
824
+ cerr<<filename<<" does not exist"<<endl;
825
+ return -1;
826
+ }
827
+
828
+ if (id_string!="DSBB")
829
+ {
830
+ cerr<<filename<<" is not a valid grd file"<<endl;
831
+ return -1;
832
+ }
833
+
834
+ if (sizeof(short int)!=2)
835
+ {
836
+ cerr<<"Error: The number of bytes of a short integer in your compiler is "<<sizeof(short int)<<" and not 2 as in the file "<<filename<<endl;
837
+ return -1;
838
+ }
839
+
840
+ if (sizeof(double)!=8)
841
+ {
842
+ cerr<<"Error: The number of bytes of a double in your compiler is "<<sizeof(double)<<" and not 8 as in the file "<<filename<<endl;
843
+ return -1;
844
+ }
845
+
846
+ /*
847
+ **--------------------------------------------------------------
848
+ ** Read output parameters
849
+ **--------------------------------------------------------------
850
+ */
851
+ file.seekg(4, ios::beg);
852
+ file.read((char *)(&size_x), 2);
853
+
854
+ file.seekg(6, ios::beg);
855
+ file.read((char *)(&size_y), 2);
856
+
857
+
858
+ file.seekg(8, ios::beg);
859
+ file.read((char *)(&min_x), 8);
860
+
861
+ file.seekg(16, ios::beg);
862
+ file.read((char *)(&max_x), 8);
863
+
864
+ file.seekg(24, ios::beg);
865
+ file.read((char *)(&min_y), 8);
866
+
867
+ file.seekg(32, ios::beg);
868
+ file.read((char *)(&max_y), 8);
869
+
870
+ file.seekg(40, ios::beg);
871
+ file.read((char *)(&min_value), 8);
872
+
873
+ file.seekg(48, ios::beg);
874
+ file.read((char *)(&max_value), 8);
875
+
876
+ return 0;
877
+ }
878
+
879
+ /*
880
+ **--------------------------------------------------------------
881
+ ** Function name: read_grd_file_body
882
+ ** Description: reads a value from a grd file
883
+ **
884
+ ** Parameter Type In/Out Req/Opt Default
885
+ ** filename string in req none
886
+ ** number long int in req none
887
+ ** value float out - none
888
+ **
889
+ ** Additional explanation of the meaning of parameters
890
+ ** filename name of the grd file to be read
891
+ ** record_number number defining the position in the file
892
+ ** record_value output of the read value
893
+ **
894
+ ** Return value: (besides the standard return values)
895
+ ** none
896
+ **--------------------------------------------------------------
897
+ */
898
+ int read_grd_file_body(string filename, long int record_number, float& record_value)
899
+ {
900
+ const int record_length = 4;
901
+ const int header_length = 56;
902
+
903
+ /*
904
+ **--------------------------------------------------------------
905
+ ** Read
906
+ ** Grd files are binary grid files in the format of the program Surfer(R)
907
+ ** The first "header_length" bytes are the header of the file
908
+ ** The body of the file consists of records of "record_length" bytes
909
+ ** The records have a "record_number", starting with 0,1,2,...
910
+ **--------------------------------------------------------------
911
+ */
912
+ fstream file(filename.c_str(), ios::in | ios::binary);
913
+ file.seekg(header_length+record_number*record_length, ios::beg);
914
+ file.read((char *)(&record_value), record_length);
915
+
916
+ /*
917
+ **--------------------------------------------------------------
918
+ ** Checks
919
+ **--------------------------------------------------------------
920
+ */
921
+ if (!file)
922
+ {
923
+ cerr<<filename<<" does not exist"<<endl;
924
+ return -1;
925
+ }
926
+
927
+ if (sizeof(record_value)!=record_length)
928
+ {
929
+ cerr<<"Error: The number of bytes of a float in your compiler is "<<sizeof(record_value)<<" and not "<<record_length<<" as in the file "<<filename<<endl;
930
+ return -1;
931
+ }
932
+ return 0;
933
+ }
934
+
935
+ /*
936
+ **--------------------------------------------------------------
937
+ ** Function name: grid_interpolation
938
+ ** Description: grid interpolation using Overhauser splines
939
+ **
940
+ ** Parameter Type In/Out Req/Opt Default
941
+ ** x double in req none
942
+ ** y double in req none
943
+ ** grd_file string in req none
944
+ ** value double out - none
945
+ **
946
+ ** Additional explanation of the meaning of parameters
947
+ ** x, y coordinates of the point for which a interpolated value is desired
948
+ ** grd_file name of the grd file to be read
949
+ ** record_value output of the interpolated value
950
+ **
951
+ ** Return value: (besides the standard return values)
952
+ ** none
953
+ **--------------------------------------------------------------
954
+ */
955
+ int grid_interpolation(double x, double y, string grd_file, double& value)
956
+ {
957
+ int error;
958
+ short int i, size_x, size_y;
959
+ double min_x, max_x, min_y, max_y, min_value, max_value;
960
+ long int record_number[16];
961
+ float record_value[16];
962
+ double ddx, ddy;
963
+ double f[4], g[4];
964
+ double gfac[16];
965
+ double step_size_x, step_size_y;
966
+
967
+ /*
968
+ **--------------------------------------------------------------
969
+ ** Explanation of the meaning of variables:
970
+ ** size_x number of grid values in x direction (row)
971
+ ** size_y number of grid values in y direction (col)
972
+ ** min_x minimum of x
973
+ ** max_x maximum of x
974
+ ** min_y minimum of y
975
+ ** max_y maximum of x
976
+ ** min_value minimum value in grid (besides the error values)
977
+ ** max_value maximum value in grid (besides the error values)
978
+ **--------------------------------------------------------------
979
+ */
980
+ error = read_grd_file_header(grd_file, size_x, size_y, min_x, max_x, min_y, max_y, min_value, max_value);
981
+ if (error!=0) return -1;
982
+
983
+ step_size_x = (max_x-min_x)/(size_x-1);
984
+ step_size_y = (max_y-min_y)/(size_y-1);
985
+
986
+ /*
987
+ **--------------------------------------------------------------
988
+ ** Check for location safely inside the bounding box of grid
989
+ **--------------------------------------------------------------
990
+ */
991
+ if (x<=(min_x+step_size_x) || x>=(max_x-step_size_x) ||
992
+ y<=(min_y+step_size_y) || y>=(max_y-step_size_y))
993
+ {
994
+ cerr<<"Outside bounding box of "<<grd_file<<endl;
995
+ if (grd_file=="x2c.grd") {error=1; value=0.0;}
996
+ if (grd_file=="y2c.grd") {error=2; value=0.0;}
997
+ if (grd_file=="nlgeo04.grd") error=3;
998
+ return error;
999
+ }
1000
+
1001
+ /*
1002
+ **--------------------------------------------------------------
1003
+ ** The selected grid points are situated around point X like this:
1004
+ **
1005
+ ** 12 13 14 15
1006
+ **
1007
+ ** 8 9 10 11
1008
+ ** X
1009
+ ** 4 5 6 7
1010
+ **
1011
+ ** 0 1 2 3
1012
+ **
1013
+ ** ddx and ddy (in parts of the grid interval) are defined relative to grid point 9, respectively to the right and down.
1014
+ **--------------------------------------------------------------
1015
+ */
1016
+ ddx = (x-min_x)/step_size_x-floor((x-min_x)/step_size_x);
1017
+ ddy = 1-((y-min_y)/step_size_y-floor((y-min_y)/step_size_y));
1018
+
1019
+ /*
1020
+ **--------------------------------------------------------------
1021
+ ** Calculate the record numbers of the selected grid points
1022
+ ** The records are numbered from lower left corner to the uper right corner starting with 0:
1023
+ **
1024
+ ** size_x*(size_y-1) . . size_x*size_y-1
1025
+ ** . .
1026
+ ** . .
1027
+ ** 0 . . . . . . size_x-1
1028
+ **--------------------------------------------------------------
1029
+ */
1030
+ record_number[5] = int((x-min_x)/step_size_x + floor((y-min_y)/step_size_y)*size_x);
1031
+ record_number[0] = record_number[5]-size_x-1;
1032
+ record_number[1] = record_number[5]-size_x ;
1033
+ record_number[2] = record_number[5]-size_x+1;
1034
+ record_number[3] = record_number[5]-size_x+2;
1035
+ record_number[4] = record_number[5]-1;
1036
+ record_number[6] = record_number[5]+1;
1037
+ record_number[7] = record_number[5]+2;
1038
+ record_number[8] = record_number[5]+size_x-1;
1039
+ record_number[9] = record_number[5]+size_x;
1040
+ record_number[10] = record_number[5]+size_x+1;
1041
+ record_number[11] = record_number[5]+size_x+2;
1042
+ record_number[12] = record_number[5]+2*size_x-1;
1043
+ record_number[13] = record_number[5]+2*size_x;
1044
+ record_number[14] = record_number[5]+2*size_x+1;
1045
+ record_number[15] = record_number[5]+2*size_x+2;
1046
+
1047
+ /*
1048
+ **--------------------------------------------------------------
1049
+ ** Read the record values of the selected grid point
1050
+ ** Outside the validity area the records have a very large value (circa 1.7e38).
1051
+ **--------------------------------------------------------------
1052
+ */
1053
+ for (int i=0; i<16; i=i+1)
1054
+ {
1055
+ error = read_grd_file_body(grd_file, record_number[i], record_value[i]);
1056
+ if (error!=0) return -1;
1057
+ if (record_value[i]>max_value+PRECISION || record_value[i]<min_value-PRECISION)
1058
+ {
1059
+ cerr<<"Outside validity area of "<<grd_file<<endl;
1060
+ if (grd_file=="x2c.grd") {error=1; value=0.0;}
1061
+ if (grd_file=="y2c.grd") {error=2; value=0.0;}
1062
+ if (grd_file=="nlgeo04.grd") error=3;
1063
+ return error;
1064
+ }
1065
+ }
1066
+
1067
+ /*
1068
+ **--------------------------------------------------------------
1069
+ ** Calculation of the multiplication factors
1070
+ **--------------------------------------------------------------
1071
+ */
1072
+ f[0] = -0.5*ddx+ddx*ddx-0.5*ddx*ddx*ddx;
1073
+ f[1] = 1.0-2.5*ddx*ddx+1.5*ddx*ddx*ddx;
1074
+ f[2] = 0.5*ddx+2.0*ddx*ddx-1.5*ddx*ddx*ddx;
1075
+ f[3] = -0.5*ddx*ddx+0.5*ddx*ddx*ddx;
1076
+ g[0] = -0.5*ddy+ddy*ddy-0.5*ddy*ddy*ddy;
1077
+ g[1] = 1.0-2.5*ddy*ddy+1.5*ddy*ddy*ddy;
1078
+ g[2] = 0.5*ddy+2.0*ddy*ddy-1.5*ddy*ddy*ddy;
1079
+ g[3] = -0.5*ddy*ddy+0.5*ddy*ddy*ddy;
1080
+
1081
+ gfac[12] = f[0]*g[0];
1082
+ gfac[8] = f[0]*g[1];
1083
+ gfac[4] = f[0]*g[2];
1084
+ gfac[0] = f[0]*g[3];
1085
+ gfac[13] = f[1]*g[0];
1086
+ gfac[9] = f[1]*g[1];
1087
+ gfac[5] = f[1]*g[2];
1088
+ gfac[1] = f[1]*g[3];
1089
+ gfac[14] = f[2]*g[0];
1090
+ gfac[10] = f[2]*g[1];
1091
+ gfac[6] = f[2]*g[2];
1092
+ gfac[2] = f[2]*g[3];
1093
+ gfac[15] = f[3]*g[0];
1094
+ gfac[11] = f[3]*g[1];
1095
+ gfac[7] = f[3]*g[2];
1096
+ gfac[3] = f[3]*g[3];
1097
+
1098
+ /*
1099
+ **--------------------------------------------------------------
1100
+ ** Calculation of the interpolated value
1101
+ ** Applying the multiplication factors on the selected grid values
1102
+ **--------------------------------------------------------------
1103
+ */
1104
+ value=0.0;
1105
+ for (i=0; i<16; i=i+1)
1106
+ {
1107
+ value=value+gfac[i]*record_value[i];
1108
+ }
1109
+
1110
+ return 0;
1111
+ }
1112
+
1113
+ /*
1114
+ **--------------------------------------------------------------
1115
+ ** Function name: rd_correction
1116
+ ** Description: apply the modelled distortions in the RD coordinate system
1117
+ **
1118
+ ** Parameter Type In/Out Req/Opt Default
1119
+ ** x_pseudo_rd double in req none
1120
+ ** y_pseudo_rd double in req none
1121
+ ** x_rd double out - none
1122
+ ** y_rd double out - none
1123
+ **
1124
+ ** Additional explanation of the meaning of parameters
1125
+ ** x_pseudo_rd, y_pseudo_rd input coordinates in undistorted pseudo RD
1126
+ ** x_rd, y_rd output coordinates in real RD
1127
+ **
1128
+ ** Return value: (besides the standard return values)
1129
+ ** none
1130
+ **--------------------------------------------------------------
1131
+ */
1132
+ int rd_correction(double x_pseudo_rd, double y_pseudo_rd,
1133
+ double& x_rd, double& y_rd)
1134
+ {
1135
+ int error;
1136
+ double dx, dy;
1137
+
1138
+ error = grid_interpolation(x_pseudo_rd, y_pseudo_rd, GRID_FILE_DX, dx);
1139
+ error = grid_interpolation(x_pseudo_rd, y_pseudo_rd, GRID_FILE_DY, dy);
1140
+ x_rd=x_pseudo_rd-dx;
1141
+ y_rd=y_pseudo_rd-dy;
1142
+ return error;
1143
+ }
1144
+
1145
+ /*
1146
+ **--------------------------------------------------------------
1147
+ ** Function name: inv_rd_correction
1148
+ ** Description: remove the modelled distortions in the RD coordinate system
1149
+ **
1150
+ ** Parameter Type In/Out Req/Opt Default
1151
+ ** x_rd double in req none
1152
+ ** y_rd double in req none
1153
+ ** x_pseudo_rd double out - none
1154
+ ** x_pseudo_rd double out - none
1155
+ **
1156
+ ** Additional explanation of the meaning of parameters
1157
+ ** x_rd, y_rd input coordinates in real RD
1158
+ ** x_pseudo_rd, y_pseudo_rd output coordinates in undistorted pseudo RD
1159
+ **
1160
+ ** Return value: (besides the standard return values)
1161
+ ** none
1162
+ **--------------------------------------------------------------
1163
+ */
1164
+ int inv_rd_correction(double x_rd, double y_rd,
1165
+ double& x_pseudo_rd, double& y_pseudo_rd)
1166
+ {
1167
+ int error;
1168
+ double dx, dy;
1169
+
1170
+ /*
1171
+ **--------------------------------------------------------------
1172
+ ** The grid values are formally in pseudo RD. For the interpolation below the RD values are used. The intoduced error is certainly smaller than 0.0001 m for the X2c.grd and Y2c.grd.
1173
+ **--------------------------------------------------------------
1174
+ */
1175
+ x_pseudo_rd=x_rd;
1176
+ y_pseudo_rd=y_rd;
1177
+ error = grid_interpolation(x_pseudo_rd, y_pseudo_rd, GRID_FILE_DX, dx);
1178
+ error = grid_interpolation(x_pseudo_rd, y_pseudo_rd, GRID_FILE_DY, dy);
1179
+ x_pseudo_rd=x_rd+dx;
1180
+ y_pseudo_rd=y_rd+dy;
1181
+ return error;
1182
+ }
1183
+
1184
+ /*
1185
+ **--------------------------------------------------------------
1186
+ ** Function name: etrs2rd
1187
+ ** Description: convert ETRS89 coordinates to RD coordinates
1188
+ **
1189
+ ** Parameter Type In/Out Req/Opt Default
1190
+ ** phi_etrs double in req none
1191
+ ** lambda_etrs double in req none
1192
+ ** h_etrs double in req none
1193
+ ** x_rd double out - none
1194
+ ** y_rd double out - none
1195
+ **
1196
+ ** Additional explanation of the meaning of parameters
1197
+ ** phi_etrs, lambda_etrs, h_etrs input ETRS89 coordinates
1198
+ ** x_rd, y_rd output RD coordinates
1199
+ **
1200
+ ** Return value: (besides the standard return values)
1201
+ ** none
1202
+ **--------------------------------------------------------------
1203
+ */
1204
+ int etrs2rd(double phi_etrs, double lambda_etrs, double h_etrs,
1205
+ double& x_rd, double& y_rd, double& h_bessel)
1206
+ {
1207
+ int error;
1208
+ double x_etrs, y_etrs, z_etrs;
1209
+ double x_bessel, y_bessel, z_bessel;
1210
+ double phi_bessel, lambda_bessel;
1211
+ double x_pseudo_rd, y_pseudo_rd;
1212
+
1213
+ double x_amersfoort_bessel;
1214
+ double y_amersfoort_bessel;
1215
+ double z_amersfoort_bessel;
1216
+ double x_amersfoort_etrs;
1217
+ double y_amersfoort_etrs;
1218
+ double z_amersfoort_etrs;
1219
+
1220
+ /*
1221
+ **--------------------------------------------------------------
1222
+ ** Calculate the cartesian ETRS89 coordinates of the pivot point Amersfoort
1223
+ **--------------------------------------------------------------
1224
+ */
1225
+ geographic2cartesian(PHI_AMERSFOORT_BESSEL, LAMBDA_AMERSFOORT_BESSEL, H_AMERSFOORT_BESSEL,
1226
+ A_BESSEL, INV_F_BESSEL,
1227
+ x_amersfoort_bessel, y_amersfoort_bessel, z_amersfoort_bessel);
1228
+ x_amersfoort_etrs = x_amersfoort_bessel+TX_BESSEL_ETRS;
1229
+ y_amersfoort_etrs = y_amersfoort_bessel+TY_BESSEL_ETRS;
1230
+ z_amersfoort_etrs = z_amersfoort_bessel+TZ_BESSEL_ETRS;
1231
+
1232
+ /*
1233
+ **--------------------------------------------------------------
1234
+ ** Convert ETRS89 coordinates to RD coordinates
1235
+ ** (To convert from degrees, minutes and seconds use the function deg_min_sec2decimal() here)
1236
+ **--------------------------------------------------------------
1237
+ */
1238
+ geographic2cartesian(phi_etrs, lambda_etrs, h_etrs,
1239
+ A_ETRS, INV_F_ETRS,
1240
+ x_etrs, y_etrs, z_etrs);
1241
+ sim_trans(x_etrs, y_etrs, z_etrs,
1242
+ TX_ETRS_BESSEL, TY_ETRS_BESSEL, TZ_ETRS_BESSEL,
1243
+ ALPHA_ETRS_BESSEL, BETA_ETRS_BESSEL, GAMMA_ETRS_BESSEL,
1244
+ DELTA_ETRS_BESSEL,
1245
+ x_amersfoort_etrs, y_amersfoort_etrs, z_amersfoort_etrs,
1246
+ x_bessel, y_bessel, z_bessel);
1247
+ cartesian2geographic(x_bessel, y_bessel, z_bessel,
1248
+ A_BESSEL, INV_F_BESSEL,
1249
+ phi_bessel, lambda_bessel, h_bessel);
1250
+ rd_projection(phi_bessel, lambda_bessel, x_pseudo_rd, y_pseudo_rd);
1251
+ error = rd_correction(x_pseudo_rd, y_pseudo_rd, x_rd, y_rd);
1252
+ return error;
1253
+ }
1254
+
1255
+ /*
1256
+ **--------------------------------------------------------------
1257
+ ** Function name: rd2etrs
1258
+ ** Description: convert RD coordinates to ETRS89 coordinates
1259
+ **
1260
+ ** Parameter Type In/Out Req/Opt Default
1261
+ ** x_rd double in req none
1262
+ ** y_rd double in req none
1263
+ ** nap double in req none
1264
+ ** phi_etrs double out - none
1265
+ ** lambda_etrs double out - none
1266
+ **
1267
+ ** Additional explanation of the meaning of parameters
1268
+ ** x_rd, y_rd, nap input RD and NAP coordinates
1269
+ ** phi_etrs, lambda_etrs output ETRS89 coordinates
1270
+ **
1271
+ ** Return value: (besides the standard return values)
1272
+ ** none
1273
+ **--------------------------------------------------------------
1274
+ */
1275
+ int rd2etrs(double x_rd, double y_rd, double nap,
1276
+ double& phi_etrs, double& lambda_etrs, double& h_etrs)
1277
+ {
1278
+ int error;
1279
+ double x_pseudo_rd, y_pseudo_rd;
1280
+ double phi_bessel, lambda_bessel, h_bessel;
1281
+ double x_bessel, y_bessel, z_bessel;
1282
+ double x_etrs, y_etrs, z_etrs;
1283
+ double x_amersfoort_bessel;
1284
+ double y_amersfoort_bessel;
1285
+ double z_amersfoort_bessel;
1286
+
1287
+ /*
1288
+ **--------------------------------------------------------------
1289
+ ** Calculate the cartesian Bessel coordinates of the pivot point Amersfoort
1290
+ **--------------------------------------------------------------
1291
+ */
1292
+ geographic2cartesian(PHI_AMERSFOORT_BESSEL, LAMBDA_AMERSFOORT_BESSEL, H_AMERSFOORT_BESSEL,
1293
+ A_BESSEL, INV_F_BESSEL,
1294
+ x_amersfoort_bessel, y_amersfoort_bessel, z_amersfoort_bessel);
1295
+
1296
+ /*
1297
+ **--------------------------------------------------------------
1298
+ ** Calculate appoximated value of ellipsoidal Bessel height
1299
+ ** The error made by using a constant for de Bessel geoid height is max. circa 1 meter in the ellipsoidal height (for the NLGEO2004 geoid model). This intoduces an error in the phi, lambda position too, this error is nevertheless certainly smaller than 0.0001 m.
1300
+ **--------------------------------------------------------------
1301
+ */
1302
+ h_bessel = nap + MEAN_GEOID_HEIGHT_BESSEL;
1303
+
1304
+ /*
1305
+ **--------------------------------------------------------------
1306
+ ** Convert RD coordinates to ETRS89 coordinates
1307
+ **--------------------------------------------------------------
1308
+ */
1309
+ error = inv_rd_correction(x_rd, y_rd,
1310
+ x_pseudo_rd, y_pseudo_rd);
1311
+ inv_rd_projection(x_pseudo_rd, y_pseudo_rd,
1312
+ phi_bessel, lambda_bessel);
1313
+ geographic2cartesian(phi_bessel, lambda_bessel, h_bessel,
1314
+ A_BESSEL, INV_F_BESSEL,
1315
+ x_bessel, y_bessel, z_bessel);
1316
+ sim_trans(x_bessel, y_bessel, z_bessel,
1317
+ TX_BESSEL_ETRS, TY_BESSEL_ETRS, TZ_BESSEL_ETRS,
1318
+ ALPHA_BESSEL_ETRS, BETA_BESSEL_ETRS, GAMMA_BESSEL_ETRS,
1319
+ DELTA_BESSEL_ETRS,
1320
+ x_amersfoort_bessel, y_amersfoort_bessel, z_amersfoort_bessel,
1321
+ x_etrs, y_etrs, z_etrs);
1322
+ cartesian2geographic(x_etrs, y_etrs, z_etrs,
1323
+ A_ETRS, INV_F_ETRS,
1324
+ phi_etrs, lambda_etrs, h_etrs);
1325
+ /*
1326
+ **--------------------------------------------------------------
1327
+ ** To convert to degrees, minutes and seconds use the function decimal2deg_min_sec() here
1328
+ **--------------------------------------------------------------
1329
+ */
1330
+ return error;
1331
+ }
1332
+
1333
+ /*
1334
+ **--------------------------------------------------------------
1335
+ ** Function name: etrs2nap
1336
+ ** Description: convert ellipsoidal ETRS89 height to NAP height
1337
+ **
1338
+ ** Parameter Type In/Out Req/Opt Default
1339
+ ** phi double in req none
1340
+ ** lambda double in req none
1341
+ ** h double in req none
1342
+ ** nap double out - none
1343
+ **
1344
+ ** Additional explanation of the meaning of parameters
1345
+ ** phi, lambda, h input ETRS89 coordinates
1346
+ ** nap output NAP height
1347
+ **
1348
+ ** Return value: (besides the standard return values) none
1349
+ ** on error (outside geoid grid) nap is not compted here
1350
+ ** instead in etrs2rdnap nap=h_bessel
1351
+ **--------------------------------------------------------------
1352
+ */
1353
+ int etrs2nap(double phi, double lambda, double h,
1354
+ double& nap)
1355
+ {
1356
+ /*
1357
+ **--------------------------------------------------------------
1358
+ ** Explanation of the meaning of variables:
1359
+ ** n geoid height
1360
+ ** on error (outside geoid grid) nap is not compted
1361
+ ** instead in etrs2rdnap nap=h_bessel
1362
+ **--------------------------------------------------------------
1363
+ */
1364
+ int error;
1365
+ double n;
1366
+ error = grid_interpolation(lambda, phi, GRID_FILE_GEOID, n);
1367
+ if (error!=0) return error;
1368
+ nap = h-n+0.0088;
1369
+ return 0;
1370
+ }
1371
+
1372
+ /*
1373
+ **--------------------------------------------------------------
1374
+ ** Function name: nap2etrs
1375
+ ** Description: convert NAP height to ellipsoidal ETRS89 height
1376
+ **
1377
+ ** Parameter Type In/Out Req/Opt Default
1378
+ ** phi double in req none
1379
+ ** lambda double in req none
1380
+ ** nap double in req none
1381
+ ** h double out - none
1382
+ **
1383
+ ** Additional explanation of the meaning of parameters
1384
+ ** phi, lambda input ETRS89 position
1385
+ ** nap input NAP height at position phi, lambda
1386
+ ** h output ellipsoidal ETRS89 height
1387
+ **
1388
+ ** Return value: (besides the standard return values)
1389
+ ** none
1390
+ ** on error (outside geoid grid) h is not compted here
1391
+ ** instead in rdnap2etrs h=h_etrs_sim (from similarity transformation)
1392
+ **--------------------------------------------------------------
1393
+ */
1394
+ int nap2etrs(double phi, double lambda, double nap,
1395
+ double& h)
1396
+ {
1397
+ /*
1398
+ **--------------------------------------------------------------
1399
+ ** Explanation of the meaning of variables:
1400
+ ** n geoid height
1401
+ **--------------------------------------------------------------
1402
+ */
1403
+ int error;
1404
+ double n;
1405
+ error = grid_interpolation(lambda, phi, GRID_FILE_GEOID, n);
1406
+ if (error!=0) return error;
1407
+ h = nap+n-0.0088;
1408
+ return 0;
1409
+ }
1410
+
1411
+ /*
1412
+ **--------------------------------------------------------------
1413
+ ** Function name: etrs2rdnap
1414
+ ** Description: convert ETRS89 coordinates to RD and NAP coordinates
1415
+ **
1416
+ ** Parameter Type In/Out Req/Opt Default
1417
+ ** phi double in req none
1418
+ ** lambda double in req none
1419
+ ** h double in req none
1420
+ ** x_rd double out - none
1421
+ ** y_rd double out - none
1422
+ ** nap double out - none
1423
+ **
1424
+ ** Additional explanation of the meaning of parameters
1425
+ ** phi, lambda, h input ETRS89 coordinates
1426
+ ** x_rd, y_rd, nap output RD and NAP coordinates
1427
+ **
1428
+ ** Return value: (besides the standard return values)
1429
+ ** none
1430
+ **--------------------------------------------------------------
1431
+ */
1432
+ int etrs2rdnap(double phi, double lambda, double h,
1433
+ double& x_rd, double& y_rd, double& nap)
1434
+ {
1435
+ int error;
1436
+ double h_bessel, h_geoid;
1437
+ error = etrs2rd( phi, lambda, h, x_rd, y_rd, h_bessel);
1438
+ error = etrs2nap(phi, lambda, h, h_geoid);
1439
+ if (error==3) nap=h_bessel;
1440
+ else nap=h_geoid;
1441
+ return error;
1442
+ }
1443
+
1444
+ /*
1445
+ **--------------------------------------------------------------
1446
+ ** Function name: rdnap2etrs
1447
+ ** Description: convert RD and NAP coordinates to ETRS89 coordinates
1448
+ **
1449
+ ** Parameter Type In/Out Req/Opt Default
1450
+ ** x_rd double in req none
1451
+ ** y_rd double in req none
1452
+ ** nap double in req none
1453
+ ** phi double out - none
1454
+ ** lambda double out - none
1455
+ ** h double out - none
1456
+ **
1457
+ ** Additional explanation of the meaning of parameters
1458
+ ** x_rd, y_rd, nap input RD and NAP coordinates
1459
+ ** phi, lambda, h output ETRS89 coordinates
1460
+ **
1461
+ ** Return value: (besides the standard return values)
1462
+ ** none
1463
+ **--------------------------------------------------------------
1464
+ */
1465
+ int rdnap2etrs(double x_rd, double y_rd, double nap,
1466
+ double& phi, double& lambda, double& h)
1467
+ {
1468
+ int error;
1469
+ double h_etrs_sim, h_etrs_geoid;
1470
+ error = rd2etrs( x_rd, y_rd, nap, phi, lambda, h_etrs_sim);
1471
+ error = nap2etrs(phi, lambda, nap, h_etrs_geoid);
1472
+ if (error==3) h=h_etrs_sim;
1473
+ else h=h_etrs_geoid;
1474
+ return error;
1475
+ }
1476
+
1477
+ // Use this typedef to make the compiler happy when
1478
+ // calling rb_define_method()
1479
+ typedef VALUE (ruby_method)(...);
1480
+
1481
+ extern "C" VALUE r_transpoint2008(VALUE point){
1482
+ int error;
1483
+ double x_rd, y_rd, nap, phi, lambda, h;
1484
+ VALUE rb_x_rd, rb_y_rd, rb_nap;
1485
+
1486
+ rb_x_rd = rb_iv_get(point, "@x");
1487
+ rb_y_rd = rb_iv_get(point, "@y");
1488
+ rb_nap = rb_iv_get(point, "@nap");
1489
+ if(TYPE(rb_x_rd) == T_FLOAT or TYPE(rb_x_rd) == T_FIXNUM or TYPE(rb_x_rd) == T_BIGNUM){
1490
+ x_rd = NUM2DBL(rb_x_rd);
1491
+ }else{
1492
+ rb_raise(rb_eArgError, "The x value of the point is not a number");
1493
+ }
1494
+ if(TYPE(rb_y_rd) == T_FLOAT or TYPE(rb_y_rd) == T_FIXNUM or TYPE(rb_y_rd) == T_BIGNUM){
1495
+ y_rd = NUM2DBL(rb_y_rd);
1496
+ }else{
1497
+ rb_raise(rb_eArgError, "The y value of point is not a number");
1498
+ }
1499
+ if(TYPE(rb_nap) == T_FLOAT or TYPE(rb_nap) == T_FIXNUM or TYPE(rb_nap) == T_BIGNUM){
1500
+ nap = NUM2DBL(rb_nap);
1501
+ }else{
1502
+ //rb_raise(rb_eArgError, "The nap value of point is not a number");
1503
+ }
1504
+ error = rdnap2etrs(x_rd, y_rd, nap, phi, lambda, h);
1505
+ rb_iv_set(point, "@lat", rb_float_new(phi));
1506
+ rb_iv_set(point, "@lng", rb_float_new(lambda));
1507
+ rb_iv_set(point, "@h", rb_float_new(h));
1508
+ //rb_iv_set(point, "@nap", rb_float_new(h));
1509
+ return point;
1510
+ }
1511
+
1512
+ extern "C" VALUE r_trans2008(VALUE self, VALUE ary) {
1513
+ long i;
1514
+ long len = RARRAY_LEN(ary);
1515
+ VALUE point;
1516
+ if(TYPE(ary) != T_ARRAY) rb_raise(rb_eArgError, "Please supply an array of RdNapToEtrs::Point objects");
1517
+
1518
+ for(i = 0; i < len; i++){
1519
+ point = rb_ary_entry(ary, i);
1520
+ r_transpoint2008(point);
1521
+ }
1522
+ return ary;
1523
+ }
1524
+
1525
+ VALUE mod_RdNapToEtrs;
1526
+ VALUE cls_Point;
1527
+ VALUE cls_Batch;
1528
+
1529
+ extern "C" void Init_trans2008()
1530
+ {
1531
+ mod_RdNapToEtrs = rb_define_module("RdNapToEtrs");
1532
+ cls_Point = rb_define_class_under(mod_RdNapToEtrs, "Point", rb_cObject);
1533
+ cls_Batch = rb_define_class_under(mod_RdNapToEtrs, "Batch", rb_cObject);
1534
+ rb_define_method(cls_Batch, "_trans2008", (ruby_method*) &r_trans2008, 1);
1535
+ }