Completed
Push — milestone/4.0 ( 4a7219...1803cd )
by Marcus
01:48
created

SimplifyBearing::simplify()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 42
rs 8.9368
c 0
b 0
f 0
cc 5
nc 4
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Phpgeo\Processor\Polyline;
6
7
use Phpgeo\Bearing\BearingEllipsoidal;
8
use Phpgeo\Polyline;
9
10
/**
11
 * Simplify Polyline.
12
 *
13
 * @author Marcus Jaschen <[email protected]>
14
 */
15
class SimplifyBearing implements SimplifyInterface
16
{
17
    /**
18
     * @var float
19
     */
20
    private $bearingAngle;
21
22
    /**
23
     * SimplifyBearing constructor.
24
     *
25
     * @param float $bearingAngle
26
     */
27
    public function __construct(float $bearingAngle)
28
    {
29
        $this->bearingAngle = $bearingAngle;
30
    }
31
32
    /**
33
     * Simplifies the given polyline
34
     *
35
     * 1. calculate the bearing angle between the first two points p1 and p2: b1
36
     * 2. calculate the bearing angle between the next two points p2 and p3: b2
37
     * 3. calculate the difference between b1 and b2: deltaB; if deltaB is
38
     *    smaller than the threshold angle, remove the middle point p2
39
     * 4. start again at (1.) as long as the polyline contains more points
40
     *
41
     * @param Polyline $polyline
42
     *
43
     * @return Polyline
44
     */
45
    public function simplify(Polyline $polyline): Polyline
46
    {
47
        $counterPoints = $polyline->getNumberOfPoints();
48
49
        if ($counterPoints < 3) {
50
            return clone $polyline;
51
        }
52
53
        $result      = new Polyline();
54
        $bearingCalc = new BearingEllipsoidal();
55
56
        $points = $polyline->getPoints();
57
58
        $index = 0;
59
60
        // add the first point to the resulting polyline
61
        $result->addPoint($points[$index]);
62
63
        do {
64
            $index++;
65
66
            // preserve the last point of the original polyline
67
            if ($index === ($counterPoints - 1)) {
68
                $result->addPoint($points[$index]);
69
                break;
70
            }
71
72
            $bearing1 = $bearingCalc->calculateBearing($points[$index - 1], $points[$index]);
73
            $bearing2 = $bearingCalc->calculateBearing($points[$index], $points[$index + 1]);
74
75
            $bearingDifference = min(
76
                fmod($bearing1 - $bearing2 + 360, 360),
77
                fmod($bearing2 - $bearing1 + 360, 360)
78
            );
79
80
            if ($bearingDifference > $this->bearingAngle) {
81
                $result->addPoint($points[$index]);
82
            }
83
        } while ($index < $counterPoints);
84
85
        return $result;
86
    }
87
}
88