Skip to content

Commit a7711d2

Browse files
committed
Gis ScaleData offsets in target coordinate system
Signed-off-by: Maximilian Krög <maxi_kroeg@web.de>
1 parent 9ffbb7f commit a7711d2

5 files changed

Lines changed: 80 additions & 15 deletions

File tree

src/Gis/Ds/ScaleData.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public function __construct(
1010
public readonly float $scale,
1111
public readonly float $offsetX,
1212
public readonly float $offsetY,
13+
public readonly int $width,
1314
public readonly int $height,
1415
) {
1516
}

src/Gis/GisGeometry.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ private function extractPointsInternal(string $pointSet, ScaleData|null $scaleDa
250250
$x = (float) $coordinates[0];
251251
$y = (float) $coordinates[1];
252252
if ($scaleData !== null) {
253-
$x = ($x - $scaleData->offsetX) * $scaleData->scale;
254-
$y = $scaleData->height - ($y - $scaleData->offsetY) * $scaleData->scale;
253+
$x = $x * $scaleData->scale + $scaleData->offsetX;
254+
$y = -$y * $scaleData->scale - $scaleData->offsetY;
255255
}
256256
} else {
257257
$x = 0.0;

src/Gis/GisVisualization.php

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -463,14 +463,27 @@ private function scaleDataSet(array $data): ScaleData|null
463463
$scale = $ratio === 0.0 ? 1.0 : 1.0 / $ratio;
464464

465465
// Center plot
466-
$x = $ratio === 0.0 || $xRatio < $yRatio
467-
? ($extent->maxX + $extent->minX - $this->width / $scale) / 2
468-
: $extent->minX - ($this->border / $scale);
469-
$y = $ratio === 0.0 || $xRatio >= $yRatio
470-
? ($extent->maxY + $extent->minY - $this->height / $scale) / 2
471-
: $extent->minY - ($this->border / $scale);
472-
473-
return new ScaleData(scale: $scale, offsetX: $x, offsetY: $y, height: $this->height);
466+
$offsetX = -$extent->minX * $scale;
467+
if ($ratio === 0.0) {
468+
$offsetX += $plotWidth / 2;
469+
} elseif ($xRatio < $yRatio) {
470+
$offsetX += ($plotWidth - ($extent->maxX - $extent->minX) * $scale) / 2;
471+
}
472+
473+
$offsetY = -$extent->minY * $scale;
474+
if ($ratio === 0.0) {
475+
$offsetY += $plotHeight / 2;
476+
} elseif ($xRatio > $yRatio) {
477+
$offsetY += ($plotHeight - ($extent->maxY - $extent->minY) * $scale) / 2;
478+
}
479+
480+
return new ScaleData(
481+
scale: $scale,
482+
offsetX: $offsetX + $this->border,
483+
offsetY: $offsetY + $this->border - $this->height,
484+
width: $this->width,
485+
height: $this->height,
486+
);
474487
}
475488

476489
/**

tests/unit/Gis/GisGeometryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public static function providerForTestExtractPointsInternal(): array
153153
// with scale data
154154
[
155155
'12 35,48 75,69 23',
156-
new ScaleData(offsetX: 5, offsetY: 5, scale: 2, height: 200),
156+
new ScaleData(scale: 2.0, offsetX: -10.0, offsetY: -210.0, width: 200, height: 200),
157157
false,
158158
[[14, 140], [86, 60], [128, 164]],
159159
],

tests/unit/Gis/GisVisualizationTest.php

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@ public function testScaleDataSet(): void
9999
);
100100
self::assertEquals(
101101
new ScaleData(
102-
offsetX: -45.35714285714286,
103-
offsetY: 42.85714285714286,
102+
offsetX: 95.24999999999999,
103+
offsetY: -540.0,
104104
scale: 2.1,
105+
width: 600,
105106
height: 450,
106107
),
107108
$dataSet,
@@ -122,8 +123,9 @@ public function testScaleDataSet(): void
122123
self::assertEquals(
123124
new ScaleData(
124125
scale: 32.30769230769231,
125-
offsetX: -2.7857142857142865,
126-
offsetY: -0.4642857142857143,
126+
offsetX: 90.0,
127+
offsetY: -435.0,
128+
width: 600,
127129
height: 450,
128130
),
129131
$dataSet,
@@ -307,6 +309,55 @@ public function testModifyQueryMariaDB(): void
307309
);
308310
}
309311

312+
#[DataProvider('providerForTestScale')]
313+
public function testScale(ScaleData|null $expected, array $data): void
314+
{
315+
$vis = GisVisualization::getByData(
316+
$data,
317+
new GisVisualizationSettings(width: 200, height: 150, spatialColumn: 'wkt'),
318+
);
319+
$scaleData = (new ReflectionClass($vis))->getMethod('scaleDataSet')->invoke(
320+
$vis,
321+
array_map(static fn (string $wkt): array => ['wkt' => $wkt], $data),
322+
);
323+
$this->assertEquals($expected, $scaleData);
324+
}
325+
326+
public static function providerForTestScale(): array
327+
{
328+
return [
329+
'empty' => [null, []],
330+
'Point - centered' => [
331+
new ScaleData(scale: 1.0, offsetX: 100.0, offsetY: -75.0, width: 200, height: 150),
332+
['POINT(0 0)'],
333+
],
334+
'Linestring - vertically centered' => [
335+
new ScaleData(scale: 0.1, offsetX: 0.0, offsetY: -76.0, width: 200, height: 150),
336+
['LINESTRING(150 10,1850 10)'],
337+
],
338+
'Polygon - empty space at the top and bottom' => [
339+
new ScaleData(scale: 17.0, offsetX: -155.0, offsetY: -75.0, width: 200, height: 150),
340+
['POLYGON((10 -1,20 -1,20 1,10 1,10 -1))'],
341+
],
342+
'MultiPoint - horizontally centered' => [
343+
new ScaleData(scale: 10.0, offsetX: -99900.0, offsetY: -135.0, width: 200, height: 150),
344+
['MULTIPOINT(10000 0,10000 12)'],
345+
],
346+
'MultiLineString - fitting exactly' => [
347+
new ScaleData(scale: 1.0, offsetX: 0.0, offsetY: -150.0, width: 200, height: 150),
348+
['MULTILINESTRING((15 15,100 100),(185 135,100 50))'],
349+
],
350+
'MultiPolygon - fitting exactly' => [
351+
new ScaleData(scale: 60.0, offsetX: 40.0, offsetY: -75.0, width: 200, height: 150),
352+
['MULTIPOLYGON(((0 0,1 1,0 1,0 0)),((1 -1,2 -1,2 0,1 -1)))'],
353+
],
354+
'GeometryCollection - empty space at either side' => [
355+
new ScaleData(scale: 6.0, offsetX: 1000.0, offsetY: -1335.0, width: 200, height: 150),
356+
['GEOMETRYCOLLECTION(MULTIPOINT(-149 201,-151 219),LINESTRING(-150 200,-150 220))'],
357+
],
358+
];
359+
}
360+
310361
public static function providerTestGisData(): array
311362
{
312363
return [

0 commit comments

Comments
 (0)