Completed
Push — master ( 095ec2...a9618e )
by Marcus
01:28 queued 12s
created

PointToLineDistance::getDistance()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 38
rs 9.312
c 0
b 0
f 0
cc 4
nc 4
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Location\Utility;
6
7
use Location\Coordinate;
8
use Location\Distance\DistanceInterface;
9
use Location\Line;
10
11
class PointToLineDistance
12
{
13
    /**
14
     * @var DistanceInterface
15
     */
16
    private $distanceCalculator;
17
18
    /**
19
     * PointToLineDistance constructor.
20
     * @param DistanceInterface $distanceCalculator
21
     */
22
    public function __construct(DistanceInterface $distanceCalculator)
23
    {
24
        $this->distanceCalculator = $distanceCalculator;
25
    }
26
27
    /**
28
     * @param Coordinate $point
29
     * @param Line $line
30
     *
31
     * @return float
32
     */
33
    public function getDistance(Coordinate $point, Line $line): float
34
    {
35
        if ($line->getPoint1()->hasSameLocation($line->getPoint2())) {
36
            return $this->distanceCalculator->getDistance($point, $line->getPoint1());
37
        }
38
39
        $pLat = deg2rad($point->getLat());
40
        $pLng = deg2rad($point->getLng());
41
42
        $l1Lat = deg2rad($line->getPoint1()->getLat());
43
        $l1Lng = deg2rad($line->getPoint1()->getLng());
44
        $l2Lat = deg2rad($line->getPoint2()->getLat());
45
        $l2Lng = deg2rad($line->getPoint2()->getLng());
46
47
        $deltal2l1Lat = $l2Lat - $l1Lat;
48
        $deltal2l1Lng = $l2Lng - $l1Lng;
49
50
        $u = (($pLat - $l1Lat) * $deltal2l1Lat + ($pLng - $l1Lng) * $deltal2l1Lng) / ($deltal2l1Lat ** 2 + $deltal2l1Lng ** 2);
51
52
        if ($u <= 0) {
53
            return $this->distanceCalculator->getDistance($point, $line->getPoint1());
54
        }
55
56
        if ($u >= 1) {
57
            return $this->distanceCalculator->getDistance($point, $line->getPoint2());
58
        }
59
60
        $tmpPoint1 = new Coordinate(
61
            $point->getLat() - $line->getPoint1()->getLat(),
62
            $point->getLng() - $line->getPoint1()->getLng()
63
        );
64
        $tmpPoint2 = new Coordinate(
65
            $u * ($line->getPoint2()->getLat() - $line->getPoint1()->getLat()),
66
            $u * ($line->getPoint2()->getLng() - $line->getPoint1()->getLng())
67
        );
68
69
        return $this->distanceCalculator->getDistance($tmpPoint1, $tmpPoint2);
70
    }
71
}
72