line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Geo::Coordinates::ETRSTM35FIN; |
2
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
129707
|
use 5.008006; |
|
4
|
|
|
|
|
13
|
|
|
4
|
|
|
|
|
180
|
|
4
|
4
|
|
|
4
|
|
27
|
use strict; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
184
|
|
5
|
4
|
|
|
4
|
|
22
|
use warnings; |
|
4
|
|
|
|
|
16
|
|
|
4
|
|
|
|
|
772
|
|
6
|
4
|
|
|
4
|
|
26
|
use Carp; |
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
435
|
|
7
|
4
|
|
|
4
|
|
15325
|
use Math::Trig; |
|
4
|
|
|
|
|
117033
|
|
|
4
|
|
|
|
|
10898
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub new { |
12
|
4
|
|
|
4
|
0
|
52
|
my $class = shift; |
13
|
|
|
|
|
|
|
|
14
|
4
|
|
|
|
|
9
|
my $self = {}; |
15
|
|
|
|
|
|
|
|
16
|
4
|
|
|
|
|
14
|
bless($self, $class); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Constants used in calculations transforming between WGS84 and ETRS-TM35FIN |
19
|
4
|
|
|
|
|
23
|
add_constant($self, 'Ca', 6378137.0); |
20
|
4
|
|
|
|
|
12
|
add_constant($self, 'Cb', 6356752.314245); |
21
|
4
|
|
|
|
|
28
|
add_constant($self, 'Cf', 1.0 / 298.257223563); |
22
|
4
|
|
|
|
|
10
|
add_constant($self, 'Ck0', 0.9996); |
23
|
4
|
|
|
|
|
26
|
add_constant($self, 'Clo0', Math::Trig::deg2rad(27.0)); |
24
|
4
|
|
|
|
|
12
|
add_constant($self, 'CE0', 500000.0); |
25
|
4
|
|
|
|
|
19
|
add_constant($self, 'Cn', get_c($self, 'Cf') / (2.0 - get_c($self, 'Cf'))); |
26
|
4
|
|
|
|
|
15
|
add_constant($self, 'CA1', get_c($self, 'Ca') / (1.0 + get_c($self, 'Cn')) * (1.0 + (get_c($self, 'Cn') ** 2.0) / 4.0 + (get_c($self, 'Cn') ** 4.0) / 64.0)); |
27
|
4
|
|
|
|
|
16
|
add_constant($self, 'Ce', sqrt(2.0 * get_c($self, 'Cf') - get_c($self, 'Cf') ** 2.0)); |
28
|
4
|
|
|
|
|
11
|
add_constant($self, 'Ch1', 1.0/2.0 * get_c($self, 'Cn') - 2.0/3.0 * (get_c($self, 'Cn') ** 2.0) + 37.0/96.0 * (get_c($self, 'Cn') ** 3.0) - 1.0/360.0 * (get_c($self, 'Cn') ** 4.0)); |
29
|
4
|
|
|
|
|
12
|
add_constant($self, 'Ch2', 1.0/48.0 * (get_c($self, 'Cn') ** 2.0) + 1.0/15.0 * (get_c($self, 'Cn') ** 3.0) - 437.0/1440.0 * (get_c($self, 'Cn') ** 4.0)); |
30
|
4
|
|
|
|
|
11
|
add_constant($self, 'Ch3', 17.0/480.0 * (get_c($self, 'Cn') ** 3.0) - 37.0/840.0 * (get_c($self, 'Cn') ** 4.0)); |
31
|
4
|
|
|
|
|
12
|
add_constant($self, 'Ch4', 4397.0/161280.0 * (get_c($self, 'Cn') ** 4.0)); |
32
|
4
|
|
|
|
|
11
|
add_constant($self, 'Ch1p', 1.0/2.0 * get_c($self, 'Cn') - 2.0/3.0 * (get_c($self, 'Cn') ** 2.0) + 5.0/16.0 * (get_c($self, 'Cn') ** 3.0) + 41.0/180.0 * (get_c($self, 'Cn') ** 4.0)); |
33
|
4
|
|
|
|
|
12
|
add_constant($self, 'Ch2p', 13.0/48.0 * (get_c($self, 'Cn') ** 2.0) - 3.0/5.0 * (get_c($self, 'Cn') ** 3.0) + 557.0/1440.0 * (get_c($self, 'Cn') ** 4.0)); |
34
|
4
|
|
|
|
|
12
|
add_constant($self, 'Ch3p', 61.0/240.0 * (get_c($self, 'Cn') ** 3.0) - 103.0/140.0 * (get_c($self, 'Cn') ** 4.0)); |
35
|
4
|
|
|
|
|
13
|
add_constant($self, 'Ch4p', 49561.0/161280.0 * (get_c($self, 'Cn') ** 4.0)); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# WGS84 bounds (ref. http://spatialreference.org/ref/epsg/3067/) |
38
|
4
|
|
|
|
|
34
|
add_constant($self, 'WGS84_min_la', "59.3000"); |
39
|
4
|
|
|
|
|
10
|
add_constant($self, 'WGS84_max_la', "70.1300"); |
40
|
4
|
|
|
|
|
12
|
add_constant($self, 'WGS84_min_lo', "19.0900"); |
41
|
4
|
|
|
|
|
9
|
add_constant($self, 'WGS84_max_lo', "31.5900"); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# ETRS-TM35FIN bounds (ref. http://spatialreference.org/ref/epsg/3067/) |
44
|
4
|
|
|
|
|
8
|
add_constant($self, 'ETRSTM35FIN_min_x', "6582464.0358"); |
45
|
4
|
|
|
|
|
10
|
add_constant($self, 'ETRSTM35FIN_max_x', "7799839.8902"); |
46
|
4
|
|
|
|
|
9
|
add_constant($self, 'ETRSTM35FIN_min_y', "50199.4814"); |
47
|
4
|
|
|
|
|
9
|
add_constant($self, 'ETRSTM35FIN_max_y', "761274.6247"); |
48
|
|
|
|
|
|
|
|
49
|
4
|
|
|
|
|
88
|
return $self; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub add_constant { |
53
|
100
|
|
|
100
|
0
|
210
|
my ($class, $constant_name, $constant_value) = @_; |
54
|
|
|
|
|
|
|
|
55
|
100
|
|
|
|
|
212
|
$class->{$constant_name} = $constant_value; |
56
|
|
|
|
|
|
|
|
57
|
100
|
|
|
|
|
130
|
return; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub get_constant { |
61
|
512
|
|
|
512
|
0
|
625
|
my ($class, $constant_name) = @_; |
62
|
|
|
|
|
|
|
|
63
|
512
|
|
|
|
|
2607
|
return $class->{$constant_name}; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# Alias for get_constant |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub get_c { |
69
|
512
|
|
|
512
|
0
|
848
|
my ($class, $constant_name) = @_; |
70
|
|
|
|
|
|
|
|
71
|
512
|
|
|
|
|
826
|
return get_constant($class, $constant_name); |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub is_defined_ETRSTM35FINxy { |
75
|
22
|
|
|
22
|
1
|
8548
|
my @params = @_; |
76
|
22
|
|
|
|
|
59
|
my ($class, $etrs_x, $etrs_y) = @params; |
77
|
|
|
|
|
|
|
|
78
|
22
|
50
|
|
|
|
56
|
if (scalar(@params) != 3) { |
79
|
0
|
|
|
|
|
0
|
croak 'Geo::Coordinates::ETRSTM35FIN::is_defined_ETRSTM35FINxy needs two arguments'; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
22
|
50
|
100
|
|
|
58
|
if (($etrs_x >= get_c($class, 'ETRSTM35FIN_min_x')) and ($etrs_x <= get_c($class, 'ETRSTM35FIN_max_x')) and |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
83
|
|
|
|
|
|
|
($etrs_y >= get_c($class, 'ETRSTM35FIN_min_y')) and ($etrs_y <= get_c($class, 'ETRSTM35FIN_max_y'))) { |
84
|
|
|
|
|
|
|
# Is in bounds |
85
|
14
|
|
|
|
|
134
|
return 1; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
8
|
|
|
|
|
27
|
return; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub is_defined_WGS84lalo { |
92
|
22
|
|
|
22
|
1
|
2023
|
my @params = @_; |
93
|
22
|
|
|
|
|
62
|
my ($class, $wgs_la, $wgs_lo) = @params; |
94
|
|
|
|
|
|
|
|
95
|
22
|
50
|
|
|
|
55
|
if (scalar(@params) != 3) { |
96
|
0
|
|
|
|
|
0
|
croak 'Geo::Coordinates::ETRSTM35FIN::is_defined_WGS84lalo needs two arguments'; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
22
|
50
|
100
|
|
|
47
|
if (($wgs_la >= get_c($class, 'WGS84_min_la')) and ($wgs_la <= get_c($class, 'WGS84_max_la')) and |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
100
|
|
|
|
|
|
|
($wgs_lo >= get_c($class, 'WGS84_min_lo')) and ($wgs_lo <= get_c($class, 'WGS84_max_lo'))) { |
101
|
|
|
|
|
|
|
# Is in bounds |
102
|
14
|
|
|
|
|
53
|
return 1; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
8
|
|
|
|
|
27
|
return; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub ETRSTM35FINxy_to_WGS84lalo { |
109
|
14
|
|
|
14
|
1
|
5854
|
my @params = @_; |
110
|
14
|
|
|
|
|
30
|
my ($class, $etrs_x, $etrs_y) = @params; |
111
|
|
|
|
|
|
|
|
112
|
14
|
100
|
|
|
|
47
|
if (scalar(@params) != 3) { |
113
|
3
|
|
|
|
|
35
|
croak 'Geo::Coordinates::ETRSTM35FIN::ETRSTM35FINxy_to_WGS84lalo needs two arguments' |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
11
|
100
|
|
|
|
28
|
if (!is_defined_ETRSTM35FINxy($class,$etrs_x, $etrs_y)) { |
117
|
4
|
|
|
|
|
21
|
return (undef, undef); |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
7
|
|
|
|
|
18
|
my $E = $etrs_x / (get_c($class,'CA1') * get_c($class,'Ck0')); |
121
|
7
|
|
|
|
|
23
|
my $nn = ($etrs_y - get_c($class,'CE0')) / (get_c($class,'CA1') * get_c($class,'Ck0')); |
122
|
|
|
|
|
|
|
|
123
|
7
|
|
|
|
|
19
|
my $E1p = get_c($class,'Ch1') * sin(2.0 * $E) * Math::Trig::cosh(2.0 * $nn); |
124
|
7
|
|
|
|
|
90
|
my $E2p = get_c($class,'Ch2') * sin(4.0 * $E) * Math::Trig::cosh(4.0 * $nn); |
125
|
7
|
|
|
|
|
64
|
my $E3p = get_c($class,'Ch3') * sin(6.0 * $E) * Math::Trig::cosh(6.0 * $nn); |
126
|
7
|
|
|
|
|
62
|
my $E4p = get_c($class,'Ch4') * sin(8.0 * $E) * Math::Trig::cosh(8.0 * $nn); |
127
|
7
|
|
|
|
|
58
|
my $nn1p = get_c($class,'Ch1') * cos(2.0 * $E) * Math::Trig::sinh(2.0 * $nn); |
128
|
7
|
|
|
|
|
75
|
my $nn2p = get_c($class,'Ch2') * cos(4.0 * $E) * Math::Trig::sinh(4.0 * $nn); |
129
|
7
|
|
|
|
|
69
|
my $nn3p = get_c($class,'Ch3') * cos(6.0 * $E) * Math::Trig::sinh(6.0 * $nn); |
130
|
7
|
|
|
|
|
64
|
my $nn4p = get_c($class,'Ch4') * cos(8.0 * $E) * Math::Trig::sinh(8.0 * $nn); |
131
|
7
|
|
|
|
|
69
|
my $Ep = $E - $E1p - $E2p - $E3p - $E4p; |
132
|
7
|
|
|
|
|
16
|
my $nnp = $nn - $nn1p - $nn2p - $nn3p - $nn4p; |
133
|
7
|
|
|
|
|
23
|
my $be = Math::Trig::asin(sin($Ep) / Math::Trig::cosh($nnp)); |
134
|
|
|
|
|
|
|
|
135
|
7
|
|
|
|
|
138
|
my $Q = Math::Trig::asinh(Math::Trig::tan($be)); |
136
|
7
|
|
|
|
|
167
|
my $Qp = $Q + get_c($class,'Ce') * Math::Trig::atanh(get_c($class,'Ce') * Math::Trig::tanh($Q)); |
137
|
7
|
|
|
|
|
188
|
$Qp = $Q + get_c($class,'Ce') * Math::Trig::atanh(get_c($class,'Ce') * Math::Trig::tanh($Qp)); |
138
|
7
|
|
|
|
|
161
|
$Qp = $Q + get_c($class,'Ce') * Math::Trig::atanh(get_c($class,'Ce') * Math::Trig::tanh($Qp)); |
139
|
7
|
|
|
|
|
152
|
$Qp = $Q + get_c($class,'Ce') * Math::Trig::atanh(get_c($class,'Ce') * Math::Trig::tanh($Qp)); |
140
|
|
|
|
|
|
|
|
141
|
7
|
|
|
|
|
152
|
my $wgs_la = Math::Trig::rad2deg(Math::Trig::atan(Math::Trig::sinh($Qp))); |
142
|
7
|
|
|
|
|
155
|
my $wgs_lo = Math::Trig::rad2deg(get_c($class,'Clo0') + Math::Trig::asin(Math::Trig::tanh($nnp) / cos($be))); |
143
|
|
|
|
|
|
|
|
144
|
7
|
|
|
|
|
216
|
return ($wgs_la, $wgs_lo); |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub WGS84lalo_to_ETRSTM35FINxy { |
148
|
14
|
|
|
14
|
1
|
23246
|
my @params = @_; |
149
|
14
|
|
|
|
|
58
|
my ($class, $wgs_la, $wgs_lo) = @params; |
150
|
|
|
|
|
|
|
|
151
|
14
|
100
|
|
|
|
53
|
if (scalar(@params) != 3) { |
152
|
3
|
|
|
|
|
21
|
croak 'Geo::Coordinates::ETRSTM35FIN::WGS84lalo_to_ETRSTM35FINxy needs two arguments' |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
11
|
100
|
|
|
|
32
|
if (!is_defined_WGS84lalo($class, $wgs_la, $wgs_lo)) { |
156
|
4
|
|
|
|
|
13
|
return (undef, undef); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
7
|
|
|
|
|
32
|
my $la = Math::Trig::deg2rad($wgs_la); |
160
|
7
|
|
|
|
|
88
|
my $lo = Math::Trig::deg2rad($wgs_lo); |
161
|
|
|
|
|
|
|
|
162
|
7
|
|
|
|
|
65
|
my $Q = Math::Trig::asinh(Math::Trig::tan($la)) - get_c($class,'Ce') * Math::Trig::atanh(get_c($class,'Ce') * sin($la)); |
163
|
7
|
|
|
|
|
66
|
my $be = Math::Trig::atan(Math::Trig::sinh($Q)); |
164
|
7
|
|
|
|
|
98
|
my $nnp = Math::Trig::atanh(cos($be) * sin($lo - get_c($class,'Clo0'))); |
165
|
7
|
|
|
|
|
68
|
my $Ep = Math::Trig::asin(sin($be) * Math::Trig::cosh($nnp)); |
166
|
7
|
|
|
|
|
97
|
my $E1 = get_c($class,'Ch1p') * sin(2.0 * $Ep) * Math::Trig::cosh(2.0 * $nnp); |
167
|
7
|
|
|
|
|
60
|
my $E2 = get_c($class,'Ch2p') * sin(4.0 * $Ep) * Math::Trig::cosh(4.0 * $nnp); |
168
|
7
|
|
|
|
|
59
|
my $E3 = get_c($class,'Ch3p') * sin(6.0 * $Ep) * Math::Trig::cosh(6.0 * $nnp); |
169
|
7
|
|
|
|
|
56
|
my $E4 = get_c($class,'Ch4p') * sin(8.0 * $Ep) * Math::Trig::cosh(8.0 * $nnp); |
170
|
|
|
|
|
|
|
|
171
|
7
|
|
|
|
|
60
|
my $nn1 = get_c($class,'Ch1p') * cos(2.0 * $Ep) * Math::Trig::sinh(2.0 * $nnp); |
172
|
7
|
|
|
|
|
69
|
my $nn2 = get_c($class,'Ch2p') * cos(4.0 * $Ep) * Math::Trig::sinh(4.0 * $nnp); |
173
|
7
|
|
|
|
|
65
|
my $nn3 = get_c($class,'Ch3p') * cos(6.0 * $Ep) * Math::Trig::sinh(6.0 * $nnp); |
174
|
7
|
|
|
|
|
63
|
my $nn4 = get_c($class,'Ch4p') * cos(8.0 * $Ep) * Math::Trig::sinh(8.0 * $nnp); |
175
|
7
|
|
|
|
|
65
|
my $E = $Ep + $E1 + $E2 + $E3 + $E4; |
176
|
7
|
|
|
|
|
14
|
my $nn = $nnp + $nn1 + $nn2 + $nn3 + $nn4; |
177
|
|
|
|
|
|
|
|
178
|
7
|
|
|
|
|
19
|
my $etrs_x = get_c($class,'CA1') * $E * get_c($class,'Ck0'); |
179
|
7
|
|
|
|
|
22
|
my $etrs_y = get_c($class,'CA1') * $nn * get_c($class,'Ck0') + get_c($class,'CE0'); |
180
|
|
|
|
|
|
|
|
181
|
7
|
|
|
|
|
31
|
return ($etrs_x, $etrs_y); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
1; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
__END__ |