Skip to content

Commit 97ae4fe

Browse files
committed
createOperations(): remove recently added exception for NTF to ETRS89
1 parent 40eb0d6 commit 97ae4fe

2 files changed

Lines changed: 166 additions & 34 deletions

File tree

src/iso19111/operation/coordinateoperationfactory.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ struct PrecomputedOpCharacteristics {
865865
bool isApprox_ = false;
866866
bool hasBallparkVertical_ = false;
867867
bool isNullTransformation_ = false;
868+
bool hasXYZGridshift_ = false;
868869

869870
// 3 below tests are for ETRS89-XXX to ETRS89-YYY following
870871
// recommendations of IOGP 373-07-7 to use ETRF2000 hub
@@ -877,7 +878,7 @@ struct PrecomputedOpCharacteristics {
877878
double area, bool isPROJExportable,
878879
bool hasGrids, bool gridsAvailable,
879880
bool gridsKnown, size_t stepCount,
880-
size_t projStepCount)
881+
size_t projStepCount, bool hasXYZGridshift)
881882
: area_(area), accuracy_(getAccuracy(op)),
882883
isPROJExportable_(isPROJExportable), hasGrids_(hasGrids),
883884
gridsAvailable_(gridsAvailable), gridsKnown_(gridsKnown),
@@ -887,6 +888,7 @@ struct PrecomputedOpCharacteristics {
887888
op->nameStr().find(BALLPARK_VERTICAL_TRANSFORMATION) !=
888889
std::string::npos),
889890
isNullTransformation_(isNullTransformation(op->nameStr())),
891+
hasXYZGridshift_(hasXYZGridshift),
890892
is_ETRS89_XXX_to_ETRS89_YYY_(
891893
starts_with(op->sourceCRS()->nameStr().c_str(), "ETRS89-") &&
892894
starts_with(op->targetCRS()->nameStr().c_str(), "ETRS89-")),
@@ -1022,6 +1024,13 @@ struct SortFunction {
10221024
}
10231025
}
10241026

1027+
if (iterA->second.hasXYZGridshift_ && !iterB->second.hasXYZGridshift_) {
1028+
return true;
1029+
}
1030+
if (!iterA->second.hasXYZGridshift_ && iterB->second.hasXYZGridshift_) {
1031+
return false;
1032+
}
1033+
10251034
// Follow recommendations of IOGP 373-07-7 to use ETRF2000 hub if
10261035
// no direct Transformation
10271036
if (iterA->second.is_ETRS89_XXX_to_ETRS89_YYY_ &&
@@ -1485,6 +1494,7 @@ struct FilterResults {
14851494
bool isPROJExportable = false;
14861495
auto formatter = io::PROJStringFormatter::create();
14871496
size_t projStepCount = 0;
1497+
bool hasXYZGridshift = false;
14881498
try {
14891499
const auto str = op->exportToPROJString(formatter.get());
14901500
// Grids might be missing, but at least this is something
@@ -1497,6 +1507,8 @@ struct FilterResults {
14971507
auto formatter2 = io::PROJStringFormatter::create();
14981508
formatter2->ingestPROJString(str);
14991509
projStepCount = formatter2->getStepCount();
1510+
} else {
1511+
hasXYZGridshift = true;
15001512
}
15011513
} catch (const std::exception &) {
15021514
}
@@ -1519,11 +1531,12 @@ struct FilterResults {
15191531
<< " ";
15201532
std::cerr << "isNull=" << isNullTransformation(op->nameStr())
15211533
<< " ";
1534+
std::cerr << "hasXYZGridshift=" << hasXYZGridshift << " ";
15221535
std::cerr << std::endl;
15231536
#endif
15241537
map[op.get()] = PrecomputedOpCharacteristics(
15251538
op, area, isPROJExportable, hasGrids, gridsAvailable,
1526-
gridsKnown, stepCount, projStepCount);
1539+
gridsKnown, stepCount, projStepCount, hasXYZGridshift);
15271540
}
15281541

15291542
// Sort !
@@ -4313,8 +4326,6 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase(
43134326
// We don't want to "improve" the result set for those transformations
43144327
// where heuristics have been painfully tuned over the years to give
43154328
// expected results...
4316-
!(sourceCRS->nameStr() == "NTF" && targetCRS->nameStr() == "ETRS89") &&
4317-
!(sourceCRS->nameStr() == "ETRS89" && targetCRS->nameStr() == "NTF") &&
43184329
!((sourceCRS->nameStr() == "GDA94" ||
43194330
sourceCRS->nameStr() == "GDA2020") &&
43204331
targetCRS->nameStr() == "WGS 84") &&
@@ -4409,6 +4420,15 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase(
44094420
for (const auto &op : ops) {
44104421
if (!op->hasBallparkTransformation()) {
44114422
auto newOp = op->shallowClone();
4423+
auto interpolationCRS =
4424+
newOp->interpolationCRS();
4425+
if (interpolationCRS &&
4426+
interpolationCRS->_isEquivalentTo(
4427+
srcDatumGeogCRS.get(),
4428+
util::IComparable::Criterion::
4429+
EQUIVALENT)) {
4430+
newOp->setInterpolationCRS(sourceCRS);
4431+
}
44124432
setCRSs(newOp.get(), sourceCRS, targetCRS);
44134433
res.push_back(newOp);
44144434
}
@@ -4479,6 +4499,15 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase(
44794499
for (const auto &op : ops) {
44804500
if (!op->hasBallparkTransformation()) {
44814501
auto newOp = op->shallowClone();
4502+
auto interpolationCRS =
4503+
newOp->interpolationCRS();
4504+
if (interpolationCRS &&
4505+
interpolationCRS->_isEquivalentTo(
4506+
dstDatumGeogCRS.get(),
4507+
util::IComparable::Criterion::
4508+
EQUIVALENT)) {
4509+
newOp->setInterpolationCRS(targetCRS);
4510+
}
44824511
setCRSs(newOp.get(), sourceCRS, targetCRS);
44834512
res.push_back(newOp);
44844513
}
@@ -4508,6 +4537,8 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase(
45084537
}
45094538
}
45104539
}
4540+
4541+
doFilterAndCheckPerfectOp = !res.empty();
45114542
}
45124543

45134544
if (doFilterAndCheckPerfectOp) {

test/unit/test_operationfactory.cpp

Lines changed: 131 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -284,25 +284,52 @@ TEST(operation, geogCRS_to_geogCRS_context_inverse_needed) {
284284
authFactory->createCoordinateReferenceSystem("4275"), // NTF
285285
authFactory->createCoordinateReferenceSystem("4258"), // ETRS89
286286
ctxt);
287-
ASSERT_EQ(list.size(), 2U);
288-
EXPECT_EQ(
289-
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
290-
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
291-
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 "
292-
"+step +proj=cart +ellps=clrk80ign +step +proj=helmert +x=-168 "
293-
"+y=-60 +z=320 +step +inv +proj=cart +ellps=GRS80 +step +proj=pop "
294-
"+v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step "
295-
"+proj=axisswap +order=2,1");
287+
ASSERT_EQ(list.size(), 3U);
288+
289+
EXPECT_EQ(list[0]->exportToPROJString(
290+
PROJStringFormatter::create(
291+
PROJStringFormatter::Convention::PROJ_5,
292+
authFactory->databaseContext())
293+
.get()),
294+
"+proj=pipeline "
295+
"+step +proj=axisswap +order=2,1 "
296+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
297+
"+step +proj=push +v_3 "
298+
"+step +proj=cart +ellps=clrk80ign "
299+
"+step +proj=helmert +x=-168 +y=-60 +z=320 "
300+
"+step +inv +proj=cart +ellps=GRS80 "
301+
"+step +proj=pop +v_3 "
302+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
303+
"+step +proj=axisswap +order=2,1");
304+
296305
EXPECT_EQ(list[1]->exportToPROJString(
297306
PROJStringFormatter::create(
298307
PROJStringFormatter::Convention::PROJ_5,
299308
authFactory->databaseContext())
300309
.get()),
301-
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
302-
"+proj=unitconvert +xy_in=deg +xy_out=rad +step "
303-
"+proj=hgridshift +grids=fr_ign_ntf_r93.tif +step "
304-
"+proj=unitconvert "
305-
"+xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1");
310+
"+proj=pipeline "
311+
"+step +proj=axisswap +order=2,1 "
312+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
313+
"+step +proj=push +v_3 "
314+
"+step +proj=cart +ellps=clrk80ign "
315+
"+step +proj=xyzgridshift +grids=fr_ign_gr3df97a.tif "
316+
"+grid_ref=output_crs +ellps=GRS80 "
317+
"+step +inv +proj=cart +ellps=GRS80 "
318+
"+step +proj=pop +v_3 "
319+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
320+
"+step +proj=axisswap +order=2,1");
321+
322+
EXPECT_EQ(list[2]->exportToPROJString(
323+
PROJStringFormatter::create(
324+
PROJStringFormatter::Convention::PROJ_5,
325+
authFactory->databaseContext())
326+
.get()),
327+
"+proj=pipeline "
328+
"+step +proj=axisswap +order=2,1 "
329+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
330+
"+step +proj=hgridshift +grids=fr_ign_ntf_r93.tif "
331+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
332+
"+step +proj=axisswap +order=2,1");
306333
}
307334
{
308335
auto ctxt =
@@ -314,14 +341,51 @@ TEST(operation, geogCRS_to_geogCRS_context_inverse_needed) {
314341
authFactory->createCoordinateReferenceSystem("4275"), // NTF
315342
authFactory->createCoordinateReferenceSystem("4258"), // ETRS89
316343
ctxt);
317-
ASSERT_EQ(list.size(), 2U);
318-
EXPECT_EQ(
319-
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
320-
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
321-
"+proj=unitconvert +xy_in=deg +xy_out=rad +step "
322-
"+proj=hgridshift +grids=fr_ign_ntf_r93.tif +step "
323-
"+proj=unitconvert "
324-
"+xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1");
344+
ASSERT_EQ(list.size(), 3U);
345+
EXPECT_EQ(list[0]->exportToPROJString(
346+
PROJStringFormatter::create(
347+
PROJStringFormatter::Convention::PROJ_5,
348+
authFactory->databaseContext())
349+
.get()),
350+
"+proj=pipeline "
351+
"+step +proj=axisswap +order=2,1 "
352+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
353+
"+step +proj=push +v_3 "
354+
"+step +proj=cart +ellps=clrk80ign "
355+
"+step +proj=xyzgridshift +grids=fr_ign_gr3df97a.tif "
356+
"+grid_ref=output_crs +ellps=GRS80 "
357+
"+step +inv +proj=cart +ellps=GRS80 "
358+
"+step +proj=pop +v_3 "
359+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
360+
"+step +proj=axisswap +order=2,1");
361+
362+
EXPECT_EQ(list[1]->exportToPROJString(
363+
PROJStringFormatter::create(
364+
PROJStringFormatter::Convention::PROJ_5,
365+
authFactory->databaseContext())
366+
.get()),
367+
"+proj=pipeline "
368+
"+step +proj=axisswap +order=2,1 "
369+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
370+
"+step +proj=hgridshift +grids=fr_ign_ntf_r93.tif "
371+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
372+
"+step +proj=axisswap +order=2,1");
373+
374+
EXPECT_EQ(list[2]->exportToPROJString(
375+
PROJStringFormatter::create(
376+
PROJStringFormatter::Convention::PROJ_5,
377+
authFactory->databaseContext())
378+
.get()),
379+
"+proj=pipeline "
380+
"+step +proj=axisswap +order=2,1 "
381+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
382+
"+step +proj=push +v_3 "
383+
"+step +proj=cart +ellps=clrk80ign "
384+
"+step +proj=helmert +x=-168 +y=-60 +z=320 "
385+
"+step +inv +proj=cart +ellps=GRS80 "
386+
"+step +proj=pop +v_3 "
387+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
388+
"+step +proj=axisswap +order=2,1");
325389
}
326390
{
327391
auto ctxt =
@@ -333,14 +397,51 @@ TEST(operation, geogCRS_to_geogCRS_context_inverse_needed) {
333397
authFactory->createCoordinateReferenceSystem("4258"), // ETRS89
334398
authFactory->createCoordinateReferenceSystem("4275"), // NTF
335399
ctxt);
336-
ASSERT_EQ(list.size(), 2U);
337-
EXPECT_EQ(
338-
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
339-
"+proj=pipeline +step +proj=axisswap +order=2,1 +step "
340-
"+proj=unitconvert +xy_in=deg +xy_out=rad +step +inv "
341-
"+proj=hgridshift +grids=fr_ign_ntf_r93.tif +step "
342-
"+proj=unitconvert "
343-
"+xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1");
400+
ASSERT_EQ(list.size(), 3U);
401+
EXPECT_EQ(list[0]->exportToPROJString(
402+
PROJStringFormatter::create(
403+
PROJStringFormatter::Convention::PROJ_5,
404+
authFactory->databaseContext())
405+
.get()),
406+
"+proj=pipeline "
407+
"+step +proj=axisswap +order=2,1 "
408+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
409+
"+step +proj=push +v_3 "
410+
"+step +proj=cart +ellps=GRS80 "
411+
"+step +inv +proj=xyzgridshift +grids=fr_ign_gr3df97a.tif "
412+
"+grid_ref=output_crs +ellps=GRS80 "
413+
"+step +inv +proj=cart +ellps=clrk80ign "
414+
"+step +proj=pop +v_3 "
415+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
416+
"+step +proj=axisswap +order=2,1");
417+
418+
EXPECT_EQ(list[1]->exportToPROJString(
419+
PROJStringFormatter::create(
420+
PROJStringFormatter::Convention::PROJ_5,
421+
authFactory->databaseContext())
422+
.get()),
423+
"+proj=pipeline "
424+
"+step +proj=axisswap +order=2,1 "
425+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
426+
"+step +inv +proj=hgridshift +grids=fr_ign_ntf_r93.tif "
427+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
428+
"+step +proj=axisswap +order=2,1");
429+
430+
EXPECT_EQ(list[2]->exportToPROJString(
431+
PROJStringFormatter::create(
432+
PROJStringFormatter::Convention::PROJ_5,
433+
authFactory->databaseContext())
434+
.get()),
435+
"+proj=pipeline "
436+
"+step +proj=axisswap +order=2,1 "
437+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
438+
"+step +proj=push +v_3 "
439+
"+step +proj=cart +ellps=GRS80 "
440+
"+step +proj=helmert +x=168 +y=60 +z=-320 "
441+
"+step +inv +proj=cart +ellps=clrk80ign "
442+
"+step +proj=pop +v_3 "
443+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
444+
"+step +proj=axisswap +order=2,1");
344445
}
345446
}
346447

0 commit comments

Comments
 (0)