From cbfc5e238da071a65606c5eeb51dab779a6f08e8 Mon Sep 17 00:00:00 2001
From: Aurelien Bricier <aurelien.bricier@c-s.fr>
Date: Mon, 7 Mar 2011 13:09:44 +0100
Subject: [PATCH] ENH: enriched fuzzy variable parametrization

---
 Code/Fuzzy/otbFuzzyVariable.h                 |  14 ++-
 Code/Fuzzy/otbFuzzyVariable.txx               |  45 ++++++-
 Testing/Code/Fuzzy/CMakeLists.txt             |  36 ++++++
 Testing/Code/Fuzzy/otbFuzzyTests2.cxx         |  35 ++++++
 .../Code/Fuzzy/otbFuzzyVariableDSApplied.cxx  |  73 ++++++++++++
 .../Code/Fuzzy/otbMassOfBeliefDSApplied.cxx   | 112 ++++++++++++++++++
 6 files changed, 307 insertions(+), 8 deletions(-)
 create mode 100644 Testing/Code/Fuzzy/otbFuzzyTests2.cxx
 create mode 100644 Testing/Code/Fuzzy/otbFuzzyVariableDSApplied.cxx
 create mode 100644 Testing/Code/Fuzzy/otbMassOfBeliefDSApplied.cxx

diff --git a/Code/Fuzzy/otbFuzzyVariable.h b/Code/Fuzzy/otbFuzzyVariable.h
index 5673062590..56a9984502 100644
--- a/Code/Fuzzy/otbFuzzyVariable.h
+++ b/Code/Fuzzy/otbFuzzyVariable.h
@@ -34,6 +34,9 @@ namespace otb
  *  of the qualitative values of the variable (MEDIUM = 0.9). Each
  *  membership function is modeled by a trapezoidal function for which
  *  4 values have to be provided.
+ *  In addition, 2 more values can be provided to define the min and
+ *  the max. By default, they ar 0 and 1 respectively.
+ *  
  */
 template <class TLabel = unsigned short, class TPrecision=double>
 class ITK_EXPORT FuzzyVariable : public itk::DataObject
@@ -56,9 +59,8 @@ public:
   typedef TPrecision PrecisionType;
  
   /** Type to hold the membership values */
-
   typedef std::map<LabelType, PrecisionType>        MembershipValueType;
-  typedef itk::FixedArray< PrecisionType, 4 >      ParametersType;
+  typedef itk::FixedArray< PrecisionType, 6>        ParametersType;
   typedef std::map<LabelType, ParametersType>       ParametersMapType;
 
   /** Get the membership related to one label */
@@ -77,6 +79,14 @@ public:
                      const PrecisionType & v3,
                      const PrecisionType & v4);
 
+  void SetMembership(const LabelType & var,
+                     const PrecisionType & v1,
+                     const PrecisionType & v2,
+                     const PrecisionType & v3,
+                     const PrecisionType & v4,
+                     const PrecisionType & min,
+                     const PrecisionType & max);
+
   /** Remove a given label from the membership table */
   void RemoveMembership(const LabelType & var);
 
diff --git a/Code/Fuzzy/otbFuzzyVariable.txx b/Code/Fuzzy/otbFuzzyVariable.txx
index 5570d8b73d..8c971e7b04 100644
--- a/Code/Fuzzy/otbFuzzyVariable.txx
+++ b/Code/Fuzzy/otbFuzzyVariable.txx
@@ -50,6 +50,8 @@ FuzzyVariable<TLabel, TPrecision>::SetMembership(const LabelType& var,
   parameters[1] = v2;
   parameters[2] = v3;
   parameters[3] = v4;
+  parameters[4] = static_cast<TPrecision>(0);
+  parameters[5] = static_cast<TPrecision>(1);
 
   // Insert it in the parameters map
   m_MembershipFunctions[var]=parameters;
@@ -58,6 +60,35 @@ FuzzyVariable<TLabel, TPrecision>::SetMembership(const LabelType& var,
   this->Modified();
 }
 
+template <class TLabel, class TPrecision>
+void
+FuzzyVariable<TLabel, TPrecision>::SetMembership(const LabelType& var,
+                                                 const PrecisionType & v1,
+                                                 const PrecisionType & v2,
+                                                 const PrecisionType & v3,
+                                                 const PrecisionType & v4,
+                                                 const PrecisionType & min,
+                                                 const PrecisionType & max)
+{
+  // Check if values are ordered correctly
+  if( v1>v2 || v2>v3 || v3>v4)
+    itkExceptionMacro(<< "Values have to be v1<=v2<=v3<=v4");
+
+  // Build the membership parameters
+  ParametersType parameters;
+  parameters[0] = v1;
+  parameters[1] = v2;
+  parameters[2] = v3;
+  parameters[3] = v4;
+  parameters[4] = min;
+  parameters[5] = max;
+
+  // Insert it in the parameters map
+  m_MembershipFunctions[var]=parameters;
+
+  // Call modified
+  this->Modified();
+}
 
 template <class TLabel, class TPrecision>
 void
@@ -105,7 +136,7 @@ FuzzyVariable<TLabel, TPrecision>
     // Remaining of the code is trapezoidal function
     if( value < parameters[0] || value > parameters[3] )
       {
-      output = 0;
+      output = parameters[4];
       }
     else if( value >= parameters[0]
              && value < parameters[1] )
@@ -113,18 +144,19 @@ FuzzyVariable<TLabel, TPrecision>
       if(parameters[1]>parameters[0])
         {
         output = static_cast<TPrecision>((value - parameters[0])
-                                         /(parameters[1] - parameters[0]));
+                                         /(parameters[1] - parameters[0])
+                                         *(parameters[5] - parameters[4]));
         }
       else
         {
-        output = static_cast<TPrecision>(1);
+        output = parameters[5];
         }
       }
 
     if( value >= parameters[1]
         && value < parameters[2] )
       {
-      output = static_cast<TPrecision>(1);
+      output = parameters[5];
       }
 
     if( value >= parameters[2]
@@ -133,11 +165,12 @@ FuzzyVariable<TLabel, TPrecision>
       if(parameters[3]>parameters[2])
         {
         output = static_cast<TPrecision>((parameters[3] - value)
-                                         /(parameters[3] - parameters[2]));
+                                         /(parameters[3] - parameters[2])
+                                         *(parameters[5] - parameters[4]));
         }
       else
         {
-        output = static_cast<TPrecision>(1);
+        output = parameters[5];
         }
       }
 
diff --git a/Testing/Code/Fuzzy/CMakeLists.txt b/Testing/Code/Fuzzy/CMakeLists.txt
index 7d86ce8a19..cdd21b05b4 100644
--- a/Testing/Code/Fuzzy/CMakeLists.txt
+++ b/Testing/Code/Fuzzy/CMakeLists.txt
@@ -19,6 +19,8 @@ SET(EPSILON_3 0.001)
 
 # Common generic tests
 SET(Fuzzy_TESTS1 ${CXX_TEST_PATH}/otbFuzzyTests1)
+# Advanced tests
+SET(Fuzzy_TESTS2 ${CXX_TEST_PATH}/otbFuzzyTests2)
 
 # FuzzyTests1
 ADD_TEST(fzTuFuzzyVariableNew ${Fuzzy_TESTS1} 
@@ -39,6 +41,30 @@ ADD_TEST(fzTvMassOfBelief ${Fuzzy_TESTS1}
 ADD_TEST(fzTvJointMassOfBeliefFilter ${Fuzzy_TESTS1}
         otbJointMassOfBeliefFilter)
 
+# FuzzyTests2
+ADD_TEST(fzTvFuzzyVariableDSApplied ${Fuzzy_TESTS2}
+        otbFuzzyVariableDSApplied)
+
+ADD_TEST(fzTvMassOfBeliefDSApplied ${Fuzzy_TESTS2}
+        otbMassOfBeliefDSApplied)
+
+#ADD_TEST(fzTuVectorDataToSpecificDescriptionFilterBaseNew ${Fuzzy_TESTS2}
+#        otbVectorDataToSpecificDescriptionFilterBaseNew)
+
+#ADD_TEST(fzTuVectorDataToRoadDescriptionFilterNew ${Fuzzy_TESTS2}
+#        otbVectorDataToRoadDescriptionFilterNew)
+
+#ADD_TEST(fzTvVectorDataToRoadDescriptionFilter ${Fuzzy_TESTS2}
+  #--compare-ogr ${NOTOL}
+  #${INPUTDATA}/.shp
+  #${TEMP}/.shp
+  #otbVectorDataToRoadDescriptionFilter
+  #${INPUTDATA}/ROI_QB_RANGUEUIL_ROADS.shp
+  #${INPUTDATA}/ROI_QB_RANGUEUIL_MUL_4.TIF
+  #${TEMP}/fzTvVectorDataToRoadDescriptionFilterOutput.shp
+  #)
+
+
 SET(BasicFuzzy_SRCS1
 otbFuzzyVariableNew.cxx
 otbFuzzyVariable2Values.cxx
@@ -48,7 +74,17 @@ otbMassOfBelief.cxx
 otbJointMassOfBeliefFilter.cxx
 )
 
+SET(BasicFuzzy_SRCS2
+otbFuzzyVariableDSApplied.cxx
+otbMassOfBeliefDSApplied.cxx
+#otbVectorDataToSpecificDescriptionFilterBase.cxx
+#otbVectorDataToRoadDescriptionFilter.cxx
+)
+
 ADD_EXECUTABLE(otbFuzzyTests1 otbFuzzyTests1.cxx ${BasicFuzzy_SRCS1})
 TARGET_LINK_LIBRARIES(otbFuzzyTests1 OTBIO OTBFuzzy  OTBTesting)
 
+ADD_EXECUTABLE(otbFuzzyTests2 otbFuzzyTests2.cxx ${BasicFuzzy_SRCS2})
+TARGET_LINK_LIBRARIES(otbFuzzyTests2 OTBIO OTBFuzzy OTBTesting)
+
 ENDIF( NOT OTB_DISABLE_CXX_TESTING AND BUILD_TESTING )
diff --git a/Testing/Code/Fuzzy/otbFuzzyTests2.cxx b/Testing/Code/Fuzzy/otbFuzzyTests2.cxx
new file mode 100644
index 0000000000..988452c771
--- /dev/null
+++ b/Testing/Code/Fuzzy/otbFuzzyTests2.cxx
@@ -0,0 +1,35 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+
+// this file defines the otbCommonTest for the test driver
+// and all it expects is that you have a function called RegisterTests
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4786 )
+#endif
+
+//
+#include "otbTestMain.h"
+
+void RegisterTests()
+{
+  REGISTER_TEST(otbFuzzyVariableDSApplied);
+  REGISTER_TEST(otbMassOfBeliefDSApplied);
+  //REGISTER_TEST(otbVectorDataToSpecificDescriptionFilterBaseNew);
+  //REGISTER_TEST(otbVectorDataToRoadDescriptionFilterNew);
+  //REGISTER_TEST(otbVectorDataToRoadDescriptionFilter);
+}
diff --git a/Testing/Code/Fuzzy/otbFuzzyVariableDSApplied.cxx b/Testing/Code/Fuzzy/otbFuzzyVariableDSApplied.cxx
new file mode 100644
index 0000000000..94266656df
--- /dev/null
+++ b/Testing/Code/Fuzzy/otbFuzzyVariableDSApplied.cxx
@@ -0,0 +1,73 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "otbFuzzyVariable.h"
+
+int otbFuzzyVariableDSApplied(int argc, char* argv[])
+{
+  typedef float PrecisionType;
+
+  typedef otb::FuzzyVariable<std::string, PrecisionType> FuzzyVarType;
+
+  FuzzyVarType::Pointer fv = FuzzyVarType::New();
+
+  fv->SetMembership("H1", 0, 0, 0.1, 0.5, 0, 0.8);
+  fv->SetMembership("!H1", 0.5, 0.8, 1.0, 1.0, 0, 0.8);
+  fv->SetMembership("Theta",0.1, 0.5, 0.5, 0.8, 0.2, 1);
+  
+  std::string maxVar;
+  PrecisionType pos;
+  PrecisionType memH1;
+  PrecisionType memH1_;
+  PrecisionType memTheta;
+
+  
+  for(unsigned int i=0; i<=100; i++)
+    {
+    pos       = (PrecisionType)i/100;
+    maxVar    = fv->GetMaxVar(pos);
+    memH1     = fv->GetMembership("H1", pos);
+    memH1_    = fv->GetMembership("!H1", pos);
+    memTheta  = fv->GetMembership("Theta", pos);
+
+
+    std::cout << "Memberships("
+              << pos
+              << "): ["
+              << memH1
+              << ", "
+              << memH1_
+              << ", "
+              << memTheta
+              <<"] - MaxVar(" 
+              << pos
+              << ") : " 
+              << maxVar
+              << std::endl;
+    }
+  
+  fv->RemoveMembership("H1");
+  fv->RemoveMembership("!H1");
+  fv->RemoveMembership("Theta");
+  fv->Clear();
+  
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/Fuzzy/otbMassOfBeliefDSApplied.cxx b/Testing/Code/Fuzzy/otbMassOfBeliefDSApplied.cxx
new file mode 100644
index 0000000000..80d3e876ff
--- /dev/null
+++ b/Testing/Code/Fuzzy/otbMassOfBeliefDSApplied.cxx
@@ -0,0 +1,112 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "otbMassOfBelief.h"
+
+#include "otbFuzzyVariable.h"
+#include "otbJointMassOfBeliefFilter.h"
+
+int otbMassOfBeliefDSApplied(int argc, char* argv[])
+{
+  typedef float                           PrecisionType;
+  typedef otb::FuzzyVariable<std::string, 
+    PrecisionType>                        FuzzyVarType;
+  
+  typedef otb::MassOfBelief<std::string>  MassOfBeliefFunctionType;
+
+  typedef otb::JointMassOfBeliefFilter<MassOfBeliefFunctionType> JointMassOfBeliefFilterType;
+
+  FuzzyVarType::Pointer desc1 = FuzzyVarType::New();
+  FuzzyVarType::Pointer desc2 = FuzzyVarType::New();
+
+  desc1->SetMembership("H1", 0, 0, 0.1, 0.5, 0, 0.8);
+  desc1->SetMembership("H1_", 0.5, 0.8, 1.0, 1.0, 0, 0.8);
+  
+  desc2->SetMembership("H2", 0, 0, 0.58, 0.68, 0, 0.99);
+  desc2->SetMembership("H2_", 0.68, 0.98, 1.0, 1.0, 0, 0.99);
+
+  PrecisionType desc1Val = 0.9;
+  PrecisionType desc2Val = 0.9;
+
+  MassOfBeliefFunctionType::Pointer mass1 = MassOfBeliefFunctionType::New();
+  MassOfBeliefFunctionType::Pointer mass2 = MassOfBeliefFunctionType::New();
+  MassOfBeliefFunctionType::Pointer jointMass = MassOfBeliefFunctionType::New();
+
+  MassOfBeliefFunctionType::LabelSetType H1, H1_, H2, H2_, universe, Hyp;
+  universe.insert("H1");
+  universe.insert("H1_");
+  universe.insert("H2");
+  universe.insert("H2_");
+
+  Hyp.insert("H1");
+  Hyp.insert("H2_");
+  
+  mass1->InitializePowerSetMasses(universe);
+  mass2->InitializePowerSetMasses(universe);
+
+  H1.insert("H1");
+  H1_.insert("H1_");
+  mass1->SetMass(H1, desc1->GetMembership("H1", desc1Val));
+  mass1->SetMass(H1_, desc1->GetMembership("H1_", desc1Val));
+  mass1->EstimateUncertainty();
+
+  H2.insert("H2");
+  H2_.insert("H2_");
+  mass2->SetMass(H2, desc2->GetMembership("H2", desc2Val));
+  mass2->SetMass(H2_, desc2->GetMembership("H2_", desc2Val));
+  mass2->EstimateUncertainty();
+  
+  JointMassOfBeliefFilterType::Pointer jointMassFilter = JointMassOfBeliefFilterType::New();
+  // Compute joint mass
+  jointMassFilter->PushBackInput(mass1);
+  jointMassFilter->PushBackInput(mass2);
+  jointMassFilter->Update();
+  jointMass = jointMassFilter->GetOutput();
+
+  std::cout<<mass1<<std::endl;
+  std::cout << "["
+            << desc1->GetMembership("H1", desc1Val)
+            << ","
+            << desc1->GetMembership("H1_", desc1Val)
+            << "]"
+            << std::endl;
+
+  std::cout<<mass2<<std::endl;
+  std::cout << "["
+            << desc2->GetMembership("H2", desc2Val)
+            << ","
+            << desc2->GetMembership("H2_", desc2Val)
+            << "]"
+            << std::endl;
+
+  std::cout << jointMass << std::endl;
+  std::cout << "Belief(Hyp) : "
+            << jointMass->GetBelief(Hyp)
+            << "  -  Plausibility(Hyp) : "
+            << jointMass->GetPlausibility(Hyp)
+            << "  -  Score(Hyp) : "
+            << (jointMass->GetBelief(Hyp) + jointMass->GetPlausibility(Hyp))/2.0
+            << std::endl;
+  
+  return EXIT_SUCCESS;
+}
+  
+  
-- 
GitLab