Skip to content

Commit

Permalink
Fix gis extent calculation
Browse files Browse the repository at this point in the history
Signed-off-by: Maximilian Krög <maxi_kroeg@web.de>
  • Loading branch information
MoonE authored and MauricioFauth committed Mar 30, 2023
1 parent b91b1c2 commit c5343ee
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 51 deletions.
11 changes: 11 additions & 0 deletions libraries/classes/Gis/GisGeometry.php
Expand Up @@ -21,11 +21,20 @@
use function str_replace;
use function trim;

use const INF;

/**
* Base class for all GIS data type classes.
*/
abstract class GisGeometry
{
public const EMPTY_EXTENT = [
'minX' => +INF,
'minY' => +INF,
'maxX' => -INF,
'maxY' => -INF,
];

/**
* Prepares and returns the code related to a row in the GIS dataset as SVG.
*
Expand Down Expand Up @@ -143,8 +152,10 @@ protected function getBoundsForOl(int $srid, array $scale_data)
*
* @param string $point_set point set
* @param array $min_max existing min, max values
* @psalm-param array{minX:float,minY:float,maxX:float,maxY:float} $min_max *
*
* @return array the updated min, max values
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
protected function setMinMax($point_set, array $min_max)
{
Expand Down
2 changes: 1 addition & 1 deletion libraries/classes/Gis/GisGeometryCollection.php
Expand Up @@ -54,7 +54,7 @@ public static function singleton()
*/
public function scaleRow($spatial)
{
$min_max = [];
$min_max = GisGeometry::EMPTY_EXTENT;

// Trim to remove leading 'GEOMETRYCOLLECTION(' and trailing ')'
$goem_col = mb_substr($spatial, 19, -1);
Expand Down
3 changes: 2 additions & 1 deletion libraries/classes/Gis/GisLineString.php
Expand Up @@ -52,13 +52,14 @@ public static function singleton()
* @param string $spatial spatial data of a row
*
* @return array an array containing the min, max values for x and y coordinates
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
public function scaleRow($spatial)
{
// Trim to remove leading 'LINESTRING(' and trailing ')'
$linestring = mb_substr($spatial, 11, -1);

return $this->setMinMax($linestring, []);
return $this->setMinMax($linestring, GisGeometry::EMPTY_EXTENT);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion libraries/classes/Gis/GisMultiLineString.php
Expand Up @@ -53,10 +53,11 @@ public static function singleton()
* @param string $spatial spatial data of a row
*
* @return array an array containing the min, max values for x and y coordinates
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
public function scaleRow($spatial)
{
$min_max = [];
$min_max = GisGeometry::EMPTY_EXTENT;

// Trim to remove leading 'MULTILINESTRING((' and trailing '))'
$multilinestirng = mb_substr($spatial, 17, -2);
Expand Down
3 changes: 2 additions & 1 deletion libraries/classes/Gis/GisMultiPoint.php
Expand Up @@ -52,13 +52,14 @@ public static function singleton()
* @param string $spatial spatial data of a row
*
* @return array an array containing the min, max values for x and y coordinates
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
public function scaleRow($spatial)
{
// Trim to remove leading 'MULTIPOINT(' and trailing ')'
$multipoint = mb_substr($spatial, 11, -1);

return $this->setMinMax($multipoint, []);
return $this->setMinMax($multipoint, GisGeometry::EMPTY_EXTENT);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion libraries/classes/Gis/GisMultiPolygon.php
Expand Up @@ -56,10 +56,11 @@ public static function singleton()
* @param string $spatial spatial data of a row
*
* @return array an array containing the min, max values for x and y coordinates
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
public function scaleRow($spatial)
{
$min_max = [];
$min_max = GisGeometry::EMPTY_EXTENT;

// Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))'
$multipolygon = mb_substr($spatial, 15, -3);
Expand Down
3 changes: 2 additions & 1 deletion libraries/classes/Gis/GisPoint.php
Expand Up @@ -51,13 +51,14 @@ public static function singleton()
* @param string $spatial spatial data of a row
*
* @return array an array containing the min, max values for x and y coordinates
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
public function scaleRow($spatial)
{
// Trim to remove leading 'POINT(' and trailing ')'
$point = mb_substr($spatial, 6, -1);

return $this->setMinMax($point, []);
return $this->setMinMax($point, GisGeometry::EMPTY_EXTENT);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion libraries/classes/Gis/GisPolygon.php
Expand Up @@ -59,6 +59,7 @@ public static function singleton()
* @param string $spatial spatial data of a row
*
* @return array an array containing the min, max values for x and y coordinates
* @psalm-return array{minX:float,minY:float,maxX:float,maxY:float}
*/
public function scaleRow($spatial)
{
Expand All @@ -74,7 +75,7 @@ public function scaleRow($spatial)
$ring = $parts[0];
}

return $this->setMinMax($ring, []);
return $this->setMinMax($ring, GisGeometry::EMPTY_EXTENT);
}

/**
Expand Down
23 changes: 13 additions & 10 deletions libraries/classes/Gis/GisVisualization.php
Expand Up @@ -17,6 +17,7 @@
use function base64_encode;
use function count;
use function intval;
use function is_finite;
use function is_numeric;
use function is_string;
use function mb_strlen;
Expand Down Expand Up @@ -543,12 +544,7 @@ public function toFile($filename, $format): void
*/
private function scaleDataSet(array $data)
{
$min_max = [
'maxX' => 0.0,
'maxY' => 0.0,
'minX' => 0.0,
'minY' => 0.0,
];
$min_max = GisGeometry::EMPTY_EXTENT;
$border = 15;
// effective width and height of the plot
$plot_width = $this->settings['width'] - 2 * $border;
Expand Down Expand Up @@ -577,28 +573,35 @@ private function scaleDataSet(array $data)

// Update minimum/maximum values for x and y coordinates.
$c_maxX = (float) $scale_data['maxX'];
if ($min_max['maxX'] === 0.0 || $c_maxX > $min_max['maxX']) {
if ($c_maxX > $min_max['maxX']) {
$min_max['maxX'] = $c_maxX;
}

$c_minX = (float) $scale_data['minX'];
if ($min_max['minX'] === 0.0 || $c_minX < $min_max['minX']) {
if ($c_minX < $min_max['minX']) {
$min_max['minX'] = $c_minX;
}

$c_maxY = (float) $scale_data['maxY'];
if ($min_max['maxY'] === 0.0 || $c_maxY > $min_max['maxY']) {
if ($c_maxY > $min_max['maxY']) {
$min_max['maxY'] = $c_maxY;
}

$c_minY = (float) $scale_data['minY'];
if ($min_max['minY'] !== 0.0 && $c_minY >= $min_max['minY']) {
if ($c_minY >= $min_max['minY']) {
continue;
}

$min_max['minY'] = $c_minY;
}

if (! is_finite($min_max['minX']) || ! is_finite($min_max['minY'])) {
$min_max['maxX'] = 0.0;
$min_max['maxY'] = 0.0;
$min_max['minX'] = 0.0;
$min_max['minY'] = 0.0;
}

// scale the visualization
$x_ratio = ($min_max['maxX'] - $min_max['minX']) / $plot_width;
$y_ratio = ($min_max['maxY'] - $min_max['minY']) / $plot_height;
Expand Down
64 changes: 32 additions & 32 deletions phpstan-baseline.neon
Expand Up @@ -3746,12 +3746,22 @@ parameters:
path: libraries/classes/Gis/GisGeometry.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisGeometry\\:\\:setMinMax\\(\\) has parameter \\$min_max with no value type specified in iterable type array\\.$#"
message: "#^Offset 'maxX' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometry.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisGeometry\\:\\:setMinMax\\(\\) return type has no value type specified in iterable type array\\.$#"
message: "#^Offset 'maxY' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometry.php

-
message: "#^Offset 'minX' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometry.php

-
message: "#^Offset 'minY' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometry.php

Expand Down Expand Up @@ -3805,6 +3815,26 @@ parameters:
count: 1
path: libraries/classes/Gis/GisGeometryCollection.php

-
message: "#^Offset 'maxX' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometryCollection.php

-
message: "#^Offset 'maxY' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometryCollection.php

-
message: "#^Offset 'minX' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometryCollection.php

-
message: "#^Offset 'minY' on array\\{minX\\: float, minY\\: float, maxX\\: float, maxY\\: float\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: libraries/classes/Gis/GisGeometryCollection.php

-
message: "#^Static property PhpMyAdmin\\\\Gis\\\\GisGeometryCollection\\:\\:\\$instance \\(PhpMyAdmin\\\\Gis\\\\GisGeometryCollection\\) in isset\\(\\) is not nullable\\.$#"
count: 1
Expand Down Expand Up @@ -3845,11 +3875,6 @@ parameters:
count: 1
path: libraries/classes/Gis/GisLineString.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisLineString\\:\\:scaleRow\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Gis/GisLineString.php

-
message: "#^Parameter \\#5 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:line\\(\\) expects int, int\\|false given\\.$#"
count: 1
Expand Down Expand Up @@ -3905,11 +3930,6 @@ parameters:
count: 1
path: libraries/classes/Gis/GisMultiLineString.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisMultiLineString\\:\\:scaleRow\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Gis/GisMultiLineString.php

-
message: "#^Parameter \\#5 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:line\\(\\) expects int, int\\|false given\\.$#"
count: 1
Expand Down Expand Up @@ -3970,11 +3990,6 @@ parameters:
count: 1
path: libraries/classes/Gis/GisMultiPoint.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisMultiPoint\\:\\:scaleRow\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Gis/GisMultiPoint.php

-
message: "#^Parameter \\#5 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:string\\(\\) expects int, int\\|false given\\.$#"
count: 1
Expand Down Expand Up @@ -4035,11 +4050,6 @@ parameters:
count: 1
path: libraries/classes/Gis/GisMultiPolygon.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisMultiPolygon\\:\\:scaleRow\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Gis/GisMultiPolygon.php

-
message: "#^Parameter \\#2 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:filledPolygon\\(\\) expects int, int\\|false given\\.$#"
count: 1
Expand Down Expand Up @@ -4095,11 +4105,6 @@ parameters:
count: 1
path: libraries/classes/Gis/GisPoint.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisPoint\\:\\:scaleRow\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Gis/GisPoint.php

-
message: "#^Parameter \\#5 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:string\\(\\) expects int, int\\|false given\\.$#"
count: 1
Expand Down Expand Up @@ -4185,11 +4190,6 @@ parameters:
count: 1
path: libraries/classes/Gis/GisPolygon.php

-
message: "#^Method PhpMyAdmin\\\\Gis\\\\GisPolygon\\:\\:scaleRow\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Gis/GisPolygon.php

-
message: "#^Parameter \\#2 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:filledPolygon\\(\\) expects int, int\\|false given\\.$#"
count: 1
Expand Down
3 changes: 2 additions & 1 deletion psalm-baseline.xml
Expand Up @@ -15640,7 +15640,8 @@
</NonInvariantDocblockPropertyType>
</file>
<file src="test/classes/Gis/GisVisualizationTest.php">
<MixedAssignment occurrences="9">
<MixedAssignment occurrences="10">
<code>$dataSet</code>
<code>$dataSet</code>
<code>$queryString</code>
<code>$queryString</code>
Expand Down
2 changes: 1 addition & 1 deletion test/classes/Gis/GisGeometryTest.php
Expand Up @@ -71,7 +71,7 @@ public function providerForTestSetMinMax(): array
return [
[
'12 35,48 75,69 23,25 45,14 53,35 78',
[],
GisGeometry::EMPTY_EXTENT,
[
'minX' => 12,
'maxX' => 69,
Expand Down
26 changes: 26 additions & 0 deletions test/classes/Gis/GisVisualizationTest.php
Expand Up @@ -80,6 +80,32 @@ public function testScaleDataSet(): void
],
$dataSet
);

// Regression test for bug with 0.0 sentinel values
$dataSet = $this->callFunction(
$gis,
GisVisualization::class,
'scaleDataSet',
[
[
['abc' => 'MULTIPOLYGON(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'],
['abc' => 'MULTIPOLYGON(((10 10,10 13,13 13,13 10,10 10),(11 11,11 12,12 12,12 11,11 11)))'],
],
]
);
$this->assertSame(
[
'scale' => 32.30769230769231,
'x' => -2.7857142857142865,
'y' => -0.4642857142857143,
'minX' => 0.0,
'maxX' => 13.0,
'minY' => 0.0,
'maxY' => 13.0,
'height' => 450,
],
$dataSet
);
}

/**
Expand Down

0 comments on commit c5343ee

Please sign in to comment.