From 16bd0b41e4df947a4ae683432f79ecd754e9bcdb Mon Sep 17 00:00:00 2001
From: Marco Biasini <marco.biasini@unibas.ch>
Date: Sun, 20 Mar 2011 22:42:05 +0100
Subject: [PATCH] move some geom unit tests from IPLT to OST

---
 modules/geom/src/composite3.cc        |  26 +---
 modules/geom/src/composite3.hh        |   7 +-
 modules/geom/src/composite3_op.cc     |  38 ++++--
 modules/geom/src/composite3_op.hh     |   2 +-
 modules/geom/src/mat2.hh              |   9 +-
 modules/geom/src/mat3.hh              |   9 +-
 modules/geom/src/mat4.cc              |   4 +-
 modules/geom/src/vec2.hh              |  11 +-
 modules/geom/src/vec3.hh              |  13 +-
 modules/geom/src/vec4.hh              |   2 +-
 modules/geom/tests/CMakeLists.txt     |   9 ++
 modules/geom/tests/helper.hh          | 129 ++++++++++++++++++
 modules/geom/tests/test_composite2.cc |   3 +
 modules/geom/tests/test_composite3.cc | 184 +++++++++++++++++++++++---
 modules/geom/tests/test_mat2.cc       |  64 +++++++++
 modules/geom/tests/test_mat3.cc       |  92 +++++++++++++
 modules/geom/tests/test_mat4.cc       | 104 +++++++++++++++
 modules/geom/tests/test_op2.cc        |  50 +++++++
 modules/geom/tests/test_op3.cc        |  51 +++++++
 modules/geom/tests/test_op4.cc        |  46 +++++++
 modules/geom/tests/test_vec2.cc       | 110 +++++++++++++++
 modules/geom/tests/test_vec3.cc       | 127 ++++++++++++++++++
 modules/geom/tests/test_vec4.cc       | 112 ++++++++++++++++
 modules/gui/src/tools/map_tool.cc     |   2 +-
 24 files changed, 1129 insertions(+), 75 deletions(-)
 create mode 100644 modules/geom/tests/helper.hh
 create mode 100644 modules/geom/tests/test_mat2.cc
 create mode 100644 modules/geom/tests/test_mat3.cc
 create mode 100644 modules/geom/tests/test_mat4.cc
 create mode 100644 modules/geom/tests/test_op2.cc
 create mode 100644 modules/geom/tests/test_op3.cc
 create mode 100644 modules/geom/tests/test_op4.cc
 create mode 100644 modules/geom/tests/test_vec2.cc
 create mode 100644 modules/geom/tests/test_vec3.cc
 create mode 100644 modules/geom/tests/test_vec4.cc

diff --git a/modules/geom/src/composite3.cc b/modules/geom/src/composite3.cc
index 2017a6d2e..686e843e1 100644
--- a/modules/geom/src/composite3.cc
+++ b/modules/geom/src/composite3.cc
@@ -62,14 +62,12 @@ Plane::Plane(const Vec3& p1, const Vec3& p2, const Vec3& p3)
   Vec3 ip2=p3-p1;
   n_=Normalize(Cross(ip1,ip2));
   p_=-Dot(n_,p1);
-  calc_ori();
 }
 
 Plane::Plane(const Vec3& p, const Vec3& n)
 {
   n_=Normalize(n);
   p_=-Dot(n_,p);
-  o_=p;
 }
 
 Plane::Plane(const Line3& l,const Vec3& p)
@@ -77,15 +75,13 @@ Plane::Plane(const Line3& l,const Vec3& p)
   Vec3 ip=l.GetOrigin()-p;
   n_=Normalize(Cross(ip,l.GetDirection()));
   p_=-Dot(n_,p);
-  calc_ori();
 }
 
-Plane::Plane( Real a, Real b, Real c, Real d)
+Plane::Plane(Real a, Real b, Real c, Real d)
 {
   n_=Vec3(a,b,c);
   p_=d/Length(n_);
   n_=Normalize(n_);
-  calc_ori();
 }
 
 Plane::Plane( Real x, Real y, Real z)
@@ -93,18 +89,6 @@ Plane::Plane( Real x, Real y, Real z)
   n_=Vec3(1.0/x,1.0/y,1.0/z);
   p_=-1.0/Length(n_);
   n_=Normalize(n_);
-  calc_ori();
-}
-
-Vec3 Plane::GetOrigin() const
-{
-  return o_;
-}
-
-void Plane::SetOrigin(const Vec3& o)
-{
-  o_=o;
-  p_=-Dot(n_,o_);
 }
 
 Vec3 Plane::GetNormal() const
@@ -115,7 +99,6 @@ Vec3 Plane::GetNormal() const
 void Plane::SetNormal(const Vec3& n)
 {
   n_=Normalize(n);
-  p_=-Dot(n_,o_);
 }
 
 Real Plane::GetP() const
@@ -128,13 +111,6 @@ Vec3 Plane::At(Real x,Real y) const
   return n_[2]!=0.0 ? Vec3(x,y,-(n_[0]*x+n_[1]*y+p_)/n_[2]) : Vec3();
 }
 
-void Plane::calc_ori()
-{
-  o_=p_/3.0*Vec3(n_[0]==0.0 ? 0.0 : 1.0/n_[0],
-                 n_[1]==0.0 ? 0.0 : 1.0/n_[1],
-                 n_[2]==0.0 ? 0.0 : 1.0/n_[2]);
-};
-
 
 /************************************************************
 *  Sphere                                                    *
diff --git a/modules/geom/src/composite3.hh b/modules/geom/src/composite3.hh
index 72b885319..ae5f56ba6 100644
--- a/modules/geom/src/composite3.hh
+++ b/modules/geom/src/composite3.hh
@@ -63,11 +63,11 @@ public:
   //! initialize based x-,y-,z- intercepts
   Plane(Real x, Real y, Real z);
 
-  Vec3 GetOrigin() const;
-  void SetOrigin(const Vec3& o);
+  Vec3 GetOrigin() const { return -p_*n_; }
   Vec3 GetNormal() const;
   void SetNormal(const Vec3& n);
   Real GetP()    const;
+  void SetP(Real p) { p_=p; }
   Vec3 At(Real x, Real y) const;
 
   enum PLANE_TYPE {
@@ -78,9 +78,6 @@ private:
   // planes are internally specified in HNF 
   Vec3 n_;
   Real p_;
-  Vec3 o_;
-
-  void calc_ori();
 };
 
 class DLLEXPORT Sphere {
diff --git a/modules/geom/src/composite3_op.cc b/modules/geom/src/composite3_op.cc
index d1602699c..09fb2c72e 100644
--- a/modules/geom/src/composite3_op.cc
+++ b/modules/geom/src/composite3_op.cc
@@ -17,6 +17,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 #include <cmath>
+#include <iostream>
 #include "exc.hh"
 #include "composite3_op.hh"
 #include "vecmat3_op.hh"
@@ -101,7 +102,7 @@ bool IsInPlane(const Plane& p,  const Line3& l,Real ephilon)
 }
 bool IsInPlane(const Plane& p,  const Vec3& v,Real ephilon)
 {
-  return Distance(p,v)<ephilon;  
+  return std::fabs(Distance(p,v))<ephilon;  
 }
 int RelativePosition(const Plane& p,  const Vec3& v,Real ephilon)
 {
@@ -119,43 +120,58 @@ bool operator==(const Plane& p1, const Plane& p2)
 }
 bool Equal(const Plane& p1, const Plane& p2,Real ephilon)
 {
-  return std::fabs(p1.GetP()-p2.GetP())<ephilon && Equal(p1.GetNormal(),p2.GetNormal(),ephilon);
+  return std::fabs(p1.GetP()-p2.GetP())<ephilon && 
+         Equal(p1.GetNormal(),p2.GetNormal(),ephilon);
 }
 bool EqualPosition(const Plane& p1, const Plane& p2,Real ephilon)
 {
-  return  Equal(p1,p2,ephilon) || (std::fabs(p1.GetP()+p2.GetP())<ephilon && Equal(p1.GetNormal(),-1.0*p2.GetNormal(),ephilon));
+  return  Equal(p1,p2,ephilon) || 
+          (std::fabs(p1.GetP()+p2.GetP())<ephilon && Equal(p1.GetNormal(),
+                                                           -p2.GetNormal(),
+                                                           ephilon));
 }
 bool operator==(const Line3& l1, const Line3& l2)
 {
   return Equal(l1,l2);
 }
+
 bool Equal(const Line3& l1, const Line3& l2,Real ephilon)
 {
-  return  Equal(l1.GetDirection(),l2.GetDirection(),ephilon) && Equal(l1.GetOrigin(),l2.GetOrigin(),ephilon);
+  return Equal(l1.GetDirection(), l2.GetDirection(), ephilon) &&
+         Equal(l1.GetOrigin(), l2.GetOrigin(), ephilon);
 }
+
 bool EqualPosition(const Line3& l1, const Line3& l2,Real ephilon)
 {
-  return  IsOnLine(l1,l2.GetOrigin()) && AreParallel(l1,l2);
+  return IsOnLine(l1,l2.GetOrigin(), ephilon) && AreParallel(l1,l2, ephilon);
 }
 
 
 bool AreParallel(const Plane& p,  const Line3& l,Real ephilon)
 {
-  return std::fabs(Dot(l.GetDirection(),p.GetNormal()))<ephilon;  
+  return std::fabs(Dot(l.GetDirection(),p.GetNormal()))<ephilon;
 }
+
 bool AreParallel(const Plane& p1, const Plane& p2,Real ephilon)
 {
-  return std::fabs(1-Dot(p1.GetNormal(),p2.GetNormal()))<ephilon;  
+  return std::fabs(1-Dot(p1.GetNormal(),p2.GetNormal()))<ephilon;
 }
-bool AreParallel(const Line3& l1, const Line3& l2,Real ephilon)
+
+bool AreParallel(const Line3& l1, const Line3& l2, Real ephilon)
 {
-  return std::fabs(1-Dot(l1.GetDirection(),l1.GetDirection()))<ephilon;  
+  return std::fabs(1.0-std::fabs(Dot(l1.GetDirection(), 
+                                     l2.GetDirection())))<ephilon;
 }
 
 
-bool AreIntersecting( const Line3& l1, const Line3& l2, Real ephilon)
+bool AreIntersecting(const Line3& l1, const Line3& l2, Real ephilon)
 {
-  return IsInPlane(Plane(l1.GetOrigin(),l2.GetOrigin(),l1.At(1)),l2.At(1),ephilon);
+  if (AreParallel(l1, l2, ephilon)) {
+    return false;
+  }
+  Plane plane(l1.GetOrigin(), Cross(l1.GetDirection(), 
+                                    l2.GetDirection()));
+  return IsInPlane(plane, l2.GetOrigin(), ephilon);
 }
 
 bool IsInSphere(const Sphere& s, const Vec3& v){
diff --git a/modules/geom/src/composite3_op.hh b/modules/geom/src/composite3_op.hh
index 4e6a2ad1a..23bdf3e5e 100644
--- a/modules/geom/src/composite3_op.hh
+++ b/modules/geom/src/composite3_op.hh
@@ -54,7 +54,7 @@ bool DLLEXPORT_OST_GEOM AreParallel(const Plane& p,  const Line3& l,Real ephilon
 bool DLLEXPORT_OST_GEOM AreParallel(const Plane& p1, const Plane& p2,Real ephilon=EPSILON);
 bool DLLEXPORT_OST_GEOM AreParallel(const Line3& l1, const Line3& l2,Real ephilon=EPSILON);
 
-bool DLLEXPORT_OST_GEOM AreIntersecting( const Line3& l1, const Line3& l2, Real ephilon=EPSILON);
+bool DLLEXPORT_OST_GEOM AreIntersecting(const Line3& l1, const Line3& l2, Real ephilon=EPSILON);
 
 DLLEXPORT bool IsInSphere(const Sphere& p,const Vec3& v);
 
diff --git a/modules/geom/src/mat2.hh b/modules/geom/src/mat2.hh
index 53fd0c59e..cb5910df4 100644
--- a/modules/geom/src/mat2.hh
+++ b/modules/geom/src/mat2.hh
@@ -22,6 +22,7 @@
 #include <cstddef> // for size_t
 #include <ostream>
 #include <cassert>
+#include <stdexcept>
 
 #include <boost/operators.hpp>
 
@@ -66,13 +67,17 @@ public:
   //! element access
   Real& operator()(std::size_t r, std::size_t c)
   {
-    assert(r<=1 && c<=1);
+    if (r>1 || c >1) {
+      throw std::out_of_range("row and column must be in the range [0-1]");
+    }
     return data_[r][c];
   }
   //! const element access
   const Real& operator()(std::size_t r, std::size_t c) const
   {
-    assert(r<=1 && c<=1);
+    if (r>1 || c >1) {
+      throw std::out_of_range("row and column must be in the range [0-1]");
+    }
     return data_[r][c];
   }
 
diff --git a/modules/geom/src/mat3.hh b/modules/geom/src/mat3.hh
index 448a66513..3cef352ed 100644
--- a/modules/geom/src/mat3.hh
+++ b/modules/geom/src/mat3.hh
@@ -22,6 +22,7 @@
 #include <cstddef> // for size_t
 #include <ostream>
 #include <cassert>
+#include <stdexcept>
 
 #include <boost/operators.hpp>
 
@@ -83,13 +84,17 @@ public:
   //! element access
   Real& operator()(std::size_t r, std::size_t c)
   {
-    assert(r<=2 && c<=2);
+    if (r>2 || c >2) {
+      throw std::out_of_range("row and column must be in the range [0-2]");
+    }
     return data_[r][c];
   }
   //! const element access
   const Real& operator()(std::size_t r, std::size_t c) const
   {
-    assert(r<=2 && c<=2);
+    if (r>2 || c >2) {
+      throw std::out_of_range("row and column must be in the range [0-2]");
+    }
     return data_[r][c];
   }
 
diff --git a/modules/geom/src/mat4.cc b/modules/geom/src/mat4.cc
index 7e2476cab..fbbc1c2a0 100644
--- a/modules/geom/src/mat4.cc
+++ b/modules/geom/src/mat4.cc
@@ -123,13 +123,13 @@ bool Mat4::operator==(const Mat4& rhs) const
 
 Real& Mat4::operator()(std::size_t r, std::size_t c)
 {
-  if(r>4 || c>4) throw OutOfRangeException();
+  if(r>3 || c>3) throw std::out_of_range("row and column must be in range [0-3]");
   return data_[r][c];
 }
 
 const Real& Mat4::operator()(std::size_t r, std::size_t c) const
 {
-  if(r>4 || c>4) throw OutOfRangeException();
+  if(r>3 || c>3) throw std::out_of_range("row and column must be in range [0-3]");
   return data_[r][c];
 }
 
diff --git a/modules/geom/src/vec2.hh b/modules/geom/src/vec2.hh
index 110ab3108..6978381ff 100644
--- a/modules/geom/src/vec2.hh
+++ b/modules/geom/src/vec2.hh
@@ -28,7 +28,7 @@
 
 #include <ost/config.hh>
 #include <ost/geom/module_config.hh>
-
+#include <ost/geom/exc.hh>
 namespace geom {
 
 // fw decl
@@ -178,7 +178,14 @@ namespace geom {
 inline Vec2::Vec2(const Vec3& v): x(v.x), y(v.y) { }
 
 
-inline Vec2::Vec2(const Vec4& v): x(v.x), y(v.y) { }
+inline Vec2::Vec2(const Vec4& v): x(v.x), y(v.y) 
+{
+  if (std::fabs(v.w)<1e-10) {
+    throw DivideByZeroException();
+  }
+  x/=v.w;
+  y/=v.w;
+}
 
 
 typedef std::vector<Vec2> Vec2List;
diff --git a/modules/geom/src/vec3.hh b/modules/geom/src/vec3.hh
index 5b31dd7a4..ec9a6cb75 100644
--- a/modules/geom/src/vec3.hh
+++ b/modules/geom/src/vec3.hh
@@ -28,7 +28,7 @@
 
 #include <ost/config.hh>
 #include <ost/geom/module_config.hh>
-
+#include <ost/geom/exc.hh>
 namespace geom {
 
 // fw decl
@@ -220,7 +220,16 @@ public:
 
 
 inline Vec3::Vec3(const Vec2& v): x(v.x), y(v.y), z(0.0) { }
-inline Vec3::Vec3(const Vec4& v): x(v.x/v.w), y(v.y/v.w), z(v.z/v.w) { }
+
+inline Vec3::Vec3(const Vec4& v): x(v.x), y(v.y), z(v.z) 
+{ 
+  if (std::fabs(v.w)<1e-10) {
+    throw DivideByZeroException();
+  }
+  x/=v.w;
+  y/=v.w;
+  z/=v.w;
+}
   
 } // namespace geom
 
diff --git a/modules/geom/src/vec4.hh b/modules/geom/src/vec4.hh
index dd72be585..20b5fd2a7 100644
--- a/modules/geom/src/vec4.hh
+++ b/modules/geom/src/vec4.hh
@@ -45,7 +45,7 @@ class DLLEXPORT Vec4:
 {
 public:
   //! Default initialization, all components are set to zero
-  Vec4(): x(0), y(0), z(0), w(0) { }
+  Vec4(): x(0), y(0), z(0), w(1) { }
 
   //! Initialization with x, y and z component
   Vec4(Real px, Real py, Real pz, Real pw): x(px), y(py), z(pz), w(pw) { }
diff --git a/modules/geom/tests/CMakeLists.txt b/modules/geom/tests/CMakeLists.txt
index 6a638d774..a7c4ab6c2 100644
--- a/modules/geom/tests/CMakeLists.txt
+++ b/modules/geom/tests/CMakeLists.txt
@@ -1,6 +1,15 @@
 set(GEOM_UNITTESTS
   test_composite3.cc
   test_composite2.cc
+  test_mat2.cc
+  test_mat3.cc
+  test_mat4.cc
+  test_op2.cc
+  test_op3.cc
+  test_op4.cc
+  test_vec2.cc
+  test_vec3.cc
+  test_vec4.cc
   tests.cc
 )
 
diff --git a/modules/geom/tests/helper.hh b/modules/geom/tests/helper.hh
new file mode 100644
index 000000000..8ad2626ef
--- /dev/null
+++ b/modules/geom/tests/helper.hh
@@ -0,0 +1,129 @@
+/////////////////////////////////////////////////////////
+// IPLT - Image Processing Library & Toolbox
+// Copyright (c) 2003-2007 University of Basel
+//
+// The usage terms and conditions of this software 
+// are governed by the GNU General Public License, 
+// as described in the accompanying text file LICENSE.
+// Please review this information carefully and contact
+// info@iplt.org should questions arise.
+/////////////////////////////////////////////////////////
+
+/*
+  Author: Ansgar Philippsen
+*/
+
+#ifndef GEOM_HELPER_HH
+#define GEOM_HELPER_HH
+
+#include <cstdlib>
+#include <cmath>
+
+#include <boost/random.hpp>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/unit_test_suite.hpp>
+using boost::unit_test::test_suite;
+
+#include <ost/geom/geom.hh>
+
+using namespace geom;
+
+
+inline bool dequal(Real a, Real b)
+{
+  return std::fabs(a-b)<EPSILON;
+}
+inline
+bool match(const Vec2& v, Real x, Real y)
+{
+  return std::fabs(v[0]-x)<EPSILON && std::fabs(v[1]-y)<EPSILON;
+}
+
+inline
+bool match(const Vec3& v, Real x, Real y, Real z)
+{
+  return std::fabs(v[0]-x)<EPSILON && std::fabs(v[1]-y)<EPSILON && std::fabs(v[2]-z)<EPSILON;
+}
+
+inline
+bool match(const Vec4& v, Real x, Real y, Real z, Real w)
+{
+  return std::fabs(v[0]-x)<EPSILON && std::fabs(v[1]-y)<EPSILON && std::fabs(v[2]-z)<EPSILON && std::fabs(v[3]-w)<EPSILON;
+}
+
+inline  
+bool match(const Mat2& m, Real i00, Real i01,  Real i10, Real i11)
+{
+  return std::fabs(m(0,0)-i00)<EPSILON &&
+    std::fabs(m(0,1)-i01)<EPSILON &&
+    std::fabs(m(1,0)-i10)<EPSILON &&
+    std::fabs(m(1,1)-i11)<EPSILON;
+}
+
+inline
+bool match(const Mat3& m, Real i00, Real i01, Real i02, Real i10, Real i11, Real i12, Real i20, Real i21, Real i22)
+{
+  return std::fabs(m(0,0)-i00)<EPSILON &&
+    std::fabs(m(0,1)-i01)<EPSILON &&
+    std::fabs(m(0,2)-i02)<EPSILON &&
+    std::fabs(m(1,0)-i10)<EPSILON &&
+    std::fabs(m(1,1)-i11)<EPSILON &&
+    std::fabs(m(1,2)-i12)<EPSILON &&
+    std::fabs(m(2,0)-i20)<EPSILON &&
+    std::fabs(m(2,1)-i21)<EPSILON &&
+    std::fabs(m(2,2)-i22)<EPSILON;
+
+}
+  
+inline
+bool match(const Mat4& m, Real i00, Real i01, Real i02, Real i03, Real i10, Real i11, Real i12, Real i13, Real i20, Real i21, Real i22, Real i23, Real i30, Real i31, Real i32, Real i33)
+{
+  static Real EPSILON=1e-10;
+  return std::fabs(m(0,0)-i00)<EPSILON &&
+    std::fabs(m(0,1)-i01)<EPSILON &&
+    std::fabs(m(0,2)-i02)<EPSILON &&
+    std::fabs(m(0,3)-i03)<EPSILON &&
+    std::fabs(m(1,0)-i10)<EPSILON &&
+    std::fabs(m(1,1)-i11)<EPSILON &&
+    std::fabs(m(1,2)-i12)<EPSILON &&
+    std::fabs(m(1,3)-i13)<EPSILON &&
+    std::fabs(m(2,0)-i20)<EPSILON &&
+    std::fabs(m(2,1)-i21)<EPSILON &&
+    std::fabs(m(2,2)-i22)<EPSILON &&
+    std::fabs(m(2,3)-i23)<EPSILON &&
+    std::fabs(m(3,0)-i30)<EPSILON &&
+    std::fabs(m(3,1)-i31)<EPSILON &&
+    std::fabs(m(3,2)-i32)<EPSILON &&
+    std::fabs(m(3,3)-i33)<EPSILON;
+}
+
+namespace {
+  boost::mt19937 RandomGenerator;
+  boost::uniform_01<boost::mt19937> UniformRandom(RandomGenerator);
+}
+
+inline  
+Vec3 rnd_vec3()
+{
+  return Vec3(UniformRandom(),UniformRandom(),UniformRandom());
+}
+
+inline  
+Mat3 rnd_mat3()
+{
+  return Mat3(UniformRandom(),UniformRandom(),UniformRandom(),
+	      UniformRandom(),UniformRandom(),UniformRandom(),
+	      UniformRandom(),UniformRandom(),UniformRandom());
+}
+
+inline  
+Mat2 rnd_mat2()
+{
+  return Mat2(UniformRandom(),UniformRandom(),
+	          UniformRandom(),UniformRandom());
+}
+
+
+
+#endif
diff --git a/modules/geom/tests/test_composite2.cc b/modules/geom/tests/test_composite2.cc
index 5f79e7b44..eccafec8a 100644
--- a/modules/geom/tests/test_composite2.cc
+++ b/modules/geom/tests/test_composite2.cc
@@ -17,8 +17,11 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
+
 #include <ost/geom/geom.hh>
 
+#include "helper.hh"
+
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 
diff --git a/modules/geom/tests/test_composite3.cc b/modules/geom/tests/test_composite3.cc
index 1ee00dafd..6548b53da 100644
--- a/modules/geom/tests/test_composite3.cc
+++ b/modules/geom/tests/test_composite3.cc
@@ -19,36 +19,178 @@
 
 #include <ost/geom/geom.hh>
 
+#include "helper.hh"
+using namespace geom;
+
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 
-using namespace geom;
-
 BOOST_AUTO_TEST_SUITE( geom )
 
+BOOST_AUTO_TEST_CASE(init_composite3)
+{
+  
+  // Vec3 v1(3,4,5);
+  // Vec3 v2(8,10,-2);
+  // Vec3 v3(-5,3,8);
+  
+  Vec3 v1(0,5,0);
+  Vec3 v2(1,5,0);
+  Vec3 v3(0,5,1);
+  //------------- Line3 --------------
+  //default
+  Line3 l;
+  BOOST_CHECK(match(l.GetOrigin(),0.0,0.0,0.0));
+  BOOST_CHECK(match(l.GetDirection(),1.0,0.0,0.0));
+      
+  //2 Points
+  l=Line3(v1,v2);
+  BOOST_CHECK(Normalize(v2-v1)==l.GetDirection());
 
-BOOST_AUTO_TEST_CASE(line_init3)
+  //------------- Plane --------------
+  Plane p;
+  BOOST_CHECK(match(p.GetOrigin(),0.0,0.0,0.0));
+  BOOST_CHECK(match(p.GetNormal(),0.0,0.0,1.0));
+  BOOST_CHECK(p.GetP()==0.0);
+  
+  
+  p=Plane(v1,v2,v3);
+  BOOST_CHECK(dequal(Length(p.GetNormal()), 1.0));
+  BOOST_CHECK(IsInPlane(p, p.GetOrigin()));
+  BOOST_CHECK(IsInPlane(p, v1));
+  BOOST_CHECK(IsInPlane(p, v2));
+  BOOST_CHECK(IsInPlane(p, v3));
+  BOOST_CHECK(std::fabs(Dot(v2-v1,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(v3-v1,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(v3-v2,p.GetNormal()))<EPSILON);
+
+  BOOST_CHECK(std::fabs(Dot(v1-p.GetOrigin(),p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(v2-p.GetOrigin(),p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(v3-p.GetOrigin(),p.GetNormal()))<EPSILON);
+  
+  //initialize based on a point and a normal
+  p=Plane(v1,v1);
+  BOOST_CHECK(v1==p.GetOrigin());
+  BOOST_CHECK(v1/Length(v1)==p.GetNormal());
+  
+  // initialize based on a line and point
+  p=Plane(Line3(v1,v2),v3);
+  BOOST_CHECK(std::fabs(Dot(v2-v1,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(v3-v1,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(v3-v2,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(p.GetOrigin()-v1,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(p.GetOrigin()-v2,p.GetNormal()))<EPSILON);
+  BOOST_CHECK(std::fabs(Dot(p.GetOrigin()-v3,p.GetNormal()))<EPSILON);
+  
+  // initialize a,b,c,d (ax+by+cz+d=0)
+  Real a=UniformRandom();
+  Real b=UniformRandom();
+  Real c=UniformRandom();
+  Real d=UniformRandom();
+  p=Plane(a,b,c,d);
+  BOOST_CHECK(std::fabs(d/Length(Vec3(a,b,c))+Dot(p.GetNormal(),p.GetOrigin()))<EPSILON);
+  BOOST_CHECK(Length(Normalize(Vec3(a,b,c))-p.GetNormal())<EPSILON);
+  
+  
+  //initialize based x-,y-,z- intercepts
+  p=Plane(a,b,c);
+  Plane p2(Vec3(a,0.0,0.0),Vec3(0.0,b,0.0),Vec3(0.0,0.0,c));
+  BOOST_CHECK(Length(p.GetOrigin()-p2.GetOrigin())<EPSILON);
+  BOOST_CHECK(Length(p.GetNormal()-p2.GetNormal())<EPSILON);
+  
+}
+
+BOOST_AUTO_TEST_CASE(operators_composite3)
 {
-  Line3 line(geom::Vec3(0,0,0), geom::Vec3(2,0,0));
-  BOOST_CHECK_EQUAL(geom::Length(line.GetDirection()), 1.0);
+  Vec3 v1(2,3,4);
+  Vec3 v2(4,3,2);
+  Line3 l(v1,v2);
+  Line3 l2(v1,v2);
+  BOOST_CHECK(l==l2);
+  
+  Plane p(v1,v2);
+  Plane p2(v1,v2);
+  BOOST_CHECK(p==p2);
+  
 }
 
-BOOST_AUTO_TEST_CASE(is_on_line3)
+BOOST_AUTO_TEST_CASE(func_composite3)
 {
-  Line3 line(geom::Vec3(0,0,0), geom::Vec3(1,0,0));
-  BOOST_CHECK(IsOnLine(line, geom::Vec3(0.5,0.0,0.0)));
-  BOOST_CHECK(IsOnLine(line, geom::Vec3(1.0,0.0,0.0)));
-  BOOST_CHECK(IsOnLine(line, geom::Vec3(0.0,0.0,0.0)));
-  BOOST_CHECK(IsOnLine(line, geom::Vec3(-5,0.0,0.0)));
-  BOOST_CHECK(IsOnLine(line, geom::Vec3(10.0,0.0,0.0)));
-  BOOST_CHECK(!IsOnLine(line, geom::Vec3(0.5,0.1,0.0)));
-  BOOST_CHECK(!IsOnLine(line, geom::Vec3(1.0,0.0,0.1)));
-  
-  line=Line3(geom::Vec3(1,0,0), geom::Vec3(1,1,1));
-  for (int i=-10; i<10; ++i) {
-    BOOST_CHECK(IsOnLine(line, line.At(i)));
-  }
-  BOOST_CHECK(!IsOnLine(line, geom::Vec3(1,2,2.1)));
+  Vec3 v1(2,2,0);
+  Vec3 v2(2,2,2);
+  Vec3 v3(3,3,3);
+  Vec3 v4(1,3,3);
+
+  Plane p1(v1,v2);  
+  Plane p2(v3,v4);
+  Plane p3(v1,v2,v3);
+  Plane p4(v1,v2,v4);
+  Line3 l1(v1,v2);
+  Line3 l2(v3,v4);
+  Line3 l3(v1,v3);
+  Line3 l4(v1+Vec3(2.0,2.0,2.0),v3+Vec3(2.0,2.0,2.0));
+  
+  Vec3 tmp1=v2-v1;
+  Vec3 tmp2=v4-v3;
+  Real ang=std::fabs(acos(Dot(tmp1,tmp2)/Length(tmp1)/Length(tmp2)));
+  
+  // angle between two lines
+  BOOST_CHECK(dequal(Angle(l1,l2), ang));
+
+  // angle between two planes
+  BOOST_CHECK(dequal(std::fabs(acos(Dot(Normalize(v2),Normalize(v4)))),Angle(p1,p2)));
+  
+  // angle between line and plane
+  BOOST_CHECK(dequal(M_PI/2.0-std::fabs(acos(Dot(Normalize(v2),
+                                                 Normalize(tmp2)))),
+                                              Angle(p1,l2)));
+
+  BOOST_CHECK(Equal(IntersectionPoint(l2,l3), v3));
+  
+  BOOST_CHECK(!AreIntersecting(l3, l4));
+  
+  BOOST_CHECK_THROW(IntersectionPoint(l3,l4), GeomException);
+  BOOST_CHECK(Equal(IntersectionPoint(p1,l3), v1));
+  BOOST_CHECK(Equal(IntersectionPoint(l3,p1), v1));
+  
+  BOOST_CHECK(EqualPosition(IntersectionLine(p3,p4),l1));
+
+  Real d=Length(Dot(v3-v2,l1.GetDirection())*l1.GetDirection()-(v3-v2));
+  BOOST_CHECK(dequal(Distance(l1,v3),d));
+  
+  BOOST_CHECK(dequal(Distance(p1,v3),Dot(p1.GetNormal(),v3)+p1.GetP()));
+
+
+  BOOST_CHECK(!Equal(l1,Line3(l1.GetOrigin()+2.0*l1.GetDirection(),
+                              l1.GetOrigin()+3.0*l1.GetDirection())));
+  BOOST_CHECK(EqualPosition(l1,Line3(l1.GetOrigin()+2.0*l1.GetDirection(),
+                                     l1.GetOrigin()-3.0*l1.GetDirection())));
+
+  BOOST_CHECK(EqualPosition(l1,Line3(l1.GetOrigin()-2.0*l1.GetDirection(),
+                                    l1.GetOrigin()+3.0*l1.GetDirection())));
+  BOOST_CHECK(Equal(p3,Plane(v1,p3.GetNormal())));
+  BOOST_CHECK(Equal(p3,Plane(v2,p3.GetNormal())));
+
+  BOOST_CHECK(EqualPosition(p3,Plane(p3.GetOrigin(),-p3.GetNormal())));
+  
+  BOOST_CHECK(AreParallel(l1,l2)==false);
+  BOOST_CHECK(AreParallel(l1,Line3(v1+Vec3(2.0,0,0),v2+Vec3(2.0,0,0)))==true);
+  BOOST_CHECK(AreParallel(p1,p2)==false);
+  BOOST_CHECK(AreParallel(p1, Plane(v3, p1.GetNormal()))==true);
+
+
+  BOOST_CHECK(IsOnLine(l1,v1));
+  BOOST_CHECK(IsOnLine(l1,v2));
+  BOOST_CHECK(IsInPlane(p3,v1));
+  BOOST_CHECK(!IsInPlane(p3,v4));
+  BOOST_CHECK(IsInPlane(p3,l1));
+
+  BOOST_CHECK(AreIntersecting(l1, l3));
+  BOOST_CHECK(!AreIntersecting(l1, l2));
+
+  BOOST_CHECK(RelativePosition(p3, v1)==0);
+  BOOST_CHECK(RelativePosition(p3, v4)==-1);
+
 }
 
-BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_mat2.cc b/modules/geom/tests/test_mat2.cc
new file mode 100644
index 000000000..af119e965
--- /dev/null
+++ b/modules/geom/tests/test_mat2.cc
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+
+BOOST_AUTO_TEST_CASE(init_mat2)
+{
+  // default
+  Mat2 m1;
+  BOOST_CHECK(match(m1,1.0,0.0, 0.0,1.0));
+
+  //with values
+  Mat2 m2(1.1,2.2,3.3,4.4);
+  BOOST_CHECK(match(m2,1.1,2.2,3.3,4.4));
+
+  // copy ctor
+  Mat2 m3(m2);
+  BOOST_CHECK(match(m3,1.1,2.2,3.3,4.4));
+
+  // array
+  Real arr[]={9.9,8.8,7.7,6.6};
+  Mat2 m4(arr);
+  BOOST_CHECK(match(m4,arr[0],arr[1],arr[2],arr[3]));
+
+  // assignement op
+  m1=m4;
+  BOOST_CHECK(match(m1,m4(0,0),m4(0,1),m4(1,0),m4(1,1)));
+}
+
+
+
+BOOST_AUTO_TEST_CASE(access_mat2)
+{
+  Mat2 m;
+  BOOST_CHECK_THROW( m(2,2)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(2,2), std::out_of_range);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
diff --git a/modules/geom/tests/test_mat3.cc b/modules/geom/tests/test_mat3.cc
new file mode 100644
index 000000000..742ba05ed
--- /dev/null
+++ b/modules/geom/tests/test_mat3.cc
@@ -0,0 +1,92 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+BOOST_AUTO_TEST_CASE(init_mat3)
+{
+  // default
+  Mat3 m1;
+  BOOST_CHECK(match(m1,1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0));
+
+  //with values
+  Mat3 m2(1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9);
+  BOOST_CHECK(match(m2,1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9));
+
+  // copy ctor
+  Mat3 m3(m2);
+  BOOST_CHECK(match(m3,1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9));
+
+  // array
+  Real arr[]={9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1};
+  Mat3 m4(arr);
+  BOOST_CHECK(match(m4,arr[0],arr[1],arr[2],arr[3],arr[4],arr[5],arr[6],arr[7],arr[8]));
+
+  // assignement op
+  m1=m4;
+  BOOST_CHECK(match(m1,m4(0,0),m4(0,1),m4(0,2),m4(1,0),m4(1,1),m4(1,2),m4(2,0),m4(2,1),m4(2,2)));
+
+  Mat3 m5(Mat2(2.0,3.0,4.0,5.0));
+  BOOST_CHECK(match(m5,2.0,3.0,0.0,4.0,5.0,0.0,0.0,0.0,1.0));
+}
+
+BOOST_AUTO_TEST_CASE(access_mat3)
+{
+  Mat3 m;
+  BOOST_CHECK_THROW( m(3,3)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(3,0)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(0,3)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(3,3), std::out_of_range);
+  BOOST_CHECK_THROW( m(3,0), std::out_of_range);
+  BOOST_CHECK_THROW( m(0,3), std::out_of_range);
+}
+
+
+BOOST_AUTO_TEST_CASE(mult_mat3)
+{
+  Mat3 m1=rnd_mat3();
+  Mat3 m2=rnd_mat3();
+  Mat3 m3=m1*m2;
+  Mat3 m4;
+  for(int ir=0;ir<3;++ir) {
+    for(int ic=0;ic<3;++ic) {
+      double tmp=0.0;
+      for(int tt=0;tt<3;++tt) {
+        tmp+=m1(ir,tt)*m2(tt,ic);
+      }
+      m4(ir,ic)=tmp;
+    }
+  }
+  BOOST_CHECK(Equal(m3,m4));
+
+  m4=rnd_mat3();
+  Mat3 m5=m2*m4;
+
+  BOOST_CHECK(Equal(m1*m5,m3*m4));  
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
diff --git a/modules/geom/tests/test_mat4.cc b/modules/geom/tests/test_mat4.cc
new file mode 100644
index 000000000..343a68ffe
--- /dev/null
+++ b/modules/geom/tests/test_mat4.cc
@@ -0,0 +1,104 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+BOOST_AUTO_TEST_CASE(init_mat4)
+{
+  // default
+  Mat4 m1;
+  BOOST_CHECK(match(m1,
+        1.0,0.0,0.0,0.0, 
+        0.0,1.0,0.0,0.0,
+        0.0,0.0,1.0,0.0,
+        0.0,0.0,0.0,1.0));
+
+  //with values
+  Mat4 m2(1.1,2.2,3.3,4.4,
+    5.5,6.6,7.7,8.8,
+    9.9,1.1,2.2,3.3,
+    4.4,5.5,6.6,7.7);
+  BOOST_CHECK(match(m2,
+        1.1,2.2,3.3,4.4,
+        5.5,6.6,7.7,8.8,
+        9.9,1.1,2.2,3.3,
+        4.4,5.5,6.6,7.7));
+
+  // copy ctor
+  Mat4 m3(m2);
+  BOOST_CHECK(match(m2,
+        1.1,2.2,3.3,4.4,
+        5.5,6.6,7.7,8.8,
+        9.9,1.1,2.2,3.3,
+        4.4,5.5,6.6,7.7));
+
+  // array
+  double arr[]={9.9,8.8,7.7,6.6,5.5,4.4,3.3,2.2,1.1,9.9,8.8,7.7,6.6,5.5,4.4,3.3};
+  Mat4 m4(arr);
+  BOOST_CHECK(match(m4,
+        arr[0],arr[1],arr[2],arr[3],
+        arr[4],arr[5],arr[6],arr[7],
+        arr[8],arr[9],arr[10],arr[11],
+        arr[12],arr[13],arr[14],arr[15]));
+
+  // assignement op
+  m1=m4;
+  BOOST_CHECK(match(m1,
+        m4(0,0),m4(0,1),m4(0,2),m4(0,3),
+        m4(1,0),m4(1,1),m4(1,2),m4(1,3),
+        m4(2,0),m4(2,1),m4(2,2),m4(2,3),
+        m4(3,0),m4(3,1),m4(3,2),m4(3,3)));
+
+  // conversion
+  Mat4 m5(Mat2(9.0,8.0,7.0,6.0));
+  BOOST_CHECK(match(m5,
+        9.0,8.0,0.0,0.0,
+        7.0,6.0,0.0,0.0,
+        0.0,0.0,1.0,0.0,
+        0.0,0.0,0.0,1.0));
+
+  Mat4 m6(Mat3(1.0,2.0,3.0, 4.0,5.0,6.0, 7.0,8.0,9.0));
+  BOOST_CHECK(match(m6,
+        1.0,2.0,3.0,0.0,
+        4.0,5.0,6.0,0.0,
+        7.0,8.0,9.0,0.0,
+        0.0,0.0,0.0,1.0));
+        
+}
+
+BOOST_AUTO_TEST_CASE(access_mat4)
+{
+  Mat4 m;
+  BOOST_CHECK_THROW( m(4,4)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(4,0)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(0,4)=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( m(4,4), std::out_of_range);
+  BOOST_CHECK_THROW( m(4,0), std::out_of_range);
+  BOOST_CHECK_THROW( m(0,4), std::out_of_range);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_op2.cc b/modules/geom/tests/test_op2.cc
new file mode 100644
index 000000000..62774a650
--- /dev/null
+++ b/modules/geom/tests/test_op2.cc
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+BOOST_AUTO_TEST_CASE(vecmat_mult2)
+{
+  Vec2 v1(1.0,2.0);
+  Mat2 m(1.0,2.0, 
+         3.0,4.0);
+
+  BOOST_CHECK(match(v1*m,7.0,10.0));
+  BOOST_CHECK(match(m*v1,5.0,11.0));
+
+  Vec2 v2(5.0,6.0);
+  BOOST_CHECK(match(CompMultiply(v1,v2),5.0,12.0));
+  BOOST_CHECK(match(CompDivide(v2,v1),5.0,3.0));
+
+  Mat2 m1=rnd_mat2();
+  Mat2 m2=rnd_mat2();
+  Mat2 m3=m1*m2;
+  Vec2 v3=v2*m1;
+  BOOST_CHECK(Equal(v3*m2,v2*m3));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_op3.cc b/modules/geom/tests/test_op3.cc
new file mode 100644
index 000000000..9672ff46a
--- /dev/null
+++ b/modules/geom/tests/test_op3.cc
@@ -0,0 +1,51 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+BOOST_AUTO_TEST_CASE(vecmat_mult3)
+{
+  Vec3 v1(1.0,2.0,3.0);
+  Mat3 m(1.0,2.0,3.0, 
+         4.0,5.0,6.0, 
+         7.0,8.0,9.0);
+
+  BOOST_CHECK(match(v1*m,30.0,36.0,42.0));
+  BOOST_CHECK(match(m*v1,14.0,32.0,50.0));
+
+  Vec3 v2(7.0,8.0,9.0);
+  BOOST_CHECK(match(CompMultiply(v1,v2),7.0,16.0,27.0));
+  BOOST_CHECK(match(CompDivide(v2,v1),7.0,4.0,3.0));
+
+  Mat3 m1=m;
+  Mat3 m2(-4,0,1,0,8,-10,8,3,0);
+  Mat3 m3=m1*m2;
+  Vec3 v3=v2*m1;
+  BOOST_CHECK(Equal(v3*m2,v2*m3));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_op4.cc b/modules/geom/tests/test_op4.cc
new file mode 100644
index 000000000..19eaaaa12
--- /dev/null
+++ b/modules/geom/tests/test_op4.cc
@@ -0,0 +1,46 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+BOOST_AUTO_TEST_CASE(vecmat_mult4)
+{
+  Vec4 v1(5.0,4.0,3.0,2.0);
+  Mat4 m(0.5,1.0,1.5,2.0, 
+	 2.5,3.0,3.5,4.0,
+	 4.5,5.0,5.5,6.0,
+	 6.5,7.0,7.5,8.0);
+
+  BOOST_CHECK(match(v1*m,39.0,46.0,53.0,60.0));
+  BOOST_CHECK(match(m*v1,15.0,43.0,71.0,99.0));
+
+  Vec4 v2(10.0,12.0,9.0,4.0);
+  BOOST_CHECK(match(CompMultiply(v1,v2),50.0,48.0,27.0,8.0));
+  BOOST_CHECK(match(CompDivide(v2,v1),2.0,3.0,3.0,2.0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_vec2.cc b/modules/geom/tests/test_vec2.cc
new file mode 100644
index 000000000..77ec6f0b5
--- /dev/null
+++ b/modules/geom/tests/test_vec2.cc
@@ -0,0 +1,110 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+  
+BOOST_AUTO_TEST_CASE(init_vec2)
+{
+  // default
+  Vec2 v1;
+  BOOST_CHECK(match(v1,0.0,0.0));
+
+  //with values
+  Vec2 v2(1.5,2.3);
+  BOOST_CHECK(match(v2,1.5,2.3));
+
+  // copy ctor
+  Vec2 v3(v2);
+  BOOST_CHECK(match(v3,1.5,2.3));
+
+  // array
+  double arr[]={6.5,4.3};
+  Vec2 v4(arr);
+  BOOST_CHECK(match(v4,arr[0],arr[1]));
+
+  // assignement op
+  v1=v4;
+  BOOST_CHECK(match(v1,v4[0],v4[1]));
+
+  // conversion from vec3
+  Vec2 v5(Vec3(1.2,2.8,1.5));
+  BOOST_CHECK(match(v5,1.2,2.8));
+
+  // conversion from vec4
+  Vec2 v6(Vec4(0.5,2.0,4.0,2.0));
+  BOOST_CHECK(match(v6, 0.25, 1.0));
+  BOOST_CHECK_THROW( Vec2(Vec4(1.0,1.0,1.0,0.0)), DivideByZeroException);
+}
+
+BOOST_AUTO_TEST_CASE(access_vec2)
+{
+  Vec2 v;
+  v[0]=1.1;
+  v[1]=2.3;
+  BOOST_CHECK(match(v,1.1,2.3));
+  BOOST_CHECK_NO_THROW( v[0]=1.0);
+  BOOST_CHECK_THROW( v[2]=1.0, std::out_of_range);
+}
+
+BOOST_AUTO_TEST_CASE(operators_vec2)
+{
+  Vec2 v1(1.2,2.3);
+  Vec2 v2(1.2,2.3);
+  Vec2 v3(0.1,0.2);
+
+  // equality
+  BOOST_CHECK(v1==v2);
+  BOOST_CHECK(v1!=v3);
+
+  // additive
+  v2=v1+v3;
+  BOOST_CHECK(match(v2,1.3,2.5));
+  v2=v1-v3;
+  BOOST_CHECK(match(v2,1.1,2.1));
+
+  // multipliable with scalar
+  v2=v1*2.0;
+  BOOST_CHECK(match(v2,2.4,4.6));
+  
+  // dividable with scalar
+  v2=v1/2.0;
+  BOOST_CHECK(match(v2,0.6,1.15));
+
+  // negative
+  v2=-v1;
+  BOOST_CHECK(match(v2,-1.2,-2.3));
+
+  // reciprocal
+  v2=1.0/v1;
+  BOOST_CHECK(match(v2,1.0/1.2,1.0/2.3));
+
+  // chaining
+  v2=-(3.0*v3-v1/2.0);
+  BOOST_CHECK(match(v2,0.3,0.55));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_vec3.cc b/modules/geom/tests/test_vec3.cc
new file mode 100644
index 000000000..a02bc8c5b
--- /dev/null
+++ b/modules/geom/tests/test_vec3.cc
@@ -0,0 +1,127 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+  
+BOOST_AUTO_TEST_CASE(init_vec3)
+{
+  // default
+  Vec3 v1;
+  BOOST_CHECK(match(v1,0.0,0.0,0.0));
+
+  //with values
+  Vec3 v2(1.5,2.3,4.5);
+  BOOST_CHECK(match(v2,1.5,2.3,4.5));
+
+  // copy ctor
+  Vec3 v3(v2);
+  BOOST_CHECK(match(v3,1.5,2.3,4.5));
+
+  // array
+  double arr[]={6.5,4.3,2.1};
+  Vec3 v4(arr);
+  BOOST_CHECK(match(v4,arr[0],arr[1],arr[2]));
+
+  // assignement op
+  v1=v4;
+  BOOST_CHECK(match(v1,v4[0],v4[1],v4[2]));
+  
+  // conversion from vec2
+  Vec3 v5(Vec2(2.8,1.5));
+  BOOST_CHECK(match(v5,2.8,1.5,0.0));
+
+  // conversion from vec4
+  Vec3 v6(Vec4(0.4,1.2,4.0,2.0));
+  BOOST_CHECK(match(v6,0.2,0.6,2.0));
+  BOOST_CHECK_THROW( Vec3(Vec4(1.0,1.0,1.0,0.0)), DivideByZeroException);
+
+}
+
+BOOST_AUTO_TEST_CASE(access_vec3)
+{
+  Vec3 v;
+  v[0]=1.1;
+  v[1]=2.3;
+  v[2]=5.6;
+  BOOST_CHECK(match(v,1.1,2.3,5.6));
+
+  BOOST_CHECK_NO_THROW(v[0]=1);
+  BOOST_CHECK_NO_THROW(v[1]=1);
+  BOOST_CHECK_NO_THROW(v[2]=1);
+  BOOST_CHECK_NO_THROW(v[0]);
+  BOOST_CHECK_NO_THROW(v[1]);
+  BOOST_CHECK_NO_THROW(v[2]);
+  BOOST_CHECK_THROW( v[3]=1.0, std::out_of_range);
+  BOOST_CHECK_THROW( v[3], std::out_of_range);
+}
+
+BOOST_AUTO_TEST_CASE(operators_vec3) 
+{
+  Vec3 v1(1.2,2.3,3.4);
+  Vec3 v2(1.2,2.3,3.4);
+  Vec3 v3(0.1,0.2,0.3);
+
+  // equality
+  BOOST_CHECK(v1==v2);
+  BOOST_CHECK(v1!=v3);
+
+  // additive
+  v2=v1+v3;
+  BOOST_CHECK(match(v2,1.3,2.5,3.7));
+  v2=v1-v3;
+  BOOST_CHECK(match(v2,1.1,2.1,3.1));
+
+  // multipliable with scalar
+  v2=v1*2.0;
+  BOOST_CHECK(match(v2,2.4,4.6,6.8));
+  
+  // dividable with scalar
+  v2=v1/2.0;
+  BOOST_CHECK(match(v2,0.6,1.15,1.7));
+
+  // negative
+  v2=-v1;
+  BOOST_CHECK(match(v2,-1.2,-2.3,-3.4));
+
+  // reciprocal
+  v2=1.0/v1;
+  BOOST_CHECK(match(v2,1.0/1.2,1.0/2.3,1.0/3.4));
+  
+  // chaining
+  v2=-(3.0*v3-v1/2.0);
+  BOOST_CHECK(match(v2,0.3,0.55,0.8));
+
+  // dot
+  double result=Dot(v1,v3);
+  BOOST_CHECK(dequal(result, 0.12+0.46+1.02));
+
+  // cross
+  v2=Cross(v1,v3);
+  BOOST_CHECK(match(v2,0.01,-0.02,0.01));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/geom/tests/test_vec4.cc b/modules/geom/tests/test_vec4.cc
new file mode 100644
index 000000000..c0f0163d3
--- /dev/null
+++ b/modules/geom/tests/test_vec4.cc
@@ -0,0 +1,112 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/geom/geom.hh>
+
+#include "helper.hh"
+using namespace geom;
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE( geom )
+
+BOOST_AUTO_TEST_CASE(init_vec4)
+{
+  // default
+  Vec4 v1;
+  BOOST_CHECK(match(v1,0.0,0.0,0.0,1.0));
+
+  //with values
+  Vec4 v2(5.9,1.5,2.3,4.5);
+  BOOST_CHECK(match(v2,5.9,1.5,2.3,4.5));
+
+  // copy ctor
+  Vec4 v3(v2);
+  BOOST_CHECK(match(v3,5.9,1.5,2.3,4.5));
+
+  // array
+  double arr[]={3.3,6.5,4.3,2.1};
+  Vec4 v4(arr);
+  BOOST_CHECK(match(v4,arr[0],arr[1],arr[2],arr[3]));
+
+  // assignement op
+  v1=v4;
+  BOOST_CHECK(match(v1,v4[0],v4[1],v4[2],v4[3]));
+
+  // conversion from vec2
+  Vec4 v5(Vec2(2.8,1.5));
+  BOOST_CHECK(match(v5,2.8,1.5,0.0,1.0));
+
+  // conversion from vec4
+  Vec4 v6(Vec3(0.4,1.2,4.0));
+  BOOST_CHECK(match(v6,0.4,1.2,4.0,1.0));
+}
+
+
+BOOST_AUTO_TEST_CASE(access_vec4)
+{
+  Vec4 v;
+  v[0]=1.1;
+  v[1]=2.3;
+  v[2]=5.6;
+  v[3]=2.0;
+  BOOST_CHECK(match(v,1.1,2.3,5.6,2.0));
+
+  BOOST_CHECK_THROW( v[4]=1.0, std::out_of_range);
+}
+
+BOOST_AUTO_TEST_CASE(operators_vec4)
+{
+  Vec4 v1(0.8,1.2,2.3,3.4);
+  Vec4 v2(0.8,1.2,2.3,3.4);
+  Vec4 v3(0.2,0.1,0.2,0.3);
+
+  // equality
+  BOOST_CHECK(v1==v2);
+  BOOST_CHECK(v1!=v3);
+
+  // additive
+  v2=v1+v3;
+  BOOST_CHECK(match(v2,1.0,1.3,2.5,3.7));
+  v2=v1-v3;
+  BOOST_CHECK(match(v2,0.6,1.1,2.1,3.1));
+
+  // multipliable with scalar
+  v2=v1*2.0;
+  BOOST_CHECK(match(v2,1.6,2.4,4.6,6.8));
+  
+  // dividable with scalar
+  v2=v1/2.0;
+  BOOST_CHECK(match(v2,0.4,0.6,1.15,1.7));
+
+  // negative
+  v2=-v1;
+  BOOST_CHECK(match(v2,-0.8,-1.2,-2.3,-3.4));
+
+  // reciprocal
+  v2=1.0/v1;
+  BOOST_CHECK(match(v2,1.0/0.8,1.0/1.2,1.0/2.3,1.0/3.4));
+
+  // chaining
+  v2=-(3.0*v3-v1/2.0);
+  BOOST_CHECK(match(v2,-0.2,0.3,0.55,0.8));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/gui/src/tools/map_tool.cc b/modules/gui/src/tools/map_tool.cc
index d5f9dac59..e16895621 100644
--- a/modules/gui/src/tools/map_tool.cc
+++ b/modules/gui/src/tools/map_tool.cc
@@ -78,7 +78,7 @@ void MapTool::MouseMove(const MouseEvent& event)
               geom::Vec3 trans(event.GetDelta().x()*fxy[0],
                                -event.GetDelta().y()*fxy[1],
                                0.0);
-              plane.SetOrigin(plane.GetOrigin()+geom::Transpose(tf.GetRot())*trans);
+              plane.SetP(plane.GetP()-geom::Dot(plane.GetNormal(), geom::Transpose(tf.GetRot())*trans));
               ms->SetPlane(plane);
             } else {
               plane.SetNormal(tf.GetXAxisRotation(static_cast<Real>(event.GetDelta().y())*0.5)*tf.GetYAxisRotation(static_cast<Real>(event.GetDelta().x())*0.5)*plane.GetNormal());
-- 
GitLab