Completed
Push — master ( 8235af...8991ff )
by Marcus
06:49 queued 17s
created

SimplifyBearing::simplify()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
dl 10
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Location\Processor\Polyline;
6
7
use Location\Bearing\BearingEllipsoidal;
8
use Location\GeometryInterface;
9
use Location\Polygon;
10
use Location\Polyline;
11
use Monolog\Handler\StreamHandler;
12
use Monolog\Logger;
13
use Monolog\Processor\IntrospectionProcessor;
14
15
/**
16
 * Simplify Polyline.
17
 *
18
 * @author Marcus Jaschen <[email protected]>
19
 */
20
class SimplifyBearing implements SimplifyInterface
21
{
22
    /**
23
     * @var float
24
     */
25
    private $bearingAngle;
26
27
    /**
28
     * SimplifyBearing constructor.
29
     *
30
     * @param float $bearingAngle
31
     */
32
    public function __construct(float $bearingAngle)
33
    {
34
        $this->bearingAngle = $bearingAngle;
35
    }
36
37
    /**
38
     * @param Polyline $polyline
39
     *
40
     * @return Polyline
41
     * @throws \RuntimeException
42
     */
43 View Code Duplication
    public function simplify(Polyline $polyline): Polyline
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44
    {
45
        $result = $this->simplifyGeometry($polyline);
46
47
        if (!($result instanceof Polyline)) {
48
            throw new \RuntimeException('Result is no Polyline', 4231694400);
49
        }
50
51
        return $result;
52
    }
53
54
    /**
55
     * Simplifies the given polyline
56
     *
57
     * 1. calculate the bearing angle between the first two points p1 and p2: b1
58
     * 2. calculate the bearing angle between the next two points p2 and p3: b2
59
     * 3. calculate the difference between b1 and b2: deltaB; if deltaB is
60
     *    smaller than the threshold angle, remove the middle point p2
61
     * 4. start again at (1.) as long as the polyline contains more points
62
     *
63
     * This method will be merged with `simplify()` in the next major release.
64
     *
65
     * @param GeometryInterface $geometry
66
     *
67
     * @return GeometryInterface
68
     */
69
    public function simplifyGeometry(GeometryInterface $geometry): GeometryInterface
70
    {
71
        if (!($geometry instanceof Polyline) && !($geometry instanceof Polygon)) {
72
            return $geometry;
73
        }
74
75
        $counterPoints = $geometry->getNumberOfPoints();
76
77 View Code Duplication
        if ($geometry instanceof Polygon) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
78
            if ($counterPoints <= 3) {
79
                return clone $geometry;
80
            }
81
            $result = new Polygon();
82
        } else {
83
            if ($counterPoints < 3) {
84
                return clone $geometry;
85
            }
86
            $result = new Polyline();
87
        }
88
89
        $bearingCalc = new BearingEllipsoidal();
90
91
        $points = $geometry->getPoints();
92
93
        $index = 0;
94
95
        // add the first point to the resulting polyline
96
        $result->addPoint($points[$index]);
97
98
        do {
99
            $index++;
100
101
            // preserve the last point of the original polyline
102
            if ($index === ($counterPoints - 1)) {
103
                $result->addPoint($points[$index]);
104
                break;
105
            }
106
107
            $bearing1 = $bearingCalc->calculateBearing($points[$index - 1], $points[$index]);
108
            $bearing2 = $bearingCalc->calculateBearing($points[$index], $points[$index + 1]);
109
110
            $bearingDifference = min(
111
                fmod($bearing1 - $bearing2 + 360, 360),
112
                fmod($bearing2 - $bearing1 + 360, 360)
113
            );
114
115
            if ($bearingDifference > $this->bearingAngle) {
116
                $result->addPoint($points[$index]);
117
            }
118
        } while ($index < $counterPoints);
119
120
        return $result;
121
    }
122
}
123