Completed
Push — master ( d764a5...d44ab1 )
by Mr
03:18
created

Geo   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
eloc 25
dl 0
loc 97
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A randomCoordinates() 0 21 2
A getCoordinatesWithinRadius() 0 9 3
A isCoordinatesInRadius() 0 8 1
A randomCoordinatesArray() 0 10 2
A radians() 0 3 1
1
<?php
2
3
namespace DrMVC\Helpers;
4
5
/**
6
 * Simple geoposition class based on below answer
7
 * @link http://stackoverflow.com/a/17286519/7977798
8
 * @package DrMVC\Helpers
9
 */
10
class Geo
11
{
12
    /**
13
     * Generate array of random coordinates for tests
14
     *
15
     * @param   int $radius In kilometers
16
     * @return  array
17
     */
18
    public static function randomCoordinates(int $radius = 100): array
19
    {
20
        $result = [];
21
22
        try {
23
            // Random angle (from 0 bad idea)
24
            $angle = deg2rad(random_int(1, 359));
25
            // Random radius (from 0 bad idea)
26
            $pointRadius = random_int(1, $radius);
27
            // Result array
28
            $result = [
29
                // Latitude
30
                sin($angle) * $pointRadius,
31
                // Longitude
32
                cos($angle) * $pointRadius
33
            ];
34
        } catch (\Exception $e) {
35
            echo $e->getMessage() . "\n";
36
        }
37
38
        return $result;
39
    }
40
    /**
41
     * Generate array of random coordinates for tests
42
     *
43
     * @param   int $count  Count of results
44
     * @param   int $radius In kilometers
45
     * @return  array
46
     */
47
    public static function randomCoordinatesArray($count = 1, int $radius = 100): array
48
    {
49
        $result = [];
50
51
        // If count is set
52
        for ($i = 0; $i < $count; $i++) {
53
            $result[] = self::randomCoordinates($radius);
54
        }
55
56
        return $result;
57
    }
58
59
    /**
60
     * The length of an arc of a unit circle is numerically equal to
61
     * the measurement in radians of the angle that it subtends.
62
     *
63
     * @link    https://en.wikipedia.org/wiki/Radian
64
     * @param   string $degree The number needed to calculate radians
65
     * @return  float|int
66
     */
67
    public static function radians($degree)
68
    {
69
        return $degree * M_PI / 180;
70
    }
71
72
    /**
73
     * Return array of coordinates within some radius
74
     *
75
     * @param   array     $coordinates Multidimensional array with coordinates for comparing [[latitude,longitude],[latitude,longitude],[latitude,longitude]]
76
     * @param   array     $center      Array with coordinates of center [latitude,longitude]
77
     * @param   int|float $radius      In kilometers or meters (1 - km, .1 - 100 meters)
78
     * @return  array Simple array with LAT,LON coordinates which are within the radius
79
     */
80
    public static function getCoordinatesWithinRadius(array $coordinates, array $center, $radius): array
81
    {
82
        $resultArray = [];
83
        foreach ($coordinates as $key => $coordinate) {
84
            if (self::isCoordinatesInRadius($coordinate, $center, $radius)) {
85
                $resultArray[$key] = $coordinate;
86
            }
87
        }
88
        return $resultArray;
89
    }
90
91
    /**
92
     * Check if coordinates is nearby center in radius
93
     *
94
     * @param   array     $coordinates Array with coordinates for comparing [latitude,longitude]
95
     * @param   array     $center      Array with coordinates of center [latitude,longitude]
96
     * @param   int|float $radius      In kilometers or meters (1 - km, .1 - 100 meters)
97
     * @return  bool
98
     */
99
    public static function isCoordinatesInRadius(array $coordinates, array $center, $radius): bool
100
    {
101
        list($lat1, $long1) = $center;
102
        list($lat2, $long2) = $coordinates;
103
104
        $distance = 3959 * acos(cos(self::radians($lat1)) * cos(self::radians($lat2)) * cos(self::radians($long2) - self::radians($long1)) + sin(self::radians($lat1)) * sin(self::radians($lat2)));
105
106
        return ($distance <= $radius);
107
    }
108
}
109