Skip to content

Commit 5116b0f

Browse files
authored
Simplify gis polygon handling (#17904)
* 'Expected' is first param for assertEquals * Do direct string comparisons with gis svg test Ids are not random during tests. * Test gis png and pdf output * Add pdf for i386 architecter, points are slightly different * No special handling for inner and outer rings Signed-off-by: Maximilian Krög <maxi_kroeg@web.de>
1 parent 283d427 commit 5116b0f

29 files changed

Lines changed: 337 additions & 464 deletions

libraries/classes/Gis/GisMultiPolygon.php

Lines changed: 50 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use function mb_substr;
1919
use function round;
2020
use function sprintf;
21-
use function str_contains;
2221
use function trim;
2322

2423
/**
@@ -63,20 +62,11 @@ public function scaleRow($spatial)
6362

6463
// Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
6564
$multipolygon = mb_substr($spatial, 15, -3);
66-
// Separate each polygon
67-
$polygons = explode(')),((', $multipolygon);
68-
69-
foreach ($polygons as $polygon) {
70-
// If the polygon doesn't have an inner ring, use polygon itself
71-
if (! str_contains($polygon, '),(')) {
72-
$ring = $polygon;
73-
} else {
74-
// Separate outer ring and use it to determine min-max
75-
$parts = explode('),(', $polygon);
76-
$ring = $parts[0];
77-
}
65+
$wkt_polygons = explode(')),((', $multipolygon);
7866

79-
$min_max = $this->setMinMax($ring, $min_max);
67+
foreach ($wkt_polygons as $wkt_polygon) {
68+
$wkt_outer_ring = explode('),(', $wkt_polygon)[0];
69+
$min_max = $this->setMinMax($wkt_outer_ring, $min_max);
8070
}
8171

8272
return $min_max;
@@ -108,42 +98,31 @@ public function prepareRowAsPng(
10898
// Separate each polygon
10999
$polygons = explode(')),((', $multipolygon);
110100

111-
$first_poly = true;
112101
foreach ($polygons as $polygon) {
113-
// If the polygon doesn't have an inner polygon
114-
if (! str_contains($polygon, '),(')) {
115-
$points_arr = $this->extractPoints($polygon, $scale_data, true);
116-
} else {
117-
// Separate outer and inner polygons
118-
$parts = explode('),(', $polygon);
119-
$outer = $parts[0];
120-
$inner = array_slice($parts, 1);
121-
122-
$points_arr = $this->extractPoints($outer, $scale_data, true);
123-
124-
foreach ($inner as $inner_poly) {
125-
$points_arr = array_merge(
126-
$points_arr,
127-
$this->extractPoints($inner_poly, $scale_data, true)
128-
);
129-
}
102+
$wkt_rings = explode('),(', $polygon);
103+
104+
$points_arr = [];
105+
106+
foreach ($wkt_rings as $wkt_ring) {
107+
$ring = $this->extractPoints($wkt_ring, $scale_data, true);
108+
$points_arr = array_merge($points_arr, $ring);
130109
}
131110

132111
// draw polygon
133112
$image->filledPolygon($points_arr, $fill_color);
134113
// mark label point if applicable
135-
if ($label !== '' && $first_poly) {
136-
$label_point = [
137-
$points_arr[2],
138-
$points_arr[3],
139-
];
114+
if (isset($label_point)) {
115+
continue;
140116
}
141117

142-
$first_poly = false;
118+
$label_point = [
119+
$points_arr[2],
120+
$points_arr[3],
121+
];
143122
}
144123

145124
// print label if applicable
146-
if (isset($label_point)) {
125+
if ($label !== '' && isset($label_point)) {
147126
$image->string(
148127
1,
149128
(int) round($label_point[0]),
@@ -174,44 +153,32 @@ public function prepareRowAsPdf($spatial, ?string $label, array $color, array $s
174153
// Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
175154
$multipolygon = mb_substr($spatial, 15, -3);
176155
// Separate each polygon
177-
$polygons = explode(')),((', $multipolygon);
156+
$wkt_polygons = explode(')),((', $multipolygon);
178157

179-
$first_poly = true;
180-
foreach ($polygons as $polygon) {
181-
// If the polygon doesn't have an inner polygon
182-
if (! str_contains($polygon, '),(')) {
183-
$points_arr = $this->extractPoints($polygon, $scale_data, true);
184-
} else {
185-
// Separate outer and inner polygons
186-
$parts = explode('),(', $polygon);
187-
$outer = $parts[0];
188-
$inner = array_slice($parts, 1);
189-
190-
$points_arr = $this->extractPoints($outer, $scale_data, true);
191-
192-
foreach ($inner as $inner_poly) {
193-
$points_arr = array_merge(
194-
$points_arr,
195-
$this->extractPoints($inner_poly, $scale_data, true)
196-
);
197-
}
158+
foreach ($wkt_polygons as $wkt_polygon) {
159+
$wkt_rings = explode('),(', $wkt_polygon);
160+
$points_arr = [];
161+
162+
foreach ($wkt_rings as $wkt_ring) {
163+
$ring = $this->extractPoints($wkt_ring, $scale_data, true);
164+
$points_arr = array_merge($points_arr, $ring);
198165
}
199166

200167
// draw polygon
201168
$pdf->Polygon($points_arr, 'F*', [], $color, true);
202169
// mark label point if applicable
203-
if ($label !== '' && $first_poly) {
204-
$label_point = [
205-
$points_arr[2],
206-
$points_arr[3],
207-
];
170+
if (isset($label_point)) {
171+
continue;
208172
}
209173

210-
$first_poly = false;
174+
$label_point = [
175+
$points_arr[2],
176+
$points_arr[3],
177+
];
211178
}
212179

213180
// print label if applicable
214-
if (isset($label_point)) {
181+
if ($label !== '' && isset($label_point)) {
215182
$pdf->setXY($label_point[0], $label_point[1]);
216183
$pdf->setFontSize(5);
217184
$pdf->Cell(0, 0, $label);
@@ -247,25 +214,14 @@ public function prepareRowAsSvg($spatial, $label, array $color, array $scale_dat
247214
// Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
248215
$multipolygon = mb_substr($spatial, 15, -3);
249216
// Separate each polygon
250-
$polygons = explode(')),((', $multipolygon);
217+
$wkt_polygons = explode(')),((', $multipolygon);
251218

252-
foreach ($polygons as $polygon) {
219+
foreach ($wkt_polygons as $wkt_polygon) {
253220
$row .= '<path d="';
254221

255-
// If the polygon doesn't have an inner polygon
256-
if (! str_contains($polygon, '),(')) {
257-
$row .= $this->drawPath($polygon, $scale_data);
258-
} else {
259-
// Separate outer and inner polygons
260-
$parts = explode('),(', $polygon);
261-
$outer = $parts[0];
262-
$inner = array_slice($parts, 1);
263-
264-
$row .= $this->drawPath($outer, $scale_data);
265-
266-
foreach ($inner as $inner_poly) {
267-
$row .= $this->drawPath($inner_poly, $scale_data);
268-
}
222+
$wkt_rings = explode('),(', $wkt_polygon);
223+
foreach ($wkt_rings as $wkt_ring) {
224+
$row .= $this->drawPath($wkt_ring, $scale_data);
269225
}
270226

271227
$polygon_options['id'] = $label . $this->getRandomId();
@@ -519,39 +475,26 @@ public function generateParams($value, $index = -1)
519475
// Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
520476
$multipolygon = mb_substr($wkt, 15, -3);
521477
// Separate each polygon
522-
$polygons = explode(')),((', $multipolygon);
478+
$wkt_polygons = explode(')),((', $multipolygon);
523479

524480
$param_row =& $params[$index]['MULTIPOLYGON'];
525-
$param_row['no_of_polygons'] = count($polygons);
481+
$param_row['no_of_polygons'] = count($wkt_polygons);
526482

527483
$k = 0;
528-
foreach ($polygons as $polygon) {
529-
// If the polygon doesn't have an inner polygon
530-
if (! str_contains($polygon, '),(')) {
531-
$param_row[$k]['no_of_lines'] = 1;
532-
$points_arr = $this->extractPoints($polygon, null);
484+
foreach ($wkt_polygons as $wkt_polygon) {
485+
$wkt_rings = explode('),(', $wkt_polygon);
486+
$param_row[$k]['no_of_lines'] = count($wkt_rings);
487+
$j = 0;
488+
foreach ($wkt_rings as $wkt_ring) {
489+
$points_arr = $this->extractPoints($wkt_ring, null);
533490
$no_of_points = count($points_arr);
534-
$param_row[$k][0]['no_of_points'] = $no_of_points;
491+
$param_row[$k][$j]['no_of_points'] = $no_of_points;
535492
for ($i = 0; $i < $no_of_points; $i++) {
536-
$param_row[$k][0][$i]['x'] = $points_arr[$i][0];
537-
$param_row[$k][0][$i]['y'] = $points_arr[$i][1];
493+
$param_row[$k][$j][$i]['x'] = $points_arr[$i][0];
494+
$param_row[$k][$j][$i]['y'] = $points_arr[$i][1];
538495
}
539-
} else {
540-
// Separate outer and inner polygons
541-
$parts = explode('),(', $polygon);
542-
$param_row[$k]['no_of_lines'] = count($parts);
543-
$j = 0;
544-
foreach ($parts as $ring) {
545-
$points_arr = $this->extractPoints($ring, null);
546-
$no_of_points = count($points_arr);
547-
$param_row[$k][$j]['no_of_points'] = $no_of_points;
548-
for ($i = 0; $i < $no_of_points; $i++) {
549-
$param_row[$k][$j][$i]['x'] = $points_arr[$i][0];
550-
$param_row[$k][$j][$i]['y'] = $points_arr[$i][1];
551-
}
552496

553-
$j++;
554-
}
497+
$j++;
555498
}
556499

557500
$k++;

libraries/classes/Gis/GisPolygon.php

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use function round;
2222
use function sprintf;
2323
use function sqrt;
24-
use function str_contains;
2524
use function trim;
2625

2726
/**
@@ -64,17 +63,9 @@ public function scaleRow($spatial)
6463
{
6564
// Trim to remove leading 'POLYGON((' and trailing '))'
6665
$polygon = mb_substr($spatial, 9, -2);
66+
$wkt_outer_ring = explode('),(', $polygon)[0];
6767

68-
// If the polygon doesn't have an inner ring, use polygon itself
69-
if (! str_contains($polygon, '),(')) {
70-
$ring = $polygon;
71-
} else {
72-
// Separate outer ring and use it to determine min-max
73-
$parts = explode('),(', $polygon);
74-
$ring = $parts[0];
75-
}
76-
77-
return $this->setMinMax($ring, []);
68+
return $this->setMinMax($wkt_outer_ring, []);
7869
}
7970

8071
/**
@@ -101,23 +92,11 @@ public function prepareRowAsPng(
10192
// Trim to remove leading 'POLYGON((' and trailing '))'
10293
$polygon = mb_substr($spatial, 9, -2);
10394

104-
// If the polygon doesn't have an inner polygon
105-
if (! str_contains($polygon, '),(')) {
106-
$points_arr = $this->extractPoints($polygon, $scale_data, true);
107-
} else {
108-
// Separate outer and inner polygons
109-
$parts = explode('),(', $polygon);
110-
$outer = $parts[0];
111-
$inner = array_slice($parts, 1);
112-
113-
$points_arr = $this->extractPoints($outer, $scale_data, true);
114-
115-
foreach ($inner as $inner_poly) {
116-
$points_arr = array_merge(
117-
$points_arr,
118-
$this->extractPoints($inner_poly, $scale_data, true)
119-
);
120-
}
95+
$points_arr = [];
96+
$wkt_rings = explode('),(', $polygon);
97+
foreach ($wkt_rings as $wkt_ring) {
98+
$ring = $this->extractPoints($wkt_ring, $scale_data, true);
99+
$points_arr = array_merge($points_arr, $ring);
121100
}
122101

123102
// draw polygon
@@ -154,23 +133,13 @@ public function prepareRowAsPdf($spatial, ?string $label, array $color, array $s
154133
// Trim to remove leading 'POLYGON((' and trailing '))'
155134
$polygon = mb_substr($spatial, 9, -2);
156135

157-
// If the polygon doesn't have an inner polygon
158-
if (! str_contains($polygon, '),(')) {
159-
$points_arr = $this->extractPoints($polygon, $scale_data, true);
160-
} else {
161-
// Separate outer and inner polygons
162-
$parts = explode('),(', $polygon);
163-
$outer = $parts[0];
164-
$inner = array_slice($parts, 1);
165-
166-
$points_arr = $this->extractPoints($outer, $scale_data, true);
167-
168-
foreach ($inner as $inner_poly) {
169-
$points_arr = array_merge(
170-
$points_arr,
171-
$this->extractPoints($inner_poly, $scale_data, true)
172-
);
173-
}
136+
$wkt_rings = explode('),(', $polygon);
137+
138+
$points_arr = [];
139+
140+
foreach ($wkt_rings as $wkt_ring) {
141+
$ring = $this->extractPoints($wkt_ring, $scale_data, true);
142+
$points_arr = array_merge($points_arr, $ring);
174143
}
175144

176145
// draw polygon
@@ -213,20 +182,9 @@ public function prepareRowAsSvg($spatial, $label, array $color, array $scale_dat
213182

214183
$row = '<path d="';
215184

216-
// If the polygon doesn't have an inner polygon
217-
if (! str_contains($polygon, '),(')) {
218-
$row .= $this->drawPath($polygon, $scale_data);
219-
} else {
220-
// Separate outer and inner polygons
221-
$parts = explode('),(', $polygon);
222-
$outer = $parts[0];
223-
$inner = array_slice($parts, 1);
224-
225-
$row .= $this->drawPath($outer, $scale_data);
226-
227-
foreach ($inner as $inner_poly) {
228-
$row .= $this->drawPath($inner_poly, $scale_data);
229-
}
185+
$wkt_rings = explode('),(', $polygon);
186+
foreach ($wkt_rings as $wkt_ring) {
187+
$row .= $this->drawPath($wkt_ring, $scale_data);
230188
}
231189

232190
$row .= '"';

0 commit comments

Comments
 (0)