Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Math
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
3 / 3
4
100.00% covered (success)
100.00%
1 / 1
 distance
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 wrapAround
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 sign
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace GeoData;
4
5/**
6 * Class that performs basic coordinate calculations
7 * Note that the formulas are useful only for our specific purposes, some of them may be
8 * inaccurate for long distances. Oh well.
9 *
10 * All the functions that accept coordinates assume that they're in degrees, not radians.
11 */
12class Math {
13    public const EARTH_RADIUS = 6371010.0;
14
15    /**
16     * Calculates distance between two coordinates
17     * @see https://en.wikipedia.org/wiki/Haversine_formula
18     *
19     * @param float $lat1
20     * @param float $lon1
21     * @param float $lat2
22     * @param float $lon2
23     * @return float Distance in meters
24     */
25    public static function distance( $lat1, $lon1, $lat2, $lon2 ): float {
26        $lat1 = deg2rad( $lat1 );
27        $lon1 = deg2rad( $lon1 );
28        $lat2 = deg2rad( $lat2 );
29        $lon2 = deg2rad( $lon2 );
30        $sin1 = sin( ( $lat2 - $lat1 ) / 2 );
31        $sin2 = sin( ( $lon2 - $lon1 ) / 2 );
32        return 2 * self::EARTH_RADIUS *
33            asin( sqrt( $sin1 * $sin1 + cos( $lat1 ) * cos( $lat2 ) * $sin2 * $sin2 ) );
34    }
35
36    /**
37     * Wraps coordinate values around globe boundaries
38     *
39     * @param float &$from
40     * @param float &$to
41     * @param float $min
42     * @param float $max
43     */
44    public static function wrapAround( &$from, &$to, $min, $max ): void {
45        $range = $max - $min;
46        $from = $min + fmod( 2 * $range - $min + $from, $range );
47        // The edge case on the right should not wrap around, e.g. +180 should not become -180
48        $to = $max - fmod( 2 * $range + $max - $to, $range );
49    }
50
51    /**
52     * @param float $x
53     * @return int 1 or -1
54     */
55    public static function sign( $x ): int {
56        return $x < 0 ? -1 : 1;
57    }
58}