Skip to content

Commit

Permalink
Allow Compound -> Geocentric conversions too, plus some cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
dvdoug committed Feb 20, 2023
1 parent 21cd64e commit 5dd3a0b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 23 deletions.
36 changes: 17 additions & 19 deletions src/CompoundPoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,26 +146,24 @@ public function convert(Compound|Geocentric|Geographic2D|Geographic3D|Projected|
}
}
}
if ($to instanceof Geographic3D) {
// try converting to any/all of the other Compound CRSs that include the same vertical CRS, where the
// horizontal CRS has a 3D equivalent. From there, try converting using the usual mechanisms
$candidateIntermediates = Compound::findFromVertical($this->getVerticalPoint()->getCRS());
unset($candidateIntermediates[$this->getCRS()->getSRID()]);

foreach ($candidateIntermediates as $candidateIntermediate) {
try {
if ($candidateIntermediate->getHorizontal() instanceof Geographic2D && $candidateIntermediate->getHorizontal()->getBaseCRS() instanceof Geographic3D) {
$candidateHorizontalPoint = $this->getHorizontalPoint()->convert($candidateIntermediate->getHorizontal());
$candidateIntermediatePoint = self::create(
$candidateIntermediate,
$candidateHorizontalPoint,
$this->getVerticalPoint()
);

return $candidateIntermediatePoint->convert($candidateIntermediate->getHorizontal()->getBaseCRS())->convert($to);
}
} catch (Throwable) {
// try converting to any/all of the other Compound CRSs that include the same vertical CRS, where the
// horizontal CRS has a 3D equivalent. From there, try converting using the usual mechanisms
$candidateIntermediates = Compound::findFromVertical($this->getVerticalPoint()->getCRS());
unset($candidateIntermediates[$this->getCRS()->getSRID()]);

foreach ($candidateIntermediates as $candidateIntermediate) {
try {
if ($candidateIntermediate->getHorizontal() instanceof Geographic2D && $candidateIntermediate->getHorizontal()->getBaseCRS() instanceof Geographic3D) {
$candidateHorizontalPoint = $this->getHorizontalPoint()->convert($candidateIntermediate->getHorizontal());
$candidateIntermediatePoint = self::create(
$candidateIntermediate,
$candidateHorizontalPoint,
$this->getVerticalPoint()
);

return $candidateIntermediatePoint->convert($candidateIntermediate->getHorizontal()->getBaseCRS())->convert($to);
}
} catch (Throwable) {
}
}
throw $e;
Expand Down
6 changes: 3 additions & 3 deletions src/CoordinateOperation/AutoConversion.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ protected function validatePath(array $candidatePath, Compound|Geocentric|Geogra

// filter out operations that use a 2D CRS as intermediate where this is a 3D point
$currentCRS = $this->getCRS();
if ($currentCRS instanceof Compound || $currentCRS instanceof Geocentric || $currentCRS instanceof Geographic3D || $currentCRS instanceof Vertical) {
if ($target instanceof Compound || $target instanceof Geocentric || $target instanceof Geographic3D || $target instanceof Vertical) {
if ($currentCRS instanceof Compound || count($currentCRS->getCoordinateSystem()->getAxes()) === 3) {
if ($target instanceof Compound || count($target->getCoordinateSystem()->getAxes()) !== 2) {
$intermediateTarget = CoordinateReferenceSystem::fromSRID($pathStep['in_reverse'] ? $pathStep['source_crs'] : $pathStep['target_crs']);
if ($intermediateTarget instanceof Geographic2D || $intermediateTarget instanceof Projected) {
if (!$intermediateTarget instanceof Compound && count($intermediateTarget->getCoordinateSystem()->getAxes()) === 2) {
return false;
}
}
Expand Down
28 changes: 27 additions & 1 deletion tests/CoordinateOperation/AutoConversionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ public function testRDNAPToETRS89(): void
self::assertEqualsWithDelta(301.798133706, $to->getHeight()->asMetres()->getValue(), 0.00001);
}

public function testRDNAPToWGS84(): void
public function testRDNAPToWGS84Geographic3D(): void
{
if (!class_exists(GTXETRS89NAPProvider::class)) {
self::markTestSkipped('Requires phpcoord/datapack-europe');
Expand All @@ -422,6 +422,32 @@ public function testRDNAPToWGS84(): void
self::assertEqualsWithDelta(301.798133706, $to->getHeight()->asMetres()->getValue(), 0.00001);
}

public function testRDNAPToWGS84Geocentric(): void
{
if (!class_exists(GTXETRS89NAPProvider::class)) {
self::markTestSkipped('Requires phpcoord/datapack-europe');
}

$from = CompoundPoint::create(
Compound::fromSRID(Compound::EPSG_AMERSFOORT_RD_NEW_PLUS_NAP_HEIGHT),
ProjectedPoint::createFromEastingNorthing(
Projected::fromSRID(Projected::EPSG_AMERSFOORT_RD_NEW),
new Metre(108360.8790),
new Metre(415757.2745),
),
VerticalPoint::create(
Vertical::fromSRID(Vertical::EPSG_NAP_HEIGHT),
new Metre(258.0057)
)
);
$toCRS = Geocentric::fromSRID(Geocentric::EPSG_WGS_84);
$to = $from->convert($toCRS);

self::assertEqualsWithDelta(3945517.9766847, $to->getX()->asMetres()->getValue(), 0.00001);
self::assertEqualsWithDelta(325220.90092962, $to->getY()->asMetres()->getValue(), 0.00001);
self::assertEqualsWithDelta(4984392.7931562, $to->getZ()->asMetres()->getValue(), 0.00001);
}

public function testNAD83NAD27SouthCarolina(): void
{
if (!class_exists(NADCON5NAD832007NAD832011CONUSLatitudeProvider::class)) {
Expand Down

0 comments on commit 5dd3a0b

Please sign in to comment.