-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathPolygonUtils.php
More file actions
288 lines (260 loc) · 9.06 KB
/
Copy pathPolygonUtils.php
File metadata and controls
288 lines (260 loc) · 9.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
<?php
namespace Mindee\Geometry;
use Mindee\Error\MindeeGeometryException;
/**
* Utility class for Polygon.
*/
abstract class PolygonUtils
{
/**
* Gets the centroid (Point) of a set of points.
*
* @param array $vertices Array of points.
* @return Point
*/
public static function getCentroid(array $vertices): Point
{
$verticesSum = count($vertices);
$xSum = 0.0;
$ySum = 0.0;
foreach ($vertices as $vertex) {
/* @var Point $vertex */
$xSum += $vertex->getX();
$ySum += $vertex->getY();
}
return new Point($xSum / $verticesSum, $ySum / $verticesSum);
}
/**
* Retrieves the minimum y coordinate of a Polygon.
*
* @param Polygon $polygon Polygon to get the minimum y coordinate of.
* @return float
* @throws MindeeGeometryException Throws if a minimum y-axis value cannot
* be found, e.g. if the polygon is empty.
*/
public static function getMinYCoordinate(Polygon $polygon): float
{
$min = null;
foreach ($polygon->getCoordinates() as $point) {
if (!isset($min) || $min > $point->getY()) {
$min = $point->getY();
}
}
if (!isset($min)) {
throw new MindeeGeometryException(
'The provided polygon seems to be empty, or the Y coordinates of each point are invalid.'
);
}
return $min;
}
/**
* Retrieves the minimum x coordinate of a Polygon.
*
* @param Polygon $polygon Polygon to get the minimum y coordinate of.
* @return float
* @throws MindeeGeometryException Throws if a minimum x-axis value cannot be
* found, e.g. if the polygon is empty.
*/
public static function getMinXCoordinate(Polygon $polygon): float
{
$min = null;
foreach ($polygon->getCoordinates() as $point) {
if (!isset($min) || $min > $point->getX()) {
$min = $point->getX();
}
}
if (!isset($min)) {
throw new MindeeGeometryException(
'The provided polygon seems to be empty, or the X coordinates of each point are invalid.'
);
}
return $min;
}
/**
* Retrieves the maximum y coordinate of a Polygon.
*
* @param Polygon $polygon Polygon to get the minimum y coordinate of.
* @return float
* @throws MindeeGeometryException Throws if a maximum y-axis value cannot be
* found, e.g. if the polygon is empty.
*/
public static function getMaxYCoordinate(Polygon $polygon): float
{
$min = null;
foreach ($polygon->getCoordinates() as $point) {
if (!isset($min) || $min < $point->getY()) {
$min = $point->getY();
}
}
if (!isset($min)) {
throw new MindeeGeometryException(
'The provided polygon seems to be empty, or the Y coordinates of each point are invalid.'
);
}
return $min;
}
/**
* Retrieves the maximum x coordinate of a Polygon.
*
* @param Polygon $polygon Polygon to get the minimum y coordinate of.
* @return float
* @throws MindeeGeometryException Throws if a maximum x-axis value cannot be
* found, e.g. if the polygon is empty.
*/
public static function getMaxXCoordinate(Polygon $polygon): float
{
$min = null;
foreach ($polygon->getCoordinates() as $point) {
if (!isset($min) || $min < $point->getX()) {
$min = $point->getX();
}
}
if (!isset($min)) {
throw new MindeeGeometryException(
'The provided polygon seems to be empty, or the X coordinates of each point are invalid.'
);
}
return $min;
}
/**
* Compares two polygons on the Y axis. Returns a sort-compliant result (0;-1;1).
*
* @param Polygon $polygon1 First polygon to compare.
* @param Polygon $polygon2 Second polygon to compare.
* @return integer
*/
public static function compareOnY(Polygon $polygon1, Polygon $polygon2): int
{
$sort = self::getMinYCoordinate($polygon1) - self::getMinYCoordinate($polygon2);
if ($sort == 0) {
return 0;
}
return $sort < 0 ? -1 : 1;
}
/**
* Merges two polygons.
*
* @param Polygon|null $base First polygon to merge.
* @param Polygon|null $target Second polygon to merge.
* @return Polygon
* @throws MindeeGeometryException Throws if both polygons are empty.
*/
public static function merge(?Polygon $base, ?Polygon $target): Polygon
{
if ((!$base || !$base->getCoordinates()) && (!$target || !$target->getCoordinates())) {
throw new MindeeGeometryException('Cannot merge two empty polygons.');
}
if (!$base || !$base->getCoordinates()) {
return $target;
}
if (!$target || !$target->getCoordinates()) {
return $base;
}
return new Polygon(array_unique(array_merge($base->getCoordinates(), $target->getCoordinates()), SORT_REGULAR));
}
/**
* Creates a bounding box from one or two polygons.
*
* @param Polygon|null $base First polygon.
* @param Polygon|null $target Second polygon.
* @return Polygon
*/
public static function createBoundingBoxFrom(?Polygon $base, ?Polygon $target = null): Polygon
{
$merged = PolygonUtils::merge($base, $target);
$topLeft = new Point(self::getMinXCoordinate($merged), self::getMinYCoordinate($merged));
$topRight = new Point(self::getMaxXCoordinate($merged), self::getMinYCoordinate($merged));
$bottomRight = new Point(self::getMaxXCoordinate($merged), self::getMaxYCoordinate($merged));
$bottomLeft = new Point(self::getMinXCoordinate($merged), self::getMaxYCoordinate($merged));
return new Polygon([
$topLeft,
$topRight,
$bottomRight,
$bottomLeft,
]);
}
/**
* Generates a quadrilateral Polygon from a given prediction.
*
* @param array $prediction Raw prediction array.
* @return Polygon
* @throws MindeeGeometryException Throws if the polygon isn't a quadrilateral.
*/
public static function quadrilateralFromPrediction(array $prediction): Polygon
{
if (count($prediction) != 4) {
throw new MindeeGeometryException('Prediction must have exactly 4 points.');
}
return new Polygon([
new Point($prediction[0][0], $prediction[0][1]),
new Point($prediction[1][0], $prediction[1][1]),
new Point($prediction[2][0], $prediction[2][1]),
new Point($prediction[3][0], $prediction[3][1]),
]);
}
/**
* Generates a Polygon from a given prediction.
*
* @deprecated construct a new Polygon() instead.
* @param array $prediction Raw prediction array.
* @return Polygon
*/
public static function polygonFromPrediction(array $prediction): Polygon
{
$points = [];
foreach ($prediction as $point) {
$points[] = new Point($point[0], $point[1]);
}
return new Polygon($points);
}
/**
* Checks whether a point is located within a coordinate range on the x-axis.
*
* @param Point $point Point to check.
* @param float $minX Lower bound.
* @param float $maxX Upper bound.
* @return boolean
*/
public static function isPointInX(Point $point, float $minX, float $maxX): bool
{
return $point->getX() >= $minX && $point->getX() <= $maxX;
}
/**
* Checks whether a point is in a polygon's x-axis range.
*
* @param Point $point Point to check.
* @param Polygon $polygon Polygon.
* @return boolean
*/
public static function isPointInPolygonX(Point $point, Polygon $polygon): bool
{
$minX = MinMaxUtils::getMinMaxX($polygon->getCoordinates())->getMin();
$maxX = MinMaxUtils::getMinMaxX($polygon->getCoordinates())->getMax();
return self::isPointInX($point, $minX, $maxX);
}
/**
* Checks whether a point is located within a coordinate range on the y-axis.
*
* @param Point $point Point to check.
* @param float $minY Lower bound.
* @param float $maxY Upper bound.
* @return boolean
*/
public static function isPointInY(Point $point, float $minY, float $maxY): bool
{
return $point->getY() >= $minY && $point->getY() <= $maxY;
}
/**
* Checks whether a point is in a polygon's y-axis range.
*
* @param Point $point Point to check.
* @param Polygon $polygon Polygon.
* @return boolean
*/
public static function isPointInPolygonY(Point $point, Polygon $polygon): bool
{
$minY = MinMaxUtils::getMinMaxY($polygon->getCoordinates())->getMin();
$maxY = MinMaxUtils::getMinMaxY($polygon->getCoordinates())->getMax();
return self::isPointInY($point, $minY, $maxY);
}
}