Skip to content

Commit

Permalink
Add RoundCoordinatesProjector
Browse files Browse the repository at this point in the history
  • Loading branch information
BenMorel committed Aug 19, 2024
1 parent 28b5f1c commit bcc19f3
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [0.11.1](https://github.com/brick/geo/releases/tag/0.11.1) - 2024-08-19

**New features**

- New projector: `RoundCoordinatesProjector`

## [0.11.0](https://github.com/brick/geo/releases/tag/0.11.0) - 2024-06-07

💥 **Breaking changes**
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,24 @@ The library supports reading and writing `Feature` and `FeatureCollection` objec

GeoJSON aims to support WGS84 only, and as such all Geometries are imported using [SRID 4326](https://epsg.io/4326).

## Reducing coordinate precision

Before exporting geometries in a text format, you may need reduce the precision of the coordinates to keep the output small, while retaining a sufficient precision.
You can use the `RoundCoordinatesProjector` for this:

```php
use Brick\Geo\Point;
use Brick\Geo\Projector\RoundCoordinatesProjector;

$roundProjector = new RoundCoordinatesProjector(2);

$point = Point::xy(1.2345678, 2.3456789);
echo $point->asText(); // POINT (1.2345678 2.3456789)

$roundedPoint = $roundProjector->project($point);
echo $roundedPoint->asText(); // POINT (1.23 2.35)
```

## Doctrine mappings

You can use `brick/geo` types in your Doctrine entities using the [brick/geo-doctrine](https://github.com/brick/geo-doctrine) package.
35 changes: 35 additions & 0 deletions src/Projector/RoundCoordinatesProjector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Brick\Geo\Projector;

use Brick\Geo\CoordinateSystem;
use Brick\Geo\Point;

/**
* Rounds coordinates to a given precision.
* This projector is typically used to simplify the WKT representation of geometries.
*/
final class RoundCoordinatesProjector implements Projector
{
public function __construct(
private readonly int $precision,
) {
}

public function project(Point $point): Point
{
$coords = array_map(
fn (float $coord): float => round($coord, $this->precision),
$point->toArray(),
);

return new Point($point->coordinateSystem(), ...$coords);
}

public function getTargetCoordinateSystem(CoordinateSystem $sourceCoordinateSystem): CoordinateSystem
{
return $sourceCoordinateSystem;
}
}
55 changes: 55 additions & 0 deletions tests/Projector/RoundCoordinatesProjectorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Brick\Geo\Tests\Projector;

use Brick\Geo\CoordinateSystem;
use Brick\Geo\Point;
use Brick\Geo\Projector\RoundCoordinatesProjector;
use Brick\Geo\Tests\AbstractTestCase;
use PHPUnit\Framework\Attributes\DataProvider;

/**
* Unit tests for class RoundCoordinatesProjector.
*/
class RoundCoordinatesProjectorTest extends AbstractTestCase
{
#[DataProvider('providerProject')]
public function testProject(float $x, float $y, int $srid, int $precision, float $expectedX, float $expectedY): void
{
$projector = new RoundCoordinatesProjector($precision);

$point = Point::xy($x, $y, $srid);
$projected = $projector->project($point);

$this->assertPointXYEquals($expectedX, $expectedY, $srid, $projected);
}

public static function providerProject(): array
{
return [
[1.234567, 2.345678, 1234, 0, 1, 2],
[1.234567, 2.345678, 2345, 1, 1.2, 2.3],
[1.234567, 2.345678, 3456, 2, 1.23, 2.35],
[1.234567, 2.345678, 4567, 3, 1.235, 2.346],
];
}

#[DataProvider('providerGetTargetCoordinateSystem')]
public function testGetTargetCoordinateSystem(CoordinateSystem $sourceCoordinateSystem): void
{
$projector = new RoundCoordinatesProjector(2);
$targetCoordinateSystem = $projector->getTargetCoordinateSystem($sourceCoordinateSystem);

$this->assertSame($sourceCoordinateSystem, $targetCoordinateSystem);
}

public static function providerGetTargetCoordinateSystem(): array
{
return [
[CoordinateSystem::xy(4326)],
[CoordinateSystem::xyz(2154)],
];
}
}

0 comments on commit bcc19f3

Please sign in to comment.