From 1ce2cc80a4a0ff248cda778ae16de51946fa61b7 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 24 Feb 2020 15:40:25 +0100 Subject: CompoundCRS::create(): reject combinations of components not allowed by ISO 19111 --- src/iso19111/crs.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'src') diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 67b0bb00..dbb68f0b 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -3914,6 +3914,28 @@ ProjectedCRS::_identify(const io::AuthorityFactoryPtr &authorityFactory) const { // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress +InvalidCompoundCRSException::InvalidCompoundCRSException(const char *message) + : Exception(message) {} + +// --------------------------------------------------------------------------- + +InvalidCompoundCRSException::InvalidCompoundCRSException( + const std::string &message) + : Exception(message) {} + +// --------------------------------------------------------------------------- + +InvalidCompoundCRSException::~InvalidCompoundCRSException() = default; + +// --------------------------------------------------------------------------- + +InvalidCompoundCRSException::InvalidCompoundCRSException( + const InvalidCompoundCRSException &) = default; +//! @endcond + +// --------------------------------------------------------------------------- + //! @cond Doxygen_Suppress struct CompoundCRS::Private { std::vector components_{}; @@ -3965,9 +3987,67 @@ CompoundCRS::componentReferenceSystems() PROJ_PURE_DEFN { * At minimum the name should be defined. * @param components the component CRS of the CompoundCRS. * @return new CompoundCRS. + * @throw InvalidCompoundCRSException */ CompoundCRSNNPtr CompoundCRS::create(const util::PropertyMap &properties, const std::vector &components) { + + if (components.size() < 2) { + throw InvalidCompoundCRSException( + "compound CRS should have at least 2 components"); + } + + auto comp0 = components[0].get(); + auto comp0Bound = dynamic_cast(comp0); + if (comp0Bound) { + comp0 = comp0Bound->baseCRS().get(); + } + auto comp0Geog = dynamic_cast(comp0); + auto comp0Proj = dynamic_cast(comp0); + auto comp0Eng = dynamic_cast(comp0); + + auto comp1 = components[1].get(); + auto comp1Bound = dynamic_cast(comp1); + if (comp1Bound) { + comp1 = comp1Bound->baseCRS().get(); + } + auto comp1Vert = dynamic_cast(comp1); + auto comp1Eng = dynamic_cast(comp1); + // Loose validation based on + // http://docs.opengeospatial.org/as/18-005r4/18-005r4.html#34 + bool ok = false; + if ((comp0Geog && comp0Geog->coordinateSystem()->axisList().size() == 2 && + (comp1Vert || + (comp1Eng && + comp1Eng->coordinateSystem()->axisList().size() == 1))) || + (comp0Proj && comp0Proj->coordinateSystem()->axisList().size() == 2 && + (comp1Vert || + (comp1Eng && + comp1Eng->coordinateSystem()->axisList().size() == 1))) || + (comp0Eng && comp0Eng->coordinateSystem()->axisList().size() <= 2 && + comp1Vert)) { + // Spatial compound coordinate reference system + ok = true; + } else { + bool isComp0Spatial = comp0Geog || comp0Proj || comp0Eng || + dynamic_cast(comp0) || + dynamic_cast(comp0); + if (isComp0Spatial && dynamic_cast(comp1)) { + // Spatio-temporal compound coordinate reference system + ok = true; + } else if (isComp0Spatial && + dynamic_cast(comp1)) { + // Spatio-parametric compound coordinate reference system + ok = true; + } + } + if (!ok) { + throw InvalidCompoundCRSException( + "components of the compound CRS do not belong to one of the " + "allowed combinations of " + "http://docs.opengeospatial.org/as/18-005r4/18-005r4.html#34"); + } + auto compoundCRS(CompoundCRS::nn_make_shared(components)); compoundCRS->assignSelf(compoundCRS); compoundCRS->setProperties(properties); -- cgit v1.2.3