From cc68302d514f08c5aee0b3829f6e2746ffbb0158 Mon Sep 17 00:00:00 2001
From: Mansard <nmansard@laas.fr>
Date: Tue, 6 Sep 2016 20:43:56 +0200
Subject: [PATCH] [C++] Geom: moved inner/outer objects from GeomModel to
 GeomData. Issue 281.4.

---
 src/algorithm/geometry.hxx | 38 ++++++++++++++++--------
 src/multibody/fcl.hpp      |  1 +
 src/multibody/geometry.hpp | 56 +++++++++++++++++-------------------
 src/multibody/geometry.hxx | 59 +++++++++++++++++++++++++++-----------
 4 files changed, 96 insertions(+), 58 deletions(-)

diff --git a/src/algorithm/geometry.hxx b/src/algorithm/geometry.hxx
index 83853400d..d4c6a3d45 100644
--- a/src/algorithm/geometry.hxx
+++ b/src/algorithm/geometry.hxx
@@ -206,21 +206,38 @@ namespace se3
           );
     }
 
-    /// 2. Update the inner/outer objects
-    typedef GeometryModel::GeomIndexList GeomIndexList;
+    /// 2. add the collision pairs between geomModel1 and geomModel2.
+    for (Index i = 0; i < nGeom1; ++i) {
+      for (Index j = 0; j < nGeom2; ++j) {
+        geomModel1.collisionPairs.push_back(CollisionPair(i, nGeom1 + j));
+      }
+    }
+  }
+
+  inline void appendGeometryModel(GeometryModel & geomModel1,
+                                  GeometryData & geomData1,
+                                  const GeometryModel & geomModel2,
+                                  const GeometryData & geomData2)
+  {
+    /// 1&2. Call previous function.
+    appendGeometryModel(geomModel1,geomModel2);
+
+    /// 3. Update the inner/outer objects
+    Index nGeom1 = geomModel1.geometryObjects.size();
+    typedef GeometryData::GeomIndexList GeomIndexList;
     typedef std::map < JointIndex, GeomIndexList > Map_t;
-    BOOST_FOREACH(const Map_t::value_type& innerObject, geomModel2.innerObjects)
+    BOOST_FOREACH(const Map_t::value_type& innerObject, geomData2.innerObjects)
     {
-      GeomIndexList& innerGeoms = geomModel1.innerObjects[innerObject.first];
+      GeomIndexList& innerGeoms = geomData1.innerObjects[innerObject.first];
       innerGeoms.reserve(innerGeoms.size() + innerObject.second.size());
       BOOST_FOREACH(const GeomIndex& gid, innerObject.second)
       {
         innerGeoms.push_back(nGeom1 + gid);
       }
     }
-    BOOST_FOREACH(const Map_t::value_type& outerObject, geomModel2.outerObjects)
+    BOOST_FOREACH(const Map_t::value_type& outerObject, geomData2.outerObjects)
     {
-      GeomIndexList& outerGeoms = geomModel1.outerObjects[outerObject.first];
+      GeomIndexList& outerGeoms = geomData1.outerObjects[outerObject.first];
       outerGeoms.reserve(outerGeoms.size() + outerObject.second.size());
       BOOST_FOREACH(const GeomIndex& gid, outerObject.second)
       {
@@ -228,12 +245,9 @@ namespace se3
       }
     }
 
-    /// 3. add the collision pairs between geomModel1 and geomModel2.
-    for (Index i = 0; i < nGeom1; ++i) {
-      for (Index j = 0; j < nGeom2; ++j) {
-        geomModel1.collisionPairs.push_back(CollisionPair(i, nGeom1 + j));
-      }
-    }
+    // FIXME: I copy here the previous algo. Maybe it would be safer to simply use the
+    // fillInnerOuterObjectMaps() method (however marginally less efficient: is it important?).
+
   }
 } // namespace se3
 
diff --git a/src/multibody/fcl.hpp b/src/multibody/fcl.hpp
index 986286227..b564c5319 100644
--- a/src/multibody/fcl.hpp
+++ b/src/multibody/fcl.hpp
@@ -66,6 +66,7 @@ namespace se3
     friend std::ostream & operator << (std::ostream & os, const CollisionPair & X);
 
   }; // struct CollisionPair
+
   typedef std::vector<CollisionPair> CollisionPairsVector_t;
 
 #ifndef WITH_HPP_FCL  
diff --git a/src/multibody/geometry.hpp b/src/multibody/geometry.hpp
index ecd5816f4..49dacec98 100644
--- a/src/multibody/geometry.hpp
+++ b/src/multibody/geometry.hpp
@@ -37,8 +37,6 @@ namespace se3
   struct GeometryModel
   {
     
-    typedef std::vector<GeomIndex> GeomIndexList;
-
     /// \brief The number of GeometryObjects
     Index ngeoms;
 
@@ -47,22 +45,12 @@ namespace se3
     ///
     /// \brief Vector of collision pairs.
     ///
-    CollisionPairsVector_t collisionPairs;
+    std::vector<CollisionPair> collisionPairs;
   
-    /// \brief A list of associated collision GeometryObjects to a given joint Id.
-    ///        Inner objects can be seen as geometry objects that directly move when the associated joint moves
-    std::map < JointIndex, GeomIndexList >  innerObjects;
-
-    /// \brief A list of associated collision GeometryObjects to a given joint Id
-    ///        Outer objects can be seen as geometry objects that may often be obstacles to the Inner objects of given joint
-    std::map < JointIndex, GeomIndexList >  outerObjects;
-
     GeometryModel()
       : ngeoms(0)
       , geometryObjects()
       , collisionPairs()
-      , innerObjects()
-      , outerObjects()
     { 
       const std::size_t num_max_collision_pairs = (ngeoms * (ngeoms-1))/2;
       collisionPairs.reserve(num_max_collision_pairs);
@@ -177,21 +165,6 @@ namespace se3
     void displayCollisionPairs() const;
 #endif // WITH_HPP_FCL
 
-    /**
-     * @brief      Associate a GeometryObject of type COLLISION to a joint's inner objects list
-     *
-     * @param[in]  joint         Index of the joint
-     * @param[in]  inner_object  Index of the GeometryObject that will be an inner object
-     */
-    void addInnerObject(const JointIndex joint, const GeomIndex inner_object);
-    
-    /**
-     * @brief      Associate a GeometryObject of type COLLISION to a joint's outer objects list
-     *
-     * @param[in]  joint         Index of the joint
-     * @param[in]  inner_object  Index of the GeometryObject that will be an outer object
-     */
-    void addOutterObject(const JointIndex joint, const GeomIndex outer_object);
     friend std::ostream& operator<<(std::ostream & os, const GeometryModel & model_geom);
   }; // struct GeometryModel
 
@@ -260,6 +233,20 @@ namespace se3
     ///
     Index collisionPairIndex;
 
+    typedef std::vector<GeomIndex> GeomIndexList;
+
+    /// \brief Map over vector GeomModel::geometryObjects, indexed by joints.
+    /// 
+    /// The map lists the collision GeometryObjects associated to a given joint Id.
+    ///  Inner objects can be seen as geometry objects that directly move when the associated joint moves
+    std::map < JointIndex, GeomIndexList >  innerObjects;
+
+    /// \brief A list of associated collision GeometryObjects to a given joint Id
+    ///
+    /// Outer objects can be seen as geometry objects that may often be
+    /// obstacles to the Inner objects of given joint
+    std::map < JointIndex, GeomIndexList >  outerObjects;
+
     GeometryData(const GeometryModel & modelGeom)
         : model_geom(modelGeom)
         , oMg(model_geom.ngeoms)
@@ -269,12 +256,15 @@ namespace se3
         , collisionRequest (1, false, false, 1, false, true, fcl::GST_INDEP)
         , collision_results(modelGeom.collisionPairs.size())
         , radius()
-         
+        , collisionPairIndex(-1)
+        , innerObjects()
+        , outerObjects()
     {
       collisionObjects.reserve(modelGeom.geometryObjects.size());
       BOOST_FOREACH( const GeometryObject & geom, modelGeom.geometryObjects)
         { collisionObjects.push_back
             (fcl::CollisionObject(geom.collision_geometry)); }
+      fillInnerOuterObjectMaps();
     }
 #else
     GeometryData(const GeometryModel & modelGeom)
@@ -335,6 +325,14 @@ namespace se3
     void computeAllDistances() PINOCCHIO_DEPRECATED;
     
     void resetDistances();
+
+    /// Fill both innerObjects and outerObjects maps, from vectors collisionObjects and 
+    /// collisionPairs. 
+    ///
+    /// \warning Outer objects are not duplicated (i.e. if a is in outerObjects[b], then
+    /// b is not in outerObjects[a]).
+    void fillInnerOuterObjectMaps();
+
 #endif //WITH_HPP_FCL
     friend std::ostream & operator<<(std::ostream & os, const GeometryData & data_geom);
     
diff --git a/src/multibody/geometry.hxx b/src/multibody/geometry.hxx
index b42615045..a73801296 100644
--- a/src/multibody/geometry.hxx
+++ b/src/multibody/geometry.hxx
@@ -36,7 +36,6 @@ namespace se3
   {
     Index idx = (Index) (ngeoms ++);
     geometryObjects.push_back(object);
-    addInnerObject(object.parentJoint, idx);
     return idx;
   }
 
@@ -82,24 +81,50 @@ namespace se3
   }
 
 
-  inline void GeometryModel::addInnerObject(const JointIndex joint_id, const GeomIndex inner_object)
+    /**
+     * @brief      Associate a GeometryObject of type COLLISION to a joint's inner objects list
+     *
+     * @param[in]  joint         Index of the joint
+     * @param[in]  inner_object  Index of the GeometryObject that will be an inner object
+     */
+  // inline void GeometryModel::addInnerObject(const JointIndex joint_id, const GeomIndex inner_object)
+  // {
+  //   if (std::find(innerObjects[joint_id].begin(),
+  //                 innerObjects[joint_id].end(),
+  //                 inner_object) == innerObjects[joint_id].end())
+  //     innerObjects[joint_id].push_back(inner_object);
+  //   else
+  //     std::cout << "inner object already added" << std::endl;
+  // }
+
+    /**
+     * @brief      Associate a GeometryObject of type COLLISION to a joint's outer objects list
+     *
+     * @param[in]  joint         Index of the joint
+     * @param[in]  inner_object  Index of the GeometryObject that will be an outer object
+     */
+  // inline void GeometryModel::addOutterObject (const JointIndex joint, const GeomIndex outer_object)
+  // {
+  //   if (std::find(outerObjects[joint].begin(),
+  //                 outerObjects[joint].end(),
+  //                 outer_object) == outerObjects[joint].end())
+  //     outerObjects[joint].push_back(outer_object);
+  //   else
+  //     std::cout << "outer object already added" << std::endl;
+  // }
+
+  inline void GeometryData::fillInnerOuterObjectMaps()
   {
-    if (std::find(innerObjects[joint_id].begin(),
-                  innerObjects[joint_id].end(),
-                  inner_object) == innerObjects[joint_id].end())
-      innerObjects[joint_id].push_back(inner_object);
-    else
-      std::cout << "inner object already added" << std::endl;
-  }
+    innerObjects.clear();
+    outerObjects.clear();
 
-  inline void GeometryModel::addOutterObject (const JointIndex joint, const GeomIndex outer_object)
-  {
-    if (std::find(outerObjects[joint].begin(),
-                  outerObjects[joint].end(),
-                  outer_object) == outerObjects[joint].end())
-      outerObjects[joint].push_back(outer_object);
-    else
-      std::cout << "outer object already added" << std::endl;
+    for( GeomIndex gid = 0; gid<model_geom.geometryObjects.size(); gid++)
+      innerObjects[model_geom.geometryObjects[gid].parentJoint].push_back(gid);
+
+    BOOST_FOREACH( const CollisionPair & pair, model_geom.collisionPairs )
+      {
+        outerObjects[model_geom.geometryObjects[pair.first].parentJoint].push_back(pair.second);
+      }
   }
 
   inline std::ostream & operator<< (std::ostream & os, const GeometryModel & model_geom)
-- 
GitLab