DistanceCalculator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 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