Completed
Push — master ( 77cc75...3bc278 )
by Marcus
01:17
created

Line::getMidpoint()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Location;
6
7
use Location\Bearing\BearingInterface;
8
use Location\Distance\DistanceInterface;
9
use Location\Utility\Cartesian;
10
11
/**
12
 * Line Implementation
13
 *
14
 * @author Marcus Jaschen <[email protected]>
15
 */
16
class Line implements GeometryInterface
17
{
18
    use GetBoundsTrait;
19
20
    /**
21
     * @var Coordinate
22
     */
23
    protected $point1;
24
25
    /**
26
     * @var Coordinate
27
     */
28
    protected $point2;
29
30
    /**
31
     * @param Coordinate $point1
32
     * @param Coordinate $point2
33
     */
34
    public function __construct(Coordinate $point1, Coordinate $point2)
35
    {
36
        $this->point1 = $point1;
37
        $this->point2 = $point2;
38
    }
39
40
    /**
41
     * @param Coordinate $point1
42
     *
43
     * @return void
44
     */
45
    public function setPoint1(Coordinate $point1)
46
    {
47
        $this->point1 = $point1;
48
    }
49
50
    /**
51
     * @return Coordinate
52
     */
53
    public function getPoint1(): Coordinate
54
    {
55
        return $this->point1;
56
    }
57
58
    /**
59
     * @param Coordinate $point2
60
     *
61
     * @return void
62
     */
63
    public function setPoint2(Coordinate $point2)
64
    {
65
        $this->point2 = $point2;
66
    }
67
68
    /**
69
     * @return Coordinate
70
     */
71
    public function getPoint2(): Coordinate
72
    {
73
        return $this->point2;
74
    }
75
76
    /**
77
     * Returns an array containing the two points.
78
     *
79
     * @return Coordinate[]
80
     */
81
    public function getPoints(): array
82
    {
83
        return [$this->point1, $this->point2];
84
    }
85
86
    /**
87
     * Calculates the length of the line (distance between the two
88
     * coordinates).
89
     *
90
     * @param DistanceInterface $calculator instance of distance calculation class
91
     *
92
     * @return float
93
     */
94
    public function getLength(DistanceInterface $calculator): float
95
    {
96
        return $calculator->getDistance($this->point1, $this->point2);
97
    }
98
99
    /**
100
     * @param BearingInterface $bearingCalculator
101
     *
102
     * @return float
103
     */
104
    public function getBearing(BearingInterface $bearingCalculator): float
105
    {
106
        return $bearingCalculator->calculateBearing($this->point1, $this->point2);
107
    }
108
109
    /**
110
     * @param BearingInterface $bearingCalculator
111
     *
112
     * @return float
113
     */
114
    public function getFinalBearing(BearingInterface $bearingCalculator): float
115
    {
116
        return $bearingCalculator->calculateFinalBearing($this->point1, $this->point2);
117
    }
118
119
    /**
120
     * Create a new instance with reversed point order, i. e. reversed direction.
121
     *
122
     * @return Line
123
     */
124
    public function getReverse(): Line
125
    {
126
        return new static($this->point2, $this->point1);
127
    }
128
129
    /**
130
     * Get the midpoint of a Line segment
131
     *
132
     * @see http://www.movable-type.co.uk/scripts/latlong.html#midpoint
133
     *
134
     * @return Coordinate
135
     */
136
    public function getMidpoint() : Coordinate
137
    {
138
        $lat1 = deg2rad($this->point1->getLat());
139
        $lng1 = deg2rad($this->point1->getLng());
140
        $lat2 = deg2rad($this->point2->getLat());
141
        $lng2 = deg2rad($this->point2->getLng());
142
        $deltaLng = $lng2 - $lng1;
143
144
        $A = new Cartesian(cos($lat1), 0, sin($lat1));
145
        $B = new Cartesian(cos($lat2) * cos($deltaLng), cos($lat2) * sin($deltaLng), sin($lat2));
146
        $C = $A->add($B);
147
148
        $latMid = atan2($C->getZ(), sqrt($C->getX() ** 2 + $C->getY() ** 2));
149
        $lngMid = $lng1 + atan2($C->getY(), $C->getX());
150
151
        return new Coordinate(rad2deg($latMid), rad2deg($lngMid));
152
    }
153
}
154