Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
MapUtils
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
5 / 5
5
100.00% covered (success)
100.00%
1 / 1
 WGStoCHy
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 WGStoCHx
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 CHtoWGSlat
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 CHtoWGSlng
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 DECtoSEX
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Olz\Utils;
4
5// Source: http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/projections.html (see PDFs under "Documentation")
6// Updated 9 dec 2014
7// Please validate your results with NAVREF on-line service: http://www.swisstopo.admin.ch/internet/swisstopo/en/home/apps/calc/navref.html (difference ~ 1-2m)
8
9/**
10 * Note: `latitude` may be from -90.0 to 90.0, `longitude` from -180.0 to 180.0.
11 *
12 * @phpstan-type OlzLocationCoordinates array{latitude: float, longitude: float}
13 */
14class MapUtils {
15    use WithUtilsTrait;
16
17    // Convert WGS lat/long (° dec) to CH y
18    public function WGStoCHy(int|float $lat, int|float $long): int|float {
19        // Converts decimal degrees sexagesimal seconds
20        $lat = $this->DECtoSEX($lat);
21        $long = $this->DECtoSEX($long);
22
23        // Auxiliary values (% Bern)
24        $lat_aux = ($lat - 169028.66) / 10000;
25        $long_aux = ($long - 26782.5) / 10000;
26
27        // Process Y
28        return 600072.37
29            + 211455.93 * $long_aux
30            - 10938.51 * $long_aux * $lat_aux
31            - 0.36 * $long_aux * pow($lat_aux, 2)
32            - 44.54 * pow($long_aux, 3);
33    }
34
35    // Convert WGS lat/long (° dec) to CH x
36    public function WGStoCHx(int|float $lat, int|float $long): int|float {
37        // Converts decimal degrees sexagesimal seconds
38        $lat = $this->DECtoSEX($lat);
39        $long = $this->DECtoSEX($long);
40
41        // Auxiliary values (% Bern)
42        $lat_aux = ($lat - 169028.66) / 10000;
43        $long_aux = ($long - 26782.5) / 10000;
44
45        // Process X
46        return 200147.07
47            + 308807.95 * $lat_aux
48            + 3745.25 * pow($long_aux, 2)
49            + 76.63 * pow($lat_aux, 2)
50            - 194.56 * pow($long_aux, 2) * $lat_aux
51            + 119.79 * pow($lat_aux, 3);
52    }
53
54    // Convert CH y/x to WGS lat
55    public function CHtoWGSlat(int|float $y, int|float $x): int|float {
56        // Converts military to civil and  to unit = 1000km
57        // Auxiliary values (% Bern)
58        $y_aux = ($y - 600000) / 1000000;
59        $x_aux = ($x - 200000) / 1000000;
60
61        // Process lat
62        $lat = 16.9023892
63            + 3.238272 * $x_aux
64            - 0.270978 * pow($y_aux, 2)
65            - 0.002528 * pow($x_aux, 2)
66            - 0.0447 * pow($y_aux, 2) * $x_aux
67            - 0.0140 * pow($x_aux, 3);
68
69        // Unit 10000" to 1 " and converts seconds to degrees (dec)
70        return $lat * 100 / 36;
71    }
72
73    // Convert CH y/x to WGS long
74    public function CHtoWGSlng(int|float $y, int|float $x): int|float {
75        // Converts military to civil and  to unit = 1000km
76        // Auxiliary values (% Bern)
77        $y_aux = ($y - 600000) / 1000000;
78        $x_aux = ($x - 200000) / 1000000;
79
80        // Process long
81        $long = 2.6779094
82            + 4.728982 * $y_aux
83            + 0.791484 * $y_aux * $x_aux
84            + 0.1306 * $y_aux * pow($x_aux, 2)
85            - 0.0436 * pow($y_aux, 3);
86
87        // Unit 10000" to 1 " and converts seconds to degrees (dec)
88        return $long * 100 / 36;
89    }
90
91    // Convert DEC angle to SEX DMS
92    protected function DECtoSEX(int|float $angle): int|float {
93        // Extract DMS
94        $deg = intval($angle);
95        $min = intval(($angle - $deg) * 60);
96        $sec = ((($angle - $deg) * 60) - $min) * 60;
97
98        // Result in sexagesimal seconds
99        return $sec + $min * 60 + $deg * 3600;
100    }
101}