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     * @param float $radius
24     * @return float Distance in meters
25     */
26    public static function distance( $lat1, $lon1, $lat2, $lon2, float $radius ): float {
27        $lat1 = deg2rad( $lat1 );
28        $lon1 = deg2rad( $lon1 );
29        $lat2 = deg2rad( $lat2 );
30        $lon2 = deg2rad( $lon2 );
31        $sin1 = sin( ( $lat2 - $lat1 ) / 2 );
32        $sin2 = sin( ( $lon2 - $lon1 ) / 2 );
33        return 2 * $radius *
34            asin( sqrt( $sin1 * $sin1 + cos( $lat1 ) * cos( $lat2 ) * $sin2 * $sin2 ) );
35    }
36
37    /**
38     * Wraps coordinate values around globe boundaries
39     *
40     * @param float &$from
41     * @param float &$to
42     * @param float $min
43     * @param float $max
44     */
45    public static function wrapAround( &$from, &$to, $min, $max ): void {
46        $range = $max - $min;
47        $from = $min + fmod( 2 * $range - $min + $from, $range );
48        // The edge case on the right should not wrap around, e.g. +180 should not become -180
49        $to = $max - fmod( 2 * $range + $max - $to, $range );
50    }
51
52    /**
53     * @param float $x
54     * @return int 1 or -1
55     */
56    public static function sign( $x ): int {
57        return $x < 0 ? -1 : 1;
58    }
59}