1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the CGI-Calc package. |
5
|
|
|
* |
6
|
|
|
* (c) Milos Tomic <[email protected]> |
7
|
|
|
* |
8
|
|
|
* This source file is subject to the MIT license that is bundled |
9
|
|
|
* with this source code in the file LICENSE. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Cgi\Calc\Point; |
13
|
|
|
|
14
|
|
|
use Cgi\Calc\Point; |
15
|
|
|
|
16
|
|
|
class Path implements \Countable |
17
|
|
|
{ |
18
|
|
|
/** @var Point[] */ |
19
|
|
|
private $points; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @param Point[] $points |
23
|
|
|
*/ |
24
|
|
|
public function __construct(array $points) |
25
|
|
|
{ |
26
|
|
|
$this->points = []; |
27
|
|
|
foreach ($points as $point) { |
28
|
|
|
if ($point instanceof Point) { |
29
|
|
|
$this->points[] = $point; |
30
|
|
|
} else { |
31
|
|
|
throw new \InvalidArgumentException('Expected instance of Point class'); |
32
|
|
|
} |
33
|
|
|
} |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @return Point[] |
38
|
|
|
*/ |
39
|
|
|
public function getPoints() |
40
|
|
|
{ |
41
|
|
|
return $this->points; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @return bool |
46
|
|
|
*/ |
47
|
|
|
public function isMonotonouslyIncreasingX() |
48
|
|
|
{ |
49
|
|
|
return count($this->points) > 1 && $this->getMonotony($this->getAllX()) === 1; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @return bool |
54
|
|
|
*/ |
55
|
|
|
public function isMonotonouslyIncreasingY() |
56
|
|
|
{ |
57
|
|
|
return count($this->points) > 1 && $this->getMonotony($this->getAllY()) === 1; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @return int|float[] |
62
|
|
|
*/ |
63
|
|
|
public function getAllX() |
64
|
|
|
{ |
65
|
|
|
return array_map(function (Point $p) { |
66
|
|
|
return $p->getX(); |
67
|
|
|
}, $this->points); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @return int|float[] |
72
|
|
|
*/ |
73
|
|
|
public function getAllY() |
74
|
|
|
{ |
75
|
|
|
return array_map(function (Point $p) { |
76
|
|
|
return $p->getY(); |
77
|
|
|
}, $this->points); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* @return int |
82
|
|
|
*/ |
83
|
|
|
public function count() |
84
|
|
|
{ |
85
|
|
|
return count($this->points); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @return Point|null |
90
|
|
|
*/ |
91
|
|
|
public function firstPoint() |
92
|
|
|
{ |
93
|
|
|
return reset($this->points); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @return Point|null |
98
|
|
|
*/ |
99
|
|
|
public function lastPoint() |
100
|
|
|
{ |
101
|
|
|
return end($this->points); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* @return Line |
106
|
|
|
*/ |
107
|
|
|
public function firstLine() |
108
|
|
|
{ |
109
|
|
|
return new Line($this->points[0], $this->points[1]); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
public function lastLine() |
113
|
|
|
{ |
114
|
|
|
$count = count($this->points); |
115
|
|
|
|
116
|
|
|
return new Line($this->points[$count - 2], $this->points[$count - 1]); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @return LineIterator |
121
|
|
|
*/ |
122
|
|
|
public function getLineIterator() |
123
|
|
|
{ |
124
|
|
|
return new LineIterator($this); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* @return \ArrayIterator |
129
|
|
|
*/ |
130
|
|
|
public function getPointIterator() |
131
|
|
|
{ |
132
|
|
|
return new \ArrayIterator($this->points); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* @param int[] $arr |
137
|
|
|
* |
138
|
|
|
* @return int|null Null if not monotonous, -1 if monotony decreasing, +1 if monotony increasing |
139
|
|
|
*/ |
140
|
|
|
public function getMonotony(array $arr) |
141
|
|
|
{ |
142
|
|
|
$count = 0; |
143
|
|
|
$previous = null; |
144
|
|
|
$sign = null; // 1 for increasing, -1 for decreasing |
|
|
|
|
145
|
|
|
foreach ($arr as $item) { |
146
|
|
|
++$count; |
147
|
|
|
if (2 === $count) { |
148
|
|
|
$sign = $previous < $item ? 1 : -1; // is second element greater or smaller then first |
149
|
|
|
} elseif ($sign > 0 && $item < $previous) { // is still increasing |
150
|
|
|
return null; |
151
|
|
|
} elseif ($sign < 0 && $item > $previous) { // is still decreasing |
152
|
|
|
return null; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
$previous = $item; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
return $sign; |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.