From c7e3e250b4e7f52ecc0c717baef60fddd70027b3 Mon Sep 17 00:00:00 2001
From: Rainer Kartmann <rainer.kartmann@student.kit.edu>
Date: Wed, 13 Feb 2019 15:41:58 +0100
Subject: [PATCH] Changed to use std::discrete_distribution

---
 .../ApproachMovementSurfaceNormal.cpp         | 45 +++----------------
 GraspPlanning/ApproachMovementSurfaceNormal.h | 30 ++++++++-----
 2 files changed, 26 insertions(+), 49 deletions(-)

diff --git a/GraspPlanning/ApproachMovementSurfaceNormal.cpp b/GraspPlanning/ApproachMovementSurfaceNormal.cpp
index 56b366cd5..3e930edb2 100644
--- a/GraspPlanning/ApproachMovementSurfaceNormal.cpp
+++ b/GraspPlanning/ApproachMovementSurfaceNormal.cpp
@@ -24,16 +24,17 @@ namespace GraspStudio
 {
 
     ApproachMovementSurfaceNormal::ApproachMovementSurfaceNormal(VirtualRobot::SceneObjectPtr object, VirtualRobot::EndEffectorPtr eef,
-            const std::string& graspPreshape, float maxRandDist, bool regardFaceAreas)
+            const std::string& graspPreshape, float maxRandDist, bool useFaceAreaDistribution)
         : ApproachMovementGenerator(object, eef, graspPreshape),
           randomDistanceMax(maxRandDist),
-          regardFaceAreas(regardFaceAreas)
+          distribUniform(0, objectModel->faces.size() - 1)
     {
         name = "ApproachMovementSurfaceNormal";
         
-        if (regardFaceAreas)
+        if (useFaceAreaDistribution)
         {
-            initFaceAreas();
+            std::vector<float> areas = objectModel->getFaceAreas();
+            distribFaceAreas = std::discrete_distribution<std::size_t>(areas.begin(), areas.end());
         }
     }
 
@@ -47,24 +48,8 @@ namespace GraspStudio
             return false;
         }
 
-        std::size_t faceIndex = 0;
-        if (!regardFaceAreas)
-        {
-            faceIndex = static_cast<std::size_t>(rand()) % objectModel->faces.size();
-        }
-        else
-        {
-            float ticket = distrib(randomEngine);
-            float currentTotal = 0;
-            
-            // find face that owns the ticket (i.e. face i with total[i-1] < ticket < total[i])
-            std::size_t i = 0;
-            for (i = 0; i < faceSizes.size() && currentTotal < ticket; ++i)
-            {
-                currentTotal += faceSizes[i];
-            }
-            faceIndex = i;
-        }
+        std::size_t faceIndex = useFaceAreasDistrib ? distribFaceAreas(randomEngine)
+                                                    : distribUniform(randomEngine);
 
         std::size_t nVert1 = (objectModel->faces[faceIndex]).id1;
         std::size_t nVert2 = (objectModel->faces[faceIndex]).id2;
@@ -253,20 +238,4 @@ namespace GraspStudio
         return true;
     }
     
-    void ApproachMovementSurfaceNormal::initFaceAreas()
-    {
-        faceSizesTotal = 0;
-        for (const auto& face : objectModel->faces)
-        {
-            float area = MathTools::getTriangleArea(objectModel->vertices[face.id1],
-                    objectModel->vertices[face.id2], objectModel->vertices[face.id3]);
-            
-            faceSizes.push_back(area);
-            faceSizesTotal += area;
-        }
-        
-        std::random_device rd;
-        randomEngine = std::default_random_engine(rd());
-        distrib = std::uniform_real_distribution<float>(0, faceSizesTotal);
-    }
 }
diff --git a/GraspPlanning/ApproachMovementSurfaceNormal.h b/GraspPlanning/ApproachMovementSurfaceNormal.h
index fa917ec8b..943dca423 100644
--- a/GraspPlanning/ApproachMovementSurfaceNormal.h
+++ b/GraspPlanning/ApproachMovementSurfaceNormal.h
@@ -27,6 +27,8 @@
 
 #include <VirtualRobot/SceneObject.h>
 
+#include <memory>
+#include <random>
 #include <vector>
 
 
@@ -53,11 +55,16 @@ namespace GraspStudio
          * \param object The object.
          * \param eef The end effector.
          * \param graspPreshape An optional preshape that can be used in order to "open" the eef.
-         * \param maxRandDist If >0, the resulting apporach pose is randomly moved in the approach direction (away from the object) in order to create different distances to the object.
+         * \param maxRandDist
+         *      If >0, the resulting apporach pose is randomly moved in the approach direction
+         *      (away from the object) in order to create different distances to the object.
+         * \param usefaceAreaDistribution
+         *      If true, the probability of a face being selected is proportional to its area.
+         *      If false, all faces are selected with equal probability.
         */
         ApproachMovementSurfaceNormal(VirtualRobot::SceneObjectPtr object, VirtualRobot::EndEffectorPtr eef,
                                       const std::string& graspPreshape = "", float maxRandDist = 0.0f,
-                                      bool regardFaceAreas = false);
+                                      bool useFaceAreaDistribution = false);
         //! Destructor
         virtual ~ApproachMovementSurfaceNormal() override;
 
@@ -78,18 +85,19 @@ namespace GraspStudio
 
     protected:
         
-        /// Fill faceSizes and faceSizesTotal with object model face sizes.
-        void initFaceAreas();
+        float randomDistanceMax;
         
+        /// The random engine.
+        std::default_random_engine randomEngine { std::random_device{}() };
         
-        float randomDistanceMax;
+        /// Uniform distribiton over face indices.
+        std::uniform_int_distribution<std::size_t> distribUniform;
+        
+        /// Indicates whether distribFaceAreas shall be used.
+        bool useFaceAreasDistrib = false;
+        /// Distribution with probability of a face proportional to its area.
+        std::discrete_distribution<std::size_t> distribFaceAreas;
         
-        bool regardFaceAreas = false;
-        std::vector<float> faceSizes;
-        float faceSizesTotal = 0;
-        std::default_random_engine randomEngine;
-        std::uniform_real_distribution<float> distrib;
-
     };
 }
 
-- 
GitLab