/* * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES) * * This file is part of Orfeo Toolbox * * https://www.orfeo-toolbox.org/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef otbOGRFeatureWrapper_h #define otbOGRFeatureWrapper_h // #include // std::ostream& #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #include #pragma GCC diagnostic pop #else #include #endif // #include "itkIndent.h", included from field #include "otbOGRFieldWrapper.h" #include "otbOGRGeometryWrapper.h" class OGRFeature; class OGRFeatureDefn; namespace otb { namespace ogr { class Feature; OTBGdalAdapters_EXPORT bool operator==(Feature const& lhs, Feature const& rhs); /**\ingroup gGeometry * \class Feature proxy class. * \brief Geometric objet with descriptive fields. * * It provides an encapsulation of OGR classes. In that particular case, it's an * encapsulation of \c OGRFeature. * * \note This class is a proxy class on top of an \c OGRLayer. * \note It can be copied, and assigned. New instances will share the underlying * \c OGRLayer: \c Feature assignment will just make one \c Feature proxy point * to another \c OGRFeature. In order to truly assign from one to another, use * \c SetFrom, or \c Clone in order to duplicate the current feature. * \note The default constructor is disabled on purpose. * \note The destructor automatically generated does everything that is * expected. * \invariant m_Feature != 0 Actually, this isn't a true invariant per * se, as it may be null in some cases, for instance to define mark the \c * Layer::end() iterator. * \since OTB v 3.14.0 * * \ingroup OTBGdalAdapters */ class OTBGdalAdapters_EXPORT Feature { public: /**\name Construction, copy and destruction */ //@{ /** * Construction from a definition. * \param[in] definition definition of the fields of the feature. * \throw None * * \post m_Feature != 0 * \post \c definition internal reference count is incremented * \warning DO NOT destroy the definition while it is relied upon by features. * \internal The OGR feature is created with the ad'hoc function from OGR API. * \sa \c OGRFeature::CreateFeature() * \todo See whether wrapping \c OGRFeatureDefn makes sense */ Feature(OGRFeatureDefn& definition); /** * Construction from a pre-existing \c OGRFeature. * \param[in,out] feature pre-existing feature that will be owned by the * wrapper. * \throw None * \pre The feature is expected to have been built with OGR API. * \internal * As all functions form \c OGRLayer returns features that are meant to be be * of the responsibility of the client code, this constructor is perfect. It * has been used in \c Layer interface to return features. */ Feature(OGRFeature* feature); /** * Destructor. * \throw None * \internal The OGR feature is released with the ad'hoc function from OGR API. * \sa \c OGRFeature::DestroyFeature() */ ~Feature(); /** * Duplicates the current feature. * \return a duplicita of \c *this. * \throw None * \invariant m_Feature != 0 * * As \c Feature is a proxy class that shares its underlying \c OGRFeature, * this function represents the only way to duplicate a feature. * \sa \c OGRFeature::Clone() */ Feature Clone() const; /** * Assigns a pre-existing feature to the current one. * \param[in] rhs pre-existing feature to assign ourseleves from. * \param[in] map integer list of the fields to duplicated (default: all) * \param[in] mustForgive tells whether the operation should continue despite * lacking output fields matching some of the source fields. * * \throw itk::ExceptionObject if no value is transferred * \sa \c OGRFeature::SetFrom() */ void SetFrom(Feature const& rhs, int* map, bool mustForgive = true); /** \copydoc Feature::SetFrom(Feature const&, int *, bool mustForgive); */ void SetFrom(Feature const& rhs, bool mustForgive = true); //@} /** Prints self into stream. */ void PrintSelf(std::ostream& os, itk::Indent indent) const; /** Access to raw \c OGRFeature. * This function provides an abstraction leak in case deeper control on the * underlying \c OGRFeature is required. * \invariant The underlying \c OGRFeature must be valid, i.e. * m_DataSource != 0, an assertion is fired otherwise. * \warning You must under no circumstance try to delete the \c OGRFeature * obtained this way. */ OGRFeature& ogr() const; /** \copydoc Feature::ogr() const */ OGRFeature& ogr(); /** Abstraction leak to the internal shared \c OGRFeature. * \throw None * \internal * This function is meant to link a \c Field to the \c OGRFeature where it is * stored, without introducing a cyclic dependency, nor deporting the fields * R/W to \c Feature interface. */ boost::shared_ptr& sptr() { return m_Feature; } /** \copydoc Feature::sptr() */ boost::shared_ptr const& sptr() const { return m_Feature; } /** * Obtains feature ID.. * \return its ID, or \c OGRNullFID if none has been assigned. * \throw None * \invariant m_Feature != 0 * \sa \c OGRFeature::GetFID() */ long GetFID() const; /** * %Feature ID setter. * \param[in] fid new id. * \throw itk::ExceptionObject if it cannot be set. * \invariant m_Feature != 0 * \sa \c OGRFeature::SetFID() */ void SetFID(long fid); /** * %Feature definition accessor. * \return a reference to the internal definition. * \throw None * \invariant m_Feature != 0 * \sa \c OGRFeature::GetDefnRef() */ OGRFeatureDefn& GetDefn() const; /**\name Fields * Fields access. * Unlike original OGR API, the access to the fields of a feature is done * directly from the \c Field interface, and not the \c Feature interface. * * Ones first need to iterate on the fields of a feature, and then use the * appropriate setter/getter to access to each field. */ //@{ /** * Returns the number of fields. * \invariant m_Feature != 0 * \sa \c OGRFeature::GetFieldCount() */ int GetSize() const; /** * Read-Write access to the i-th field. * \invariant m_Feature != 0 * \pre index < GetSize() * \throw None */ Field operator[](int index); /** * Read-only access to the i-th field. * \invariant m_Feature != 0 * \pre index < GetSize() * \throw None */ Field const operator[](int index) const; /** * Read-Write access to a field by name. * \invariant m_Feature != 0 * \throw itk::ExceptionObject if no field named \c name exists. */ Field operator[](std::string const& name); /** * Read-Only access to a field by name. * \invariant m_Feature != 0 * \throw itk::ExceptionObject if no field named \c name exists. */ Field const operator[](std::string const& name) const; /** Accessor to the definition of the i-th field. * \invariant m_Feature != 0 * \pre index < GetSize() * \throw None * \sa \c OGRFeature::GetFieldDefnRef() */ FieldDefn GetFieldDefn(int index) const; /** Accessor to the definition of a field gven its name. * \invariant m_Feature != 0 * \throw itk::ExceptionObject if no field named \c name exists. * \sa \c OGRFeature::GetFieldDefnRef() */ FieldDefn GetFieldDefn(std::string const& name) const; //@} /**\name Geometries * \todo We should detect whether the official C++11 \c std::unique_ptr<> is * available instead of always using boost.interprocess.unique_ptr<>. * \internal * \c OGRGeometry pointers are used and not references are used because the * current geometry can be unset. */ //@{ /** * Changes the current geometry. * \param[in] geometry Pointer to an existing geometry, null to dismiss any * geometry. * \post The input \c OGRGeometry is copied (cloned actually). * \throw itk::ExceptionObject on failure. * \invariant m_Feature != 0 * \sa \c OGRFeature::SetGeometry() */ void SetGeometry(OGRGeometry const* geometry); /** * Accessor to the internal \c OGRGeometry stored. * * \return The result may be null if no geometry is associated to the feature. * \return In any case the result shall not be modified. * \throw None * \invariant m_Feature != 0 * \sa \c OGRFeature::GetGeometryRef() */ OGRGeometry const* GetGeometry() const; /** * Changes the current geometry (transfers ownership). * \param[in] geometry Unique-pointer to an existing geometry, null to * dismiss any geometry. * \post Ownership of the input \c OGRGeometry is given to the feature. * \post GetGeometry() == initial_geometry * \post The user is no longer responsible of the input geometry, even on * failure of the operation. In that case, the geometry would have been * definitivelly destroyed with the ad'hoc function (\c * OGRGeometryFactory::destroyGeometry()). * \throw itk::ExceptionObject on failure. * \invariant m_Feature != 0 * \sa \c OGRFeature::SetGeometryDirectly() */ void SetGeometryDirectly(UniqueGeometryPtr geometry); /** * Steals the geometry stored.. * * \return A unique-pointer to a \c OGRGeometry that is now of the * responsibility of the caller. * \post GetGeometry() == 0 * \throw None * \invariant m_Feature != 0 * \sa \c OGRFeature::StealGeometry() * \internal * The \c UniqueGeometryPtr RAII wrapper will know how to correctly destroy * the \c OGRGeometry instance. */ UniqueGeometryPtr StealGeometry(); //@} /** * Tells whether two features are equal. * \return whether both are null or equal. * \throw None * \sa \c OGRFeature::Equals() * \internal * Used to determine when two \c Layer::iterator (\c Layer::feature_iter) are * equal. */ friend bool otb::ogr::operator==(Feature const& lhs, Feature const& rhs); OGRFeature const* addr() const { return m_Feature.get(); } private: /**\name Unchecked definitions * All the definitions that follow do the real work. However, they are not the * exposed public functions. The design of this class follows the principle * behind the NVI (Non-Virtual Interface) pattern: * - The public functions are inlined and check invariants and preconditions, * - While the private functions do the work. */ //@{ Feature UncheckedClone() const; void UncheckedSetFrom(Feature const& rhs, int* map, bool mustForgive = true); void UncheckedSetFrom(Feature const& rhs, bool mustForgive = true); void UncheckedPrintSelf(std::ostream& os, itk::Indent indent) const; Field UncheckedGetElement(int index); Field UncheckedGetElement(std::string const& name); FieldDefn UncheckedGetFieldDefn(int index) const; FieldDefn UncheckedGetFieldDefn(std::string const& name) const; int UncheckedGetFieldIndex(std::string const& name) const; long UncheckedGetFID() const; void UncheckedSetFID(long fid); OGRFeatureDefn& UncheckedGetDefn() const; void UncheckedSetGeometryDirectly(UniqueGeometryPtr geometry); UniqueGeometryPtr UncheckedStealGeometry(); OGRGeometry const* UncheckedGetGeometry() const; void UncheckedSetGeometry(OGRGeometry const* geometry); //@} /** Searches the index of a field given a name. * \invariant m_Feature != 0 * \throw itk::ExceptionObject if no field named \c name exists. */ int GetFieldIndex(std::string const& name) const; /** * Checks whether the internal \c OGRFeature is non null. * Fires an assertion otherwise. * \internal * Used by all the functions of \c Feature. As the definition of this function * is inlined, \c assert() actual behaviour will be conditionned by the * compilation mode (\em debug or \em release; or more exactly on \c NDEBUG * precompiler directive). */ void CheckInvariants() const; /** Internal pointer to the shared \c OGRFeature. */ boost::shared_ptr m_Feature; }; } // ogr namespace } // otb namespace #ifndef OTB_MANUAL_INSTANTIATION #include "otbOGRFeatureWrapper.hxx" #endif #endif // otbOGRFeatureWrapper_h