DistanceCalculator   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 5
lcom 1
cbo 5
dl 0
loc 88
ccs 21
cts 21
cp 1
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A create() 0 4 2
A distance() 0 4 1
A calculate() 0 23 1
1
<?php namespace Arcanedev\GeoLocation\Calculators;
2
3
use Arcanedev\GeoLocation\Contracts\Calculators\DistanceCalculator as DistanceCalculatorContract;
4
use Arcanedev\GeoLocation\Contracts\Entities\Coordinates\Position;
5
use Arcanedev\GeoLocation\Contracts\Entities\Sphere;
6
use Arcanedev\GeoLocation\Entities\Measures\Distance;
7
use Arcanedev\GeoLocation\Entities\Spheres\Earth;
8
9
/**
10
 * Class     DistanceCalculator
11
 *
12
 * @package  Arcanedev\GeoLocation
13
 * @author   ARCANEDEV <[email protected]>
14
 */
15
class DistanceCalculator implements DistanceCalculatorContract
16
{
17
    /* -----------------------------------------------------------------
18
     |  Properties
19
     | -----------------------------------------------------------------
20
     */
21
22
    /** @var  \Arcanedev\GeoLocation\Contracts\Entities\Sphere */
23
    private $sphere;
24
25
    /* -----------------------------------------------------------------
26
     |  Constructor
27
     | -----------------------------------------------------------------
28
     */
29
30
    /**
31
     * DistanceCalculator constructor.
32
     *
33
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Sphere  $sphere
34
     */
35 12
    public function __construct(Sphere $sphere)
36
    {
37 12
        $this->sphere = $sphere;
38 12
    }
39
40
    /* -----------------------------------------------------------------
41
     |  Main Methods
42
     | -----------------------------------------------------------------
43
     */
44
45
    /**
46
     * Create a metric distance calculator, using earth as base sphere.
47
     *
48
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Sphere|null  $sphere
49
     *
50
     * @return self
51
     */
52 9
    public static function create($sphere = null)
53
    {
54 9
        return new static($sphere ?: new Earth);
55
    }
56
57
    /**
58
     * Calculate the distance between two positions.
59
     *
60
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Coordinates\Position  $start
61
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Coordinates\Position  $end
62
     *
63
     * @return \Arcanedev\GeoLocation\Entities\Measures\Distance
64
     */
65 6
    public function calculate(Position $start, Position $end)
66
    {
67 6
        $deltaLatitude = deg2rad(
68 6
            $start->lat()->value() - $end->lat()->value()
69
        );
70
71 6
        $deltaLongitude = deg2rad(
72 6
            $start->lng()->value() - $end->lng()->value()
73
        );
74
75 6
        $angle = asin(
76 4
            sqrt(
77 6
                pow(sin($deltaLatitude * 0.5), 2)
78 6
                + cos(deg2rad($start->lat()->value()))
79 6
                * cos(deg2rad($end->lat()->value()))
80 6
                * pow(sin($deltaLongitude * 0.5), 2)
81
            )
82 6
        ) * 2;
83
84 6
        $value = $angle * $this->sphere->radius();
85
86 6
        return new Distance("{$value} meters", $value);
87
    }
88
89
    /**
90
     * Calculate the numeric distance between two positions.
91
     *
92
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Coordinates\Position  $start
93
     * @param  \Arcanedev\GeoLocation\Contracts\Entities\Coordinates\Position  $end
94
     * @param  int                                                             $precision
95
     *
96
     * @return float
97
     */
98 3
    public function distance(Position $start, Position $end, $precision = 2)
99
    {
100 3
        return round($this->calculate($start, $end)->value(), $precision);
101
    }
102
}
103