Skip to content

Commit 7f898f9

Browse files
Refactor gis scale data set calculation (#18100)
* Add better array types through automatic inference Signed-off-by: Kamil Tekiela <tekiela246@gmail.com> * Create VO for ScaleData Signed-off-by: Kamil Tekiela <tekiela246@gmail.com> * Fix bug with calculation of minimum X/Y 0.0 cannot be used as a sentinel value because it's one of the possible values. Signed-off-by: Kamil Tekiela <tekiela246@gmail.com> * Update baselines Signed-off-by: Kamil Tekiela <tekiela246@gmail.com> --------- Signed-off-by: Kamil Tekiela <tekiela246@gmail.com>
1 parent a0f859b commit 7f898f9

22 files changed

Lines changed: 146 additions & 291 deletions

libraries/classes/Gis/GisGeometry.php

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ abstract public function prepareRowAsOl(
9999
*
100100
* @param string $spatial spatial data of a row
101101
*
102-
* @return array array containing the min, max values for x and y coordinates
102+
* @return ScaleData|null min, max values for x and y coordinates
103103
*/
104-
abstract public function scaleRow($spatial);
104+
abstract public function scaleRow(string $spatial): ?ScaleData;
105105

106106
/**
107107
* Generates the WKT with the set of parameters passed by the GIS editor.
@@ -142,42 +142,27 @@ protected function getBoundsForOl(int $srid, array $scale_data)
142142
/**
143143
* Updates the min, max values with the given point set.
144144
*
145-
* @param string $point_set point set
146-
* @param array $min_max existing min, max values
145+
* @param string $point_set point set
146+
* @param ScaleData|null $scaleData existing min, max values
147147
*
148-
* @return array the updated min, max values
148+
* @return ScaleData|null the updated min, max values
149149
*/
150-
protected function setMinMax($point_set, array $min_max)
150+
protected function setMinMax(string $point_set, ?ScaleData $scaleData = null): ?ScaleData
151151
{
152152
// Separate each point
153153
$points = explode(',', $point_set);
154154

155155
foreach ($points as $point) {
156156
// Extract coordinates of the point
157-
$cordinates = explode(' ', $point);
158-
159-
$x = (float) $cordinates[0];
160-
if (! isset($min_max['maxX']) || $x > $min_max['maxX']) {
161-
$min_max['maxX'] = $x;
162-
}
163-
164-
if (! isset($min_max['minX']) || $x < $min_max['minX']) {
165-
$min_max['minX'] = $x;
166-
}
167-
168-
$y = (float) $cordinates[1];
169-
if (! isset($min_max['maxY']) || $y > $min_max['maxY']) {
170-
$min_max['maxY'] = $y;
171-
}
157+
$coordinates = explode(' ', $point);
172158

173-
if (isset($min_max['minY']) && $y >= $min_max['minY']) {
174-
continue;
175-
}
159+
$x = (float) $coordinates[0];
160+
$y = (float) $coordinates[1];
176161

177-
$min_max['minY'] = $y;
162+
$scaleData = $scaleData === null ? new ScaleData($x, $x, $y, $y) : $scaleData->expand($x, $y);
178163
}
179164

180-
return $min_max;
165+
return $scaleData;
181166
}
182167

183168
/**

libraries/classes/Gis/GisGeometryCollection.php

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,10 @@ public static function singleton()
4949
* Scales each row.
5050
*
5151
* @param string $spatial spatial data of a row
52-
*
53-
* @return array array containing the min, max values for x and y coordinates
5452
*/
55-
public function scaleRow($spatial)
53+
public function scaleRow(string $spatial): ?ScaleData
5654
{
57-
$min_max = [];
55+
$min_max = null;
5856

5957
// Trim to remove leading 'GEOMETRYCOLLECTION(' and trailing ')'
6058
$goem_col = mb_substr($spatial, 19, -1);
@@ -77,28 +75,7 @@ public function scaleRow($spatial)
7775

7876
$scale_data = $gis_obj->scaleRow($sub_part);
7977

80-
// Update minimum/maximum values for x and y coordinates.
81-
$c_maxX = (float) $scale_data['maxX'];
82-
if (! isset($min_max['maxX']) || $c_maxX > $min_max['maxX']) {
83-
$min_max['maxX'] = $c_maxX;
84-
}
85-
86-
$c_minX = (float) $scale_data['minX'];
87-
if (! isset($min_max['minX']) || $c_minX < $min_max['minX']) {
88-
$min_max['minX'] = $c_minX;
89-
}
90-
91-
$c_maxY = (float) $scale_data['maxY'];
92-
if (! isset($min_max['maxY']) || $c_maxY > $min_max['maxY']) {
93-
$min_max['maxY'] = $c_maxY;
94-
}
95-
96-
$c_minY = (float) $scale_data['minY'];
97-
if (isset($min_max['minY']) && $c_minY >= $min_max['minY']) {
98-
continue;
99-
}
100-
101-
$min_max['minY'] = $c_minY;
78+
$min_max = $min_max === null ? $scale_data : $scale_data?->merge($min_max);
10279
}
10380

10481
return $min_max;
@@ -263,9 +240,9 @@ public function prepareRowAsOl($spatial, int $srid, $label, array $color, array
263240
*
264241
* @param string $geom_col geometry collection string
265242
*
266-
* @return array the constituents of the geometry collection object
243+
* @return string[] the constituents of the geometry collection object
267244
*/
268-
private function explodeGeomCol($geom_col)
245+
private function explodeGeomCol($geom_col): array
269246
{
270247
$sub_parts = [];
271248
$br_count = 0;

libraries/classes/Gis/GisLineString.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ public static function singleton()
5151
*
5252
* @param string $spatial spatial data of a row
5353
*
54-
* @return array an array containing the min, max values for x and y coordinates
54+
* @return ScaleData|null the min, max values for x and y coordinates
5555
*/
56-
public function scaleRow($spatial)
56+
public function scaleRow(string $spatial): ?ScaleData
5757
{
5858
// Trim to remove leading 'LINESTRING(' and trailing ')'
5959
$linestring = mb_substr($spatial, 11, -1);
6060

61-
return $this->setMinMax($linestring, []);
61+
return $this->setMinMax($linestring);
6262
}
6363

6464
/**

libraries/classes/Gis/GisMultiLineString.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ public static function singleton()
5252
*
5353
* @param string $spatial spatial data of a row
5454
*
55-
* @return array an array containing the min, max values for x and y coordinates
55+
* @return ScaleData|null the min, max values for x and y coordinates
5656
*/
57-
public function scaleRow($spatial)
57+
public function scaleRow(string $spatial): ?ScaleData
5858
{
59-
$min_max = [];
59+
$min_max = null;
6060

6161
// Trim to remove leading 'MULTILINESTRING((' and trailing '))'
6262
$multilinestirng = mb_substr($spatial, 17, -2);

libraries/classes/Gis/GisMultiPoint.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ public static function singleton()
5151
*
5252
* @param string $spatial spatial data of a row
5353
*
54-
* @return array an array containing the min, max values for x and y coordinates
54+
* @return ScaleData|null the min, max values for x and y coordinates
5555
*/
56-
public function scaleRow($spatial)
56+
public function scaleRow(string $spatial): ?ScaleData
5757
{
5858
// Trim to remove leading 'MULTIPOINT(' and trailing ')'
5959
$multipoint = mb_substr($spatial, 11, -1);
6060

61-
return $this->setMinMax($multipoint, []);
61+
return $this->setMinMax($multipoint);
6262
}
6363

6464
/**

libraries/classes/Gis/GisMultiPolygon.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ public static function singleton()
5454
*
5555
* @param string $spatial spatial data of a row
5656
*
57-
* @return array an array containing the min, max values for x and y coordinates
57+
* @return ScaleData|null the min, max values for x and y coordinates
5858
*/
59-
public function scaleRow($spatial)
59+
public function scaleRow(string $spatial): ?ScaleData
6060
{
61-
$min_max = [];
61+
$min_max = null;
6262

6363
// Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
6464
$multipolygon = mb_substr($spatial, 15, -3);

libraries/classes/Gis/GisPoint.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ public static function singleton()
5050
*
5151
* @param string $spatial spatial data of a row
5252
*
53-
* @return array an array containing the min, max values for x and y coordinates
53+
* @return ScaleData|null the min, max values for x and y coordinates
5454
*/
55-
public function scaleRow($spatial)
55+
public function scaleRow(string $spatial): ?ScaleData
5656
{
5757
// Trim to remove leading 'POINT(' and trailing ')'
5858
$point = mb_substr($spatial, 6, -1);
5959

60-
return $this->setMinMax($point, []);
60+
return $this->setMinMax($point);
6161
}
6262

6363
/**

libraries/classes/Gis/GisPolygon.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ public static function singleton()
5757
*
5858
* @param string $spatial spatial data of a row
5959
*
60-
* @return array an array containing the min, max values for x and y coordinates
60+
* @return ScaleData|null the min, max values for x and y coordinates
6161
*/
62-
public function scaleRow($spatial)
62+
public function scaleRow(string $spatial): ?ScaleData
6363
{
6464
// Trim to remove leading 'POLYGON((' and trailing '))'
6565
$polygon = mb_substr($spatial, 9, -2);
6666
$wkt_outer_ring = explode('),(', $polygon)[0];
6767

68-
return $this->setMinMax($wkt_outer_ring, []);
68+
return $this->setMinMax($wkt_outer_ring);
6969
}
7070

7171
/**

libraries/classes/Gis/GisVisualization.php

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,7 @@ public function toFile($filename, $format): void
517517
*/
518518
private function scaleDataSet(array $data)
519519
{
520-
$min_max = [
521-
'maxX' => 0.0,
522-
'maxY' => 0.0,
523-
'minX' => 0.0,
524-
'minY' => 0.0,
525-
];
520+
$min_max = null;
526521
$border = 15;
527522
// effective width and height of the plot
528523
$plot_width = $this->settings['width'] - 2 * $border;
@@ -547,55 +542,37 @@ private function scaleDataSet(array $data)
547542
continue;
548543
}
549544

550-
$scale_data = $gis_obj->scaleRow($row[$this->settings['spatialColumn']]);
545+
$scaleData = $gis_obj->scaleRow($row[$this->settings['spatialColumn']]);
551546

552547
// Update minimum/maximum values for x and y coordinates.
553-
$c_maxX = (float) $scale_data['maxX'];
554-
if ($min_max['maxX'] === 0.0 || $c_maxX > $min_max['maxX']) {
555-
$min_max['maxX'] = $c_maxX;
556-
}
557-
558-
$c_minX = (float) $scale_data['minX'];
559-
if ($min_max['minX'] === 0.0 || $c_minX < $min_max['minX']) {
560-
$min_max['minX'] = $c_minX;
561-
}
562-
563-
$c_maxY = (float) $scale_data['maxY'];
564-
if ($min_max['maxY'] === 0.0 || $c_maxY > $min_max['maxY']) {
565-
$min_max['maxY'] = $c_maxY;
566-
}
567-
568-
$c_minY = (float) $scale_data['minY'];
569-
if ($min_max['minY'] !== 0.0 && $c_minY >= $min_max['minY']) {
570-
continue;
571-
}
572-
573-
$min_max['minY'] = $c_minY;
548+
$min_max = $min_max === null ? $scaleData : $scaleData?->merge($min_max);
574549
}
575550

551+
$min_max ??= new ScaleData(0, 0, 0, 0);
552+
576553
// scale the visualization
577-
$x_ratio = ($min_max['maxX'] - $min_max['minX']) / $plot_width;
578-
$y_ratio = ($min_max['maxY'] - $min_max['minY']) / $plot_height;
554+
$x_ratio = ($min_max->maxX - $min_max->minX) / $plot_width;
555+
$y_ratio = ($min_max->maxY - $min_max->minY) / $plot_height;
579556
$ratio = $x_ratio > $y_ratio ? $x_ratio : $y_ratio;
580557

581558
$scale = $ratio != 0 ? 1 / $ratio : 1;
582559

583560
// Center plot
584561
$x = $ratio == 0 || $x_ratio < $y_ratio
585-
? ($min_max['maxX'] + $min_max['minX'] - $this->settings['width'] / $scale) / 2
586-
: $min_max['minX'] - ($border / $scale);
562+
? ($min_max->maxX + $min_max->minX - $this->settings['width'] / $scale) / 2
563+
: $min_max->minX - ($border / $scale);
587564
$y = $ratio == 0 || $x_ratio >= $y_ratio
588-
? ($min_max['maxY'] + $min_max['minY'] - $this->settings['height'] / $scale) / 2
589-
: $min_max['minY'] - ($border / $scale);
565+
? ($min_max->maxY + $min_max->minY - $this->settings['height'] / $scale) / 2
566+
: $min_max->minY - ($border / $scale);
590567

591568
return [
592569
'scale' => $scale,
593570
'x' => $x,
594571
'y' => $y,
595-
'minX' => $min_max['minX'],
596-
'maxX' => $min_max['maxX'],
597-
'minY' => $min_max['minY'],
598-
'maxY' => $min_max['maxY'],
572+
'minX' => $min_max->minX,
573+
'maxX' => $min_max->maxX,
574+
'minY' => $min_max->minY,
575+
'maxY' => $min_max->maxY,
599576
'height' => $this->settings['height'],
600577
];
601578
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\Gis;
6+
7+
use function max;
8+
use function min;
9+
10+
class ScaleData
11+
{
12+
public function __construct(
13+
public readonly float $maxX,
14+
public readonly float $minX,
15+
public readonly float $maxY,
16+
public readonly float $minY,
17+
) {
18+
}
19+
20+
public function expand(float $x, float $y): ScaleData
21+
{
22+
return new ScaleData(
23+
max($this->maxX, $x),
24+
min($this->minX, $x),
25+
max($this->maxY, $y),
26+
min($this->minY, $y),
27+
);
28+
}
29+
30+
public function merge(ScaleData $scaleData): ScaleData
31+
{
32+
return new ScaleData(
33+
max($this->maxX, $scaleData->maxX),
34+
min($this->minX, $scaleData->minX),
35+
max($this->maxY, $scaleData->maxY),
36+
min($this->minY, $scaleData->minY),
37+
);
38+
}
39+
}

0 commit comments

Comments
 (0)