GeoHash   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 93.94%

Importance

Changes 0
Metric Value
wmc 11
lcom 0
cbo 0
dl 0
loc 95
ccs 31
cts 33
cp 0.9394
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B distance() 0 24 5
B getGeoHashPrecision() 0 24 2
B getPrecisionFromArea() 0 26 4
1
<?php
2
3
namespace Cobak78\GeoHash;
4
5
/**
6
 * Class GeoHash
7
 * @package Cobak78\GeoHash
8
 */
9
class GeoHash
10
{
11
    /**
12
     * @param  float  $lat1
13
     * @param  float  $lon1
14
     * @param  float  $lat2
15
     * @param  float  $lon2
16
     * @param  string $unit
17
     * @return float
18
     */
19 2
    public function distance(
20
        float $lat1,
21
        float $lon1,
22
        float $lat2,
23
        float $lon2,
24
        string $unit = 'K'
25
    ) {
26 2
        $theta = $lon1 - $lon2;
27 2
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
28 2
        $dist = acos($dist);
29 2
        $dist = rad2deg($dist);
30 2
        $miles = $dist * 60 * 1.1515;
31
32 2
        switch (strtoupper($unit)) {
33 2
            case "K":
34 1
            case "KM":
35 2
                return ($miles * 1.609344);
36 1
            case "MN":
37 1
            case "N":
38 1
                return ($miles * 0.8684);
39
            default:
40 1
                return $miles;
41
        }
42
    }
43
44
    /**
45
     * geoBoundBox: [ top_left => [ lat => x, lon => y ], bottom_right => [ lat => x, lon => y ]
46
     *
47
     * @param  array      $geoBoundBox
48
     * @param  int        $squares
49
     * @return mixed
50
     * @throws \Exception
51
     */
52 1
    public function getGeoHashPrecision(array $geoBoundBox, int $squares)
53
    {
54 1
        $remainder = $squares % 2;
55 1
        $xQuotient = $squares / 2;
56 1
        $yQuotient = $xQuotient / 2;
57
58 1
        if (0 !== $remainder) {
59
            throw new \InvalidArgumentException('geoHash divisions must be multiple of 2');
60
        }
61
62
        // get x distance
63 1
        $xDist = $this->distance($geoBoundBox['top_left']['lat'], $geoBoundBox['top_left']['lon'], $geoBoundBox['bottom_right']['lat'], $geoBoundBox['top_left']['lon']);
64 1
        $xDist = $xDist * 1000;
65
        // get y distance
66 1
        $yDist = $this->distance($geoBoundBox['top_left']['lat'], $geoBoundBox['top_left']['lon'], $geoBoundBox['top_left']['lat'], $geoBoundBox['bottom_right']['lon']);
67 1
        $yDist = $yDist * 1000;
68
69
        // geohash distances
70 1
        $xGeohashDist = $xDist / $xQuotient;
71 1
        $yGeohashDist = $yDist / $yQuotient;
72
73 1
        return $this->getPrecisionFromArea($xGeohashDist, $yGeohashDist);
74
75
    }
76
77 1
    private function getPrecisionFromArea($width, $height)
78
    {
79
        // return
80
        $precisionMap = [
81 1
            1 => [5009400, 4992000.6],
82
            2 => [1252300, 624100],
83
            3 => [156500, 156000],
84
            4 => [39100, 19500],
85
            5 => [4900, 4900],
86
            6 => [1200, 609.4],
87
            7 => [152.9, 152.4],
88
            8 => [38.2, 19],
89
            9 => [4.8, 4.8],
90
            10 => [1.2, 0.595],
91
            11 => [0.14, 0.149],
92
            12 => [0.037, 0.019]
93
        ];
94
95 1
        foreach ($precisionMap as $key => $value) {
96 1
            if ($width > $value[0] || $height > $value[1]) {
97 1
                return $key;
98
            }
99
        }
100
101
        return 12;
102
    }
103
}
104