From 7c4c0b655d0cae3fa1f4c4f288d13e61fffbd239 Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@c-s.fr>
Date: Wed, 25 Apr 2012 17:21:18 +0200
Subject: [PATCH] ENH: OTB-134/OGR: geometry helpers

---
 .../OGRAdapters/otbOGRFeatureWrapper.cxx      |   2 +-
 .../OGRAdapters/otbOGRFeatureWrapper.h        |   9 +-
 .../OGRAdapters/otbOGRGeometryWrapper.cxx     | 110 ++++++++++++++++++
 .../OGRAdapters/otbOGRGeometryWrapper.h       |  88 ++++++++++++++
 .../OGRAdapters/otbOGRLayerWrapper.cxx        |  27 +++++
 .../OGRAdapters/otbOGRLayerWrapper.h          |  20 +++-
 6 files changed, 244 insertions(+), 12 deletions(-)
 create mode 100644 Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.cxx
 create mode 100644 Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.h

diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx
index 2077dedaa5..a5da28e9bc 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.cxx
@@ -190,7 +190,7 @@ void otb::ogr::Feature::SetGeometryDirectly(UniqueGeometryPtr geometry)
   assert(! geometry);
 }
 
-otb::ogr::Feature::UniqueGeometryPtr otb::ogr::Feature::StealGeometry()
+otb::ogr::UniqueGeometryPtr otb::ogr::Feature::StealGeometry()
 {
   CheckInvariants();
   OGRGeometry * g = m_Feature->StealGeometry();
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h
index 0321c799f6..2ac36ef9e1 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRFeatureWrapper.h
@@ -21,12 +21,11 @@
 // #include <iosfwd> // std::ostream&
 #include <cassert>
 #include <boost/shared_ptr.hpp>
-#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
 #include "itkIndent.h"
 #include "otbOGRFieldWrapper.h"
+#include "otbOGRGeometryWrapper.h"
 
 class OGRFeature;
-class OGRGeometry;
 class OGRFeatureDefn;
 
 namespace otb {
@@ -90,12 +89,6 @@ public:
   void SetGeometry(OGRGeometry const* geometry); // not a ref because it may be null
   OGRGeometry const* GetGeometry() const; // not a ref because it may be null
 
-  struct JustDelete {
-    template <typename T>
-    void operator()(T* p) {delete p; }
-  };
-  typedef boost::interprocess::unique_ptr<OGRGeometry, JustDelete> UniqueGeometryPtr;
-
   void SetGeometryDirectly(UniqueGeometryPtr geometry);
   UniqueGeometryPtr StealGeometry();
 
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.cxx
new file mode 100644
index 0000000000..a15587b6ee
--- /dev/null
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.cxx
@@ -0,0 +1,110 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+/*===========================================================================*/
+/*===============================[ Includes ]================================*/
+/*===========================================================================*/
+#include "otbOGRGeometryWrapper.h"
+#include "ogr_geometry.h"
+
+/*===========================================================================*/
+/*================================[ Deleter ]================================*/
+/*===========================================================================*/
+void otb::ogr::internal::GeometryDeleter::operator()(OGRGeometry* p)
+{
+  OGRGeometryFactory::destroyGeometry (p);
+}
+
+/*===========================================================================*/
+/*======================[ Double dispatched functions ]======================*/
+/*===========================================================================*/
+bool otb::ogr::Intersects(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  // OGRGeometry::Intersects is not const-correct ...
+  return lhs.Intersects(const_cast <OGRGeometry*>(&rhs));
+}
+
+bool otb::ogr::Equals(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  // OGRGeometry::Equals is not const-correct ...
+  return lhs.Equals(const_cast <OGRGeometry*>(&rhs));
+}
+
+bool otb::ogr::Disjoint(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Disjoint(&rhs);
+}
+
+bool otb::ogr::Touches(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Touches(&rhs);
+}
+
+bool otb::ogr::Crosses(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Crosses(&rhs);
+}
+
+bool otb::ogr::Within(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Within(&rhs);
+}
+
+bool otb::ogr::Contains(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Contains(&rhs);
+}
+
+bool otb::ogr::Overlaps(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Overlaps(&rhs);
+}
+
+double otb::ogr::Distance(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return lhs.Distance(&rhs);
+}
+
+otb::ogr::UniqueGeometryPtr otb::ogr::Intersection(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return UniqueGeometryPtr(lhs.Intersection(&rhs));
+}
+
+otb::ogr::UniqueGeometryPtr otb::ogr::Union(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return UniqueGeometryPtr(lhs.Union(&rhs));
+}
+
+otb::ogr::UniqueGeometryPtr otb::ogr::UnionCascaded(OGRGeometry const& this_)
+{
+  return UniqueGeometryPtr(this_.UnionCascaded());
+}
+
+otb::ogr::UniqueGeometryPtr otb::ogr::Difference(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+  return UniqueGeometryPtr(lhs.Difference(&rhs));
+}
+
+otb::ogr::UniqueGeometryPtr otb::ogr::SymDifference(OGRGeometry const& lhs, OGRGeometry const& rhs)
+{
+#if GDAL_VERSION_NUM >= 1800
+  return UniqueGeometryPtr(lhs.SymDifference(&rhs));
+#else
+  return UniqueGeometryPtr(lhs.SymmetricDifference(&rhs));
+#endif
+}
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.h
new file mode 100644
index 0000000000..244976f30a
--- /dev/null
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRGeometryWrapper.h
@@ -0,0 +1,88 @@
+/*=========================================================================
+
+ Program: ORFEO Toolbox
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+
+ Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+ See OTBCopyright.txt for details.
+
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbOGRGeometryWrapper_h
+#define __otbOGRGeometryWrapper_h
+
+#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
+class OGRGeometry;
+
+namespace otb { namespace ogr {
+namespace internal {
+struct GeometryDeleter
+  {
+  void operator()(OGRGeometry* p);
+  };
+} // metaprog namespace
+
+
+// we don't encapsulate OGRGeometry, but please, don't create new geometries with a new.
+
+/**\ingroup Geometry
+ * \defgroup OGRGeometryWrapper OGRGeometry Wrappers
+ * Helper definition to hangle \c OGRGeometry objects.
+ *
+ * @note %OTB doesn't provide anything on top of \c OGRGeometryFactory to create
+ * new factories. Please, never create new \c OGRGeometry by hand with
+ * <tt>new</tt> operator as there is no garanty they'll get destroyed within the
+ * proper memory context when released from an owning \c OGRFeature.
+ *
+ * Thus, always use \c OGRGeometryFactory functions to create new geometries.
+ * You can then manage their lifetime manually or rely on \c UniqueGeometryPtr
+ * that provides a non-copyable, but movable RAII wrapper around \c OGRGeometry.
+ * @{
+ */
+typedef boost::interprocess::unique_ptr<OGRGeometry, internal::GeometryDeleter> UniqueGeometryPtr;
+///Do these features intersect?
+bool Intersects (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Returns wheither if two geometries are equivalent.
+bool Equals (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Tests for disjointness.
+bool Disjoint (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Tests for touching.
+bool Touches (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Tests for crossing.
+bool Crosses (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Tests for containment.
+bool Within (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Tests for containment.
+bool Contains (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Tests for overlap.
+bool Overlaps (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Computes distance between two geometries.
+double Distance (OGRGeometry const& lhs, OGRGeometry const& rhs);
+
+/// Computes intersection.
+UniqueGeometryPtr Intersection (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Computes union.
+UniqueGeometryPtr Union (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Computes union using cascading.
+UniqueGeometryPtr UnionCascaded (OGRGeometry const& this_);
+/// Computes difference.
+UniqueGeometryPtr Difference (OGRGeometry const& lhs, OGRGeometry const& rhs);
+/// Computes symmetric difference.
+UniqueGeometryPtr SymDifference (OGRGeometry const& lhs, OGRGeometry const& rhs); // -1.8
+
+/** @} */
+
+} } // end namespace otb::ogr
+
+#ifndef OTB_MANUAL_INSTANTIATION
+// #include "otbOGRGeometryWrapper.txx"
+#endif
+
+#endif // __otbOGRGeometryWrapper_h
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
index 92434357fc..ab798e9f66 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.cxx
@@ -83,6 +83,20 @@ otb::ogr::Layer::const_iterator otb::ogr::Layer::cbegin() const
   return const_iterator(*const_cast <Layer*>(this));
 }
 
+otb::ogr::Layer::iterator otb::ogr::Layer::start(size_t index)
+{
+  assert(m_Layer && "OGRLayer not initialized");
+  m_Layer->SetNextByIndex(index);
+  return iterator(*this);
+}
+
+otb::ogr::Layer::const_iterator otb::ogr::Layer::cstart(size_t index) const
+{
+  assert(m_Layer && "OGRLayer not initialized");
+  m_Layer->SetNextByIndex(index);
+  return const_iterator(*const_cast <Layer*>(this));
+}
+
 void otb::ogr::Layer::CreateFeature(Feature feature)
 {
   assert(m_Layer && "OGRLayer not initialized");
@@ -163,6 +177,19 @@ void otb::ogr::Layer::SetSpatialFilter(OGRGeometry const* spatialFilter)
   m_Layer->SetSpatialFilter(const_cast <OGRGeometry*>(spatialFilter));
 }
 
+void otb::ogr::Layer::SetSpatialFilterRect(
+  double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+{
+  assert(m_Layer && "OGRLayer not initialized");
+  m_Layer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
+}
+
+OGRSpatialReference const* otb::ogr::Layer::GetSpatialRef() const
+{
+  assert(m_Layer && "OGRLayer not initialized");
+  return m_Layer->GetSpatialRef();
+}
+
 /*===========================================================================*/
 /*==========================[ Feature Definition ]===========================*/
 /*===========================================================================*/
diff --git a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h
index 235fda9970..f3e6f91917 100644
--- a/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h
+++ b/Code/UtilitiesAdapters/OGRAdapters/otbOGRLayerWrapper.h
@@ -126,13 +126,23 @@ public:
   OGRLayer & ogr();
 
   /**\name Spatial filter property
-   * \internal the I/O geometry is an undeletable pointer, can be may be null.
+   * \internal the I/O geometry is an undeletable pointer, that may be null.
    * \todo we'll see later if a Geometry capsule is defined, or a
    * \c nondeletable<> pointer type.
    */
   //@{
-  OGRGeometry const* GetSpatialFilter() const;
-  void SetSpatialFilter(OGRGeometry const* spatialFilter);
+  OGRGeometry const* GetSpatialFilter() const; // not a ref because it may be null
+  void SetSpatialFilter(OGRGeometry const* spatialFilter); // not a ref because it may be null
+  /// Sets a new rectangular spatial filter.
+  void SetSpatialFilterRect(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
+  //@}
+
+  /**\name Spatial Reference property
+   * \internal the I/O spatial reference is an undeletable pointer, that may be null.
+   * \note read-only property
+   */
+  //@{
+  OGRSpatialReference const* GetSpatialRef() const;
   //@}
 
   /**\name Iteration */
@@ -193,6 +203,10 @@ public:
   const_iterator cend  () const { return iterator(); }
   iterator       begin ();
   iterator       end   () { return iterator(); }
+
+  const_iterator start (size_t index) const { return cstart(index); }
+  const_iterator cstart(size_t index) const;
+  iterator       start (size_t index);
   //@}
 
   /**\name Features definition */
-- 
GitLab