changeset 189:964118e7e6de wasm

unit test for AlignVectorsWithRotation
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 16 Mar 2018 13:19:23 +0100
parents 45b03b04a777
children 465b294a55f0
files Framework/Toolbox/FiniteProjectiveCamera.cpp Framework/Toolbox/GeometryToolbox.cpp Framework/Toolbox/GeometryToolbox.h Framework/Toolbox/LinearAlgebra.cpp Framework/Toolbox/LinearAlgebra.h UnitTestsSources/UnitTestsMain.cpp
diffstat 6 files changed, 131 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Toolbox/FiniteProjectiveCamera.cpp	Fri Mar 16 13:02:17 2018 +0100
+++ b/Framework/Toolbox/FiniteProjectiveCamera.cpp	Fri Mar 16 13:19:23 2018 +0100
@@ -253,8 +253,8 @@
     }
       
     Matrix a;
-    LinearAlgebra::AlignVectorsWithRotation(a, camera - principalPoint,
-                                            LinearAlgebra::CreateVector(0, 0, -1));
+    GeometryToolbox::AlignVectorsWithRotation(a, camera - principalPoint,
+                                              LinearAlgebra::CreateVector(0, 0, -1));
 
     Matrix r = LinearAlgebra::Product(GeometryToolbox::CreateRotationMatrixAlongZ(angle), a);
 
--- a/Framework/Toolbox/GeometryToolbox.cpp	Fri Mar 16 13:02:17 2018 +0100
+++ b/Framework/Toolbox/GeometryToolbox.cpp	Fri Mar 16 13:19:23 2018 +0100
@@ -415,5 +415,63 @@
         return true;
       }
     }
+
+
+    void AlignVectorsWithRotation(Matrix& r,
+                                  const Vector& a,
+                                  const Vector& b)
+    {
+      // This is Rodrigues' rotation formula:
+      // https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula#Matrix_notation
+
+      // Check also result A4.6 from "Multiple View Geometry in Computer
+      // Vision - 2nd edition" (p. 584)
+  
+      if (a.size() != 3 ||
+          b.size() != 3)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
+
+      double aNorm = boost::numeric::ublas::norm_2(a);
+      double bNorm = boost::numeric::ublas::norm_2(b);
+
+      if (LinearAlgebra::IsCloseToZero(aNorm) ||
+          LinearAlgebra::IsCloseToZero(bNorm))
+      {
+        LOG(ERROR) << "Vector with zero norm";
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);      
+      }
+
+      Vector aUnit, bUnit;
+      aUnit = a / aNorm;
+      bUnit = b / bNorm;
+
+      Vector v;
+      LinearAlgebra::CrossProduct(v, aUnit, bUnit);
+
+      double cosine = boost::numeric::ublas::inner_prod(aUnit, bUnit);
+
+      if (LinearAlgebra::IsCloseToZero(1 + cosine))
+      {
+        // "a == -b": TODO
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+      }
+
+      Matrix k;
+      LinearAlgebra::CreateSkewSymmetric(k, v);
+
+#if 0
+      double sine = boost::numeric::ublas::norm_2(v);
+
+      r = (boost::numeric::ublas::identity_matrix<double>(3) +
+           sine * k + 
+           (1 - cosine) * boost::numeric::ublas::prod(k, k));
+#else
+      r = (boost::numeric::ublas::identity_matrix<double>(3) +
+           k + 
+           boost::numeric::ublas::prod(k, k) / (1 + cosine));
+#endif
+    }
   }
 }
--- a/Framework/Toolbox/GeometryToolbox.h	Fri Mar 16 13:02:17 2018 +0100
+++ b/Framework/Toolbox/GeometryToolbox.h	Fri Mar 16 13:19:23 2018 +0100
@@ -95,6 +95,10 @@
                                const Vector& origin,
                                const Vector& direction);
 
+    void AlignVectorsWithRotation(Matrix& r,
+                                  const Vector& a,
+                                  const Vector& b);
+
     inline float ComputeBilinearInterpolationUnitSquare(float x,
                                                         float y,
                                                         float f00,    // source(0, 0)
--- a/Framework/Toolbox/LinearAlgebra.cpp	Fri Mar 16 13:02:17 2018 +0100
+++ b/Framework/Toolbox/LinearAlgebra.cpp	Fri Mar 16 13:19:23 2018 +0100
@@ -537,64 +537,6 @@
     }
 
   
-    void AlignVectorsWithRotation(Matrix& r,
-                                  const Vector& a,
-                                  const Vector& b)
-    {
-      // This is Rodrigues' rotation formula:
-      // https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula#Matrix_notation
-
-      // Check also result A4.6 from "Multiple View Geometry in Computer
-      // Vision - 2nd edition" (p. 584)
-  
-      if (a.size() != 3 ||
-          b.size() != 3)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-      }
-
-      double aNorm = boost::numeric::ublas::norm_2(a);
-      double bNorm = boost::numeric::ublas::norm_2(b);
-
-      if (LinearAlgebra::IsCloseToZero(aNorm) ||
-          LinearAlgebra::IsCloseToZero(bNorm))
-      {
-        LOG(ERROR) << "Vector with zero norm";
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);      
-      }
-
-      Vector aUnit, bUnit;
-      aUnit = a / aNorm;
-      bUnit = b / bNorm;
-
-      Vector v;
-      LinearAlgebra::CrossProduct(v, aUnit, bUnit);
-
-      double cosine = boost::numeric::ublas::inner_prod(aUnit, bUnit);
-
-      if (LinearAlgebra::IsCloseToZero(1 + cosine))
-      {
-        // "a == -b": TODO
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
-      }
-
-      Matrix k;
-      CreateSkewSymmetric(k, v);
-
-#if 0
-      double sine = boost::numeric::ublas::norm_2(v);
-
-      r = (boost::numeric::ublas::identity_matrix<double>(3) +
-           sine * k + 
-           (1 - cosine) * boost::numeric::ublas::prod(k, k));
-#else
-      r = (boost::numeric::ublas::identity_matrix<double>(3) +
-           k + 
-           boost::numeric::ublas::prod(k, k) / (1 + cosine));
-#endif
-    }
-
-
     Matrix InvertScalingTranslationMatrix(const Matrix& t)
     {
       if (t.size1() != 4 ||
--- a/Framework/Toolbox/LinearAlgebra.h	Fri Mar 16 13:02:17 2018 +0100
+++ b/Framework/Toolbox/LinearAlgebra.h	Fri Mar 16 13:19:23 2018 +0100
@@ -284,10 +284,6 @@
     void CreateSkewSymmetric(Matrix& s,
                              const Vector& v);
   
-    void AlignVectorsWithRotation(Matrix& r,
-                                  const Vector& a,
-                                  const Vector& b);
-
     Matrix InvertScalingTranslationMatrix(const Matrix& t);
 
     bool IsShearMatrix(const Matrix& shear);  
--- a/UnitTestsSources/UnitTestsMain.cpp	Fri Mar 16 13:02:17 2018 +0100
+++ b/UnitTestsSources/UnitTestsMain.cpp	Fri Mar 16 13:19:23 2018 +0100
@@ -658,6 +658,73 @@
 }
 
 
+static bool IsEqualVector(OrthancStone::Vector a,
+                          OrthancStone::Vector b)
+{
+  if (a.size() == 3 &&
+      b.size() == 3)
+  {
+    OrthancStone::LinearAlgebra::NormalizeVector(a);
+    OrthancStone::LinearAlgebra::NormalizeVector(b);
+    return OrthancStone::LinearAlgebra::IsCloseToZero(boost::numeric::ublas::norm_2(a - b));
+  }
+  else
+  {
+    return false;
+  } 
+}
+
+
+TEST(GeometryToolbox, AlignVectorsWithRotation)
+{
+  OrthancStone::Vector a, b;
+  OrthancStone::Matrix r;
+
+  OrthancStone::LinearAlgebra::AssignVector(a, -200, 200, -846.63);
+  OrthancStone::LinearAlgebra::AssignVector(b, 0, 0, 1);
+
+  OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, a, b);
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::IsRotationMatrix(r));
+  ASSERT_TRUE(IsEqualVector(OrthancStone::LinearAlgebra::Product(r, a), b));
+
+  OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, b, a);
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::IsRotationMatrix(r));
+  ASSERT_TRUE(IsEqualVector(OrthancStone::LinearAlgebra::Product(r, b), a));
+
+  OrthancStone::LinearAlgebra::AssignVector(a, 1, 0, 0);
+  OrthancStone::LinearAlgebra::AssignVector(b, 0, 0, 1);
+  OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, a, b);
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::IsRotationMatrix(r));
+  ASSERT_TRUE(IsEqualVector(OrthancStone::LinearAlgebra::Product(r, a), b));
+
+  OrthancStone::LinearAlgebra::AssignVector(a, 0, 1, 0);
+  OrthancStone::LinearAlgebra::AssignVector(b, 0, 0, 1);
+  OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, a, b);
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::IsRotationMatrix(r));
+  ASSERT_TRUE(IsEqualVector(OrthancStone::LinearAlgebra::Product(r, a), b));
+
+  OrthancStone::LinearAlgebra::AssignVector(a, 0, 0, 1);
+  OrthancStone::LinearAlgebra::AssignVector(b, 0, 0, 1);
+  OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, a, b);
+  ASSERT_TRUE(OrthancStone::LinearAlgebra::IsRotationMatrix(r));
+  ASSERT_TRUE(IsEqualVector(OrthancStone::LinearAlgebra::Product(r, a), b));
+
+  OrthancStone::LinearAlgebra::AssignVector(a, 0, 0, 0);
+  OrthancStone::LinearAlgebra::AssignVector(b, 0, 0, 1);
+  ASSERT_THROW(OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, a, b), Orthanc::OrthancException);
+
+  // TODO: Deal with opposite vectors
+
+  /*
+  OrthancStone::LinearAlgebra::AssignVector(a, 0, 0, -1);
+  OrthancStone::LinearAlgebra::AssignVector(b, 0, 0, 1);
+  OrthancStone::GeometryToolbox::AlignVectorsWithRotation(r, a, b);
+  OrthancStone::LinearAlgebra::Print(r);
+  OrthancStone::LinearAlgebra::Print(boost::numeric::ublas::prod(r, a));
+  */
+}
+
+
 int main(int argc, char **argv)
 {
   Orthanc::Logging::Initialize();