diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in
index c0bf72cf2393804e78933418e9630eb97691c6f8..014864e614694ee7ddb8e26aeff38eb29f733032 100644
--- a/Documentation/Doxyfile.in
+++ b/Documentation/Doxyfile.in
@@ -692,7 +692,7 @@ LAYOUT_FILE            = ${CMAKE_SOURCE_DIR}/Documentation/DoxygenLayout.xml
 # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
 # search path. See also \cite for info how to create references.
 
-CITE_BIB_FILES         =
+CITE_BIB_FILES         = ${PROJECT_SOURCE_DIR}/Documentation/bibliography
 
 #---------------------------------------------------------------------------
 # Configuration options related to warning and progress messages
diff --git a/Documentation/bibliography.bib b/Documentation/bibliography.bib
new file mode 100644
index 0000000000000000000000000000000000000000..04937bd17cafe59709369cb090be8951688419d3
--- /dev/null
+++ b/Documentation/bibliography.bib
@@ -0,0 +1,8 @@
+@book{Ericson:2004:RCD:1121584,
+ author = {Ericson, Christer},
+ title = {Real-Time Collision Detection (The Morgan Kaufmann Series in Interactive 3-D Technology) (The Morgan Kaufmann Series in Interactive 3D Technology)},
+ year = {2004},
+ isbn = {1558607323},
+ publisher = {Morgan Kaufmann Publishers Inc.},
+ address = {San Francisco, CA, USA},
+}
\ No newline at end of file
diff --git a/GeoLib/AnalyticalGeometry-impl.h b/GeoLib/AnalyticalGeometry-impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..3049da7e00a84b7d2eeea43be5ac86b1686d59a1
--- /dev/null
+++ b/GeoLib/AnalyticalGeometry-impl.h
@@ -0,0 +1,142 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+namespace GeoLib
+{
+
+template <class T_POINT>
+void getNewellPlane (const std::vector<T_POINT*>& pnts,
+                     MathLib::Vector3 &plane_normal,
+                     double& d)
+{
+    d = 0;
+    MathLib::Vector3 centroid;
+    std::size_t n_pnts(pnts.size());
+    for (size_t i(n_pnts - 1), j(0); j < n_pnts; i = j, j++) {
+        plane_normal[0] += ((*(pnts[i]))[1] - (*(pnts[j]))[1])
+                           * ((*(pnts[i]))[2] + (*(pnts[j]))[2]); // projection on yz
+        plane_normal[1] += ((*(pnts[i]))[2] - (*(pnts[j]))[2])
+                           * ((*(pnts[i]))[0] + (*(pnts[j]))[0]); // projection on xz
+        plane_normal[2] += ((*(pnts[i]))[0] - (*(pnts[j]))[0])
+                           * ((*(pnts[i]))[1] + (*(pnts[j]))[1]); // projection on xy
+
+        centroid += *(pnts[j]);
+    }
+
+    plane_normal.normalize();
+    d = MathLib::scalarProduct(centroid, plane_normal) / n_pnts;
+}
+
+template<class T_MATRIX>
+void compute2DRotationMatrixToX(MathLib::Vector3 const& v,
+        T_MATRIX & rot_mat)
+{
+    const double cos_theta = v[0];
+    const double sin_theta = v[1];
+    rot_mat(0,0) = rot_mat(1,1) = cos_theta;
+    rot_mat(0,1) = sin_theta;
+    rot_mat(1,0) = -sin_theta;
+    rot_mat(0,2) = rot_mat(1,2) = rot_mat(2,0) = rot_mat(2,1) = 0.0;
+    rot_mat(2,2) = 1.0;
+}
+
+template <class T_MATRIX>
+void compute3DRotationMatrixToX(MathLib::Vector3  const& v,
+        T_MATRIX & rot_mat)
+{
+    // a vector on the plane
+    MathLib::Vector3 yy(0, 0, 0);
+    if (std::abs(v[0]) > 0.0 && std::abs(v[1]) + std::abs(v[2]) < std::numeric_limits<double>::epsilon()) {
+        yy[2] = 1.0;
+    } else if (std::abs(v[1]) > 0.0 && std::abs(v[0]) + std::abs(v[2]) < std::numeric_limits<double>::epsilon()) {
+        yy[0] = 1.0;
+    } else if (std::abs(v[2]) > 0.0 && std::abs(v[0]) + std::abs(v[1]) < std::numeric_limits<double>::epsilon()) {
+        yy[1] = 1.0;
+    } else {
+        for (unsigned i = 0; i < 3; i++) {
+            if (std::abs(v[i]) > 0.0) {
+                yy[i] = -v[i];
+                break;
+            }
+        }
+    }
+    // z"_vec
+    MathLib::Vector3 zz(MathLib::crossProduct(v, yy));
+    zz.normalize();
+    // y"_vec
+    yy = MathLib::crossProduct(zz, v);
+    yy.normalize();
+
+    for (unsigned i=0; i<3; ++i) {
+        rot_mat(0, i) = v[i];
+        rot_mat(1, i) = yy[i];
+        rot_mat(2, i) = zz[i];
+    }
+}
+
+template <class T_MATRIX>
+void computeRotationMatrixToXY(MathLib::Vector3 const& n,
+		T_MATRIX & rot_mat)
+{
+	// check if normal points already in the right direction
+	if (sqrt(n[0]*n[0]+n[1]*n[1]) == 0) {
+		rot_mat(0,0) = 1.0;
+		rot_mat(0,1) = 0.0;
+		rot_mat(0,2) = 0.0;
+		rot_mat(1,0) = 0.0;
+		rot_mat(1,1) = 1.0;
+		rot_mat(1,2) = 0.0;
+		rot_mat(2,0) = 0.0;
+		rot_mat(2,1) = 0.0;
+		rot_mat(2,2) = 1.0;
+		return;
+	}
+
+	// sqrt (n_1^2 + n_3^2)
+	double const h0(sqrt(n[0]*n[0]+n[2]*n[2]));
+
+	// In case the x and z components of the normal are both zero the rotation
+	// to the x-z-plane is not required, i.e. only the rotation in the z-axis is
+	// required. The angle is either pi/2 or 3/2*pi. Thus the components of
+	// rot_mat are as follows.
+	if (h0 < std::numeric_limits<double>::epsilon()) {
+		rot_mat(0,0) = 1.0;
+		rot_mat(0,1) = 0.0;
+		rot_mat(0,2) = 0.0;
+		rot_mat(1,0) = 0.0;
+		rot_mat(1,1) = 0.0;
+		if (n[1] > 0)
+			rot_mat(1,2) = -1.0;
+		else
+			rot_mat(1,2) = 1.0;
+		rot_mat(2,0) = 0.0;
+		if (n[1] > 0)
+			rot_mat(2,1) = 1.0;
+		else
+			rot_mat(2,1) = -1.0;
+		rot_mat(2,2) = 0.0;
+		return;
+	}
+
+	double h1(1 / n.getLength());
+
+	// general case: calculate entries of rotation matrix
+	rot_mat(0, 0) = n[2] / h0;
+	rot_mat(0, 1) = 0;
+	rot_mat(0, 2) = - n[0] / h0;
+	rot_mat(1, 0) = - n[1]*n[0]/h0 * h1;
+	rot_mat(1, 1) = h0 * h1;
+	rot_mat(1, 2) = - n[1]*n[2]/h0 * h1;
+	rot_mat(2, 0) = n[0] * h1;
+	rot_mat(2, 1) = n[1] * h1;
+	rot_mat(2, 2) = n[2] * h1;
+}
+
+} // end namespace GeoLib
+
diff --git a/GeoLib/AnalyticalGeometry.cpp b/GeoLib/AnalyticalGeometry.cpp
index d651df8b41aaab8f78dcbfabee6853333f3ac36a..67b5f1d6e0f4f1c3e246110d56efd4fe258203dd 100644
--- a/GeoLib/AnalyticalGeometry.cpp
+++ b/GeoLib/AnalyticalGeometry.cpp
@@ -348,84 +348,6 @@ double calcTetrahedronVolume(MathLib::Point3d const& x1,
 	return std::abs(GeoLib::scalarTriple(ac, ad, ab)) / 6.0;
 }
 
-// NewellPlane from book Real-Time Collision detection p. 494
-void getNewellPlane(const std::vector<GeoLib::Point*>& pnts, MathLib::Vector3 &plane_normal, double& d)
-{
-	d = 0;
-	MathLib::Vector3 centroid;
-	size_t n_pnts(pnts.size());
-	for (size_t i(n_pnts - 1), j(0); j < n_pnts; i = j, j++) {
-		plane_normal[0] += ((*(pnts[i]))[1] - (*(pnts[j]))[1])
-		                   * ((*(pnts[i]))[2] + (*(pnts[j]))[2]); // projection on yz
-		plane_normal[1] += ((*(pnts[i]))[2] - (*(pnts[j]))[2])
-		                   * ((*(pnts[i]))[0] + (*(pnts[j]))[0]); // projection on xz
-		plane_normal[2] += ((*(pnts[i]))[0] - (*(pnts[j]))[0])
-		                   * ((*(pnts[i]))[1] + (*(pnts[j]))[1]); // projection on xy
-
-		centroid += *(pnts[j]);
-	}
-
-	plane_normal *= 1.0 / plane_normal.getLength();
-	d = MathLib::scalarProduct(centroid, plane_normal) / n_pnts;
-}
-
-void computeRotationMatrixToXY(MathLib::Vector3 const& n,
-	MathLib::DenseMatrix<double> & rot_mat)
-{
-	// check if normal points already in the right direction
-	if (sqrt(n[0]*n[0]+n[1]*n[1]) == 0) {
-		rot_mat(0,0) = 1.0;
-		rot_mat(0,1) = 0.0;
-		rot_mat(0,2) = 0.0;
-		rot_mat(1,0) = 0.0;
-		rot_mat(1,1) = 1.0;
-		rot_mat(1,2) = 0.0;
-		rot_mat(2,0) = 0.0;
-		rot_mat(2,1) = 0.0;
-		rot_mat(2,2) = 1.0;
-		return;
-	}
-
-	// sqrt (n_1^2 + n_3^2)
-	double const h0(sqrt(n[0]*n[0]+n[2]*n[2]));
-
-	// In case the x and z components of the normal are both zero the rotation
-	// to the x-z-plane is not required, i.e. only the rotation in the z-axis is
-	// required. The angle is either pi/2 or 3/2*pi. Thus the components of
-	// rot_mat are as follows.
-	if (h0 < std::numeric_limits<double>::epsilon()) {
-		rot_mat(0,0) = 1.0;
-		rot_mat(0,1) = 0.0;
-		rot_mat(0,2) = 0.0;
-		rot_mat(1,0) = 0.0;
-		rot_mat(1,1) = 0.0;
-		if (n[1] > 0)
-			rot_mat(1,2) = -1.0;
-		else
-			rot_mat(1,2) = 1.0;
-		rot_mat(2,0) = 0.0;
-		if (n[1] > 0)
-			rot_mat(2,1) = 1.0;
-		else
-			rot_mat(2,1) = -1.0;
-		rot_mat(2,2) = 0.0;
-		return;
-	}
-
-	double h1(1 / n.getLength());
-
-	// general case: calculate entries of rotation matrix
-	rot_mat(0, 0) = n[2] / h0;
-	rot_mat(0, 1) = 0;
-	rot_mat(0, 2) = - n[0] / h0;
-	rot_mat(1, 0) = - n[1]*n[0]/h0 * h1;
-	rot_mat(1, 1) = h0 * h1;
-	rot_mat(1, 2) = - n[1]*n[2]/h0 * h1;
-	rot_mat(2, 0) = n[0] * h1;
-	rot_mat(2, 1) = n[1] * h1;
-	rot_mat(2, 2) = n[2] * h1;
-}
-
 void computeRotationMatrixToXZ(MathLib::Vector3 const& plane_normal, MathLib::DenseMatrix<double> & rot_mat)
 {
 	// *** some frequently used terms ***
diff --git a/GeoLib/AnalyticalGeometry.h b/GeoLib/AnalyticalGeometry.h
index 1198202138b4b9b7464f52ccb4a3f7814a7f75a8..e07a73b4609a326ac711f3add921e24823d5ef34 100644
--- a/GeoLib/AnalyticalGeometry.h
+++ b/GeoLib/AnalyticalGeometry.h
@@ -55,22 +55,41 @@ Orientation getOrientation (const GeoLib::Point* p0,
 /**
  * compute a supporting plane (represented by plane_normal and the value d) for the polygon
  * Let \f$n\f$ be the plane normal and \f$d\f$ a parameter. Then for all points \f$p \in R^3\f$ of the plane
- * it holds \f$ n \cdot p + d = 0\f$
+ * it holds \f$ n \cdot p + d = 0\f$. The Newell algorithm is described in
+ * \cite Ericson:2004:RCD:1121584 .
  * @param pnts points of a closed polyline describing a polygon
  * @param plane_normal the normal of the plane the polygon is located in
  * @param d parameter from the plane equation
  */
-void getNewellPlane (const std::vector<GeoLib::Point*>& pnts,
+template <class T_POINT>
+void getNewellPlane (const std::vector<T_POINT*>& pnts,
                      MathLib::Vector3 &plane_normal,
                      double& d);
 
+/**
+ * Computes a rotation matrix that rotates the given 2D normal vector parallel to X-axis
+ * @param v        a 2D normal vector to be rotated
+ * @param rot_mat  a 2x2 rotation matrix
+ */
+template<class T_MATRIX>
+void compute2DRotationMatrixToX(MathLib::Vector3 const& v, T_MATRIX & rot_mat);
+
+/**
+ * Computes a rotation matrix that rotates the given 3D normal vector parallel to X-axis
+ * @param v        a 3D normal vector to be rotated
+ * @param rot_mat  a 3x3 rotation matrix
+ */
+template <class T_MATRIX>
+void compute3DRotationMatrixToX(MathLib::Vector3  const& v, T_MATRIX & rot_mat);
+
 /**
  * Method computes the rotation matrix that rotates the given vector parallel to the \f$z\f$ axis.
  * @param plane_normal the (3d) vector that is rotated parallel to the \f$z\f$ axis
  * @param rot_mat 3x3 rotation matrix
  */
+template <class T_MATRIX>
 void computeRotationMatrixToXY(MathLib::Vector3 const& plane_normal,
-                               MathLib::DenseMatrix<double> & rot_mat);
+                               T_MATRIX & rot_mat);
 
 /**
  * Method computes the rotation matrix that rotates the given vector parallel to the \f$y\f$ axis.
@@ -296,4 +315,6 @@ GeoLib::Polygon rotatePolygonToXY(GeoLib::Polygon const& polygon_in,
 
 } // end namespace GeoLib
 
+#include "AnalyticalGeometry-impl.h"
+
 #endif /* ANALYTICAL_GEOMETRY_H_ */
diff --git a/MathLib/LinAlg/Dense/DenseMatrix-impl.h b/MathLib/LinAlg/Dense/DenseMatrix-impl.h
index 131ab32940df82cba0e4d28f2a502bbd71851cfe..6abda2755fb346fe6ef861c4d06f7401c343f35c 100644
--- a/MathLib/LinAlg/Dense/DenseMatrix-impl.h
+++ b/MathLib/LinAlg/Dense/DenseMatrix-impl.h
@@ -219,6 +219,26 @@ DenseMatrix<FP_TYPE, IDX_TYPE>::transpose() const
 	return y;
 }
 
+template<typename FP_TYPE, typename IDX_TYPE>
+void
+DenseMatrix<FP_TYPE, IDX_TYPE>::transposeInPlace()
+{
+	if (_n_rows==_n_cols) { // square matrix
+		for (IDX_TYPE i = 0; i < _n_rows; i++)
+			for (IDX_TYPE j = i+1; j < _n_cols; j++)
+				std::swap(_data[address(i, j)], _data[address(j, i)]);
+	} else { // non-square matrix
+		const DenseMatrix<FP_TYPE, IDX_TYPE> org(*this);
+		std::swap(_n_rows, _n_cols);
+		for (IDX_TYPE i = 0; i < _n_rows; i++) {
+			for (IDX_TYPE j = 0; j < _n_cols; j++) {
+				_data[address(i, j)] = org(j, i);
+			}
+		}
+	}
+
+}
+
 template<typename FP_TYPE, typename IDX_TYPE>
 DenseMatrix<FP_TYPE, IDX_TYPE>*
 DenseMatrix<FP_TYPE, IDX_TYPE>::getSubMatrix(
@@ -285,6 +305,16 @@ DenseMatrix<FP_TYPE, IDX_TYPE>::write (std::ostream &out) const
 	}
 }
 
+template <typename FP_TYPE, typename IDX_TYPE>
+void
+DenseMatrix<FP_TYPE, IDX_TYPE>::setIdentity()
+{
+	(*this) = 0.0;
+	const IDX_TYPE n_square_rows = std::min(_n_rows, _n_cols);
+	for (IDX_TYPE i=0; i<n_square_rows; i++)
+		_data[address(i,i)] = 1.0;
+}
+
 template <typename FP_TYPE, typename IDX_TYPE>
 FP_TYPE
 sqrFrobNrm (const DenseMatrix<FP_TYPE, IDX_TYPE> &mat)
diff --git a/MathLib/LinAlg/Dense/DenseMatrix.h b/MathLib/LinAlg/Dense/DenseMatrix.h
index 6dc6c659a4b7cd138d537c4fd8cfb0048317cc30..a26256876d54370243d873759dbd78dc25d47cf2 100644
--- a/MathLib/LinAlg/Dense/DenseMatrix.h
+++ b/MathLib/LinAlg/Dense/DenseMatrix.h
@@ -57,6 +57,14 @@ public:
        return _data;
    }
 
+   /**
+    * Get all entries, which are stored in an array.
+   */
+   const FP_TYPE *data() const
+   {
+       return _data;
+   }
+
    /**
     * Assignment operator, makes a copy of the internal data of the object.
     * @param rhs The DenseMatrix object to the right side of the assignment symbol.
@@ -109,6 +117,11 @@ public:
     */
    DenseMatrix* transpose() const; // HB & ZC
 
+   /**
+    * transpose the matrix in place
+    */
+   void transposeInPlace();
+
    DenseMatrix* getSubMatrix (IDX_TYPE b_row, IDX_TYPE b_col, IDX_TYPE e_row, IDX_TYPE e_col) const;
 
    /**
@@ -139,6 +152,16 @@ public:
 	 */
 	IDX_TYPE getNCols () const { return _n_cols; }
 
+	/**
+	 * get the number of entries in the matrix
+	 */
+	IDX_TYPE size() const { return _n_rows*_n_cols; }
+
+	/**
+	 * set the identity matrix
+	 */
+	void setIdentity();
+
 protected:
 	/**
 	 * the number of rows
diff --git a/MathLib/Point3d.h b/MathLib/Point3d.h
index 75368621aa822dd8c9df062d82378b795938e4e7..d59fc2ab998c537e6808514599d15bb5c3736945 100644
--- a/MathLib/Point3d.h
+++ b/MathLib/Point3d.h
@@ -42,5 +42,24 @@ bool lessEq(const MathLib::Point3d& p0,
             const MathLib::Point3d& p1,
             double tol = std::numeric_limits<double>::epsilon());
 
+/**
+ * rotation of points
+ * @param mat a rotation matrix
+ * @param p   a point to be transformed
+ * @return a rotated point
+ */
+template <typename MATRIX>
+inline MathLib::Point3d operator*(MATRIX const& mat, MathLib::Point3d const& p)
+{
+    MathLib::Point3d new_p;
+    for (std::size_t i(0); i<3; ++i) {
+        new_p[i] = 0.0;
+        for (std::size_t j(0); j<3; ++j) {
+            new_p[i] += mat(i,j)*p[j];
+        }
+    }
+    return new_p;
+}
+
 #endif /* POINT3D_H_ */
 
diff --git a/MathLib/TemplatePoint.h b/MathLib/TemplatePoint.h
index d6e3f5a4c1cbade978b8eb455a8d82e21ec3788b..1a58d4f2465bfc033ab639e8894ee71c699238de 100644
--- a/MathLib/TemplatePoint.h
+++ b/MathLib/TemplatePoint.h
@@ -78,6 +78,13 @@ public:
 		return _x.data();
 	}
 
+	/** set the coordinates of the point */
+	void setCoords (const T* coords)
+	{
+		for (unsigned i=0; i<DIM; i++)
+			_x[i] = coords[i];
+	}
+
 	/** write point coordinates into stream (used from operator<<)
 	 * \param os a standard output stream
 	 */
diff --git a/MeshLib/CoordinateSystem.cpp b/MeshLib/CoordinateSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..03209a90fed6ec1eef254c322644c2025f934fcb
--- /dev/null
+++ b/MeshLib/CoordinateSystem.cpp
@@ -0,0 +1,34 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "CoordinateSystem.h"
+
+#include "MeshLib/Node.h"
+#include "MeshLib/Elements/Element.h"
+
+namespace MeshLib
+{
+
+CoordinateSystem::CoordinateSystem(const Element &ele)
+{
+    const GeoLib::AABB<MeshLib::Node> aabb(ele.getNodes(),
+        ele.getNodes()+ele.getNNodes());
+    const CoordinateSystem bboxCoordSys(getCoordinateSystem(aabb));
+    if (bboxCoordSys.getDimension() >= ele.getDimension()) {
+        _type = bboxCoordSys.getType();
+    } else { // e.g. zero volume elements
+        if (ele.getDimension()>=1)
+            _type = CoordinateSystemType::X;
+        if (ele.getDimension()>=2)
+            _type |= CoordinateSystemType::Y;
+        if (ele.getDimension()==3)
+            _type |= CoordinateSystemType::Z;
+    }
+}
+
+} // end
diff --git a/MeshLib/CoordinateSystem.h b/MeshLib/CoordinateSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8d7af4747d43b3b09a832ba0fefc54a53dba641
--- /dev/null
+++ b/MeshLib/CoordinateSystem.h
@@ -0,0 +1,100 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#ifndef COORDINATESYSTEMTYPE_H_
+#define COORDINATESYSTEMTYPE_H_
+
+#include <cmath>
+
+#include "GeoLib/AABB.h"
+
+namespace MeshLib
+{
+
+class Element;
+
+/**
+ * \brief Coordinate system type
+ */
+struct CoordinateSystemType
+{
+    enum type
+    {
+        X = 0x01,
+        Y = 0x02,
+        Z = 0x04
+    };
+};
+
+/**
+ * \brief Coordinate systems
+ *
+ *
+ */
+class CoordinateSystem
+{
+public:
+    /// User provided coordinate system
+    explicit CoordinateSystem(unsigned char coord) : _type (coord) {}
+
+    /// Decides for a given element
+    explicit CoordinateSystem(const Element &ele);
+
+    /// Decides a coordinate system from a bounding box
+    template <class T>
+    explicit CoordinateSystem(const GeoLib::AABB<T> &bbox) : _type(getCoordinateSystem(bbox)) {}
+
+    /// get this coordinate type
+    unsigned char getType() const { return _type; }
+
+    /// get dimension size
+    unsigned getDimension() const {
+        if (hasZ())
+            return 3;
+        else if (hasY())
+            return 2;
+        else
+            return 1;
+    }
+
+    /// has X dimension
+    bool hasX() const { return (_type & CoordinateSystemType::type::X); }
+
+    /// has Y dimension
+    bool hasY() const { return (_type & CoordinateSystemType::type::Y); }
+
+    /// has z dimension
+    bool hasZ() const { return (_type & CoordinateSystemType::type::Z); }
+
+private:
+    template <class T>
+    unsigned char getCoordinateSystem(const GeoLib::AABB<T> &bbox) const;
+
+    unsigned char _type;
+};
+
+template <class T>
+unsigned char CoordinateSystem::getCoordinateSystem(const GeoLib::AABB<T> &bbox) const
+{
+    unsigned char coords = 0;
+
+    const T pt_diff = bbox.getMaxPoint() - bbox.getMinPoint();
+
+    if (std::abs(pt_diff[0]) > .0)
+        coords |= CoordinateSystemType::X;
+    if (std::abs(pt_diff[1]) > .0)
+        coords |= CoordinateSystemType::Y;
+    if (std::abs(pt_diff[2]) > .0)
+        coords |= CoordinateSystemType::Z;
+
+    return coords;
+}
+
+} // MeshLib
+
+#endif // COORDINATESYSTEMTYPE_H_
diff --git a/MeshLib/ElementCoordinatesMappingLocal.cpp b/MeshLib/ElementCoordinatesMappingLocal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ccaf5e57ad619b5ad93326bd3fd1e613d8ed716
--- /dev/null
+++ b/MeshLib/ElementCoordinatesMappingLocal.cpp
@@ -0,0 +1,86 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "ElementCoordinatesMappingLocal.h"
+
+#include <limits>
+#include <cassert>
+
+#include "GeoLib/AnalyticalGeometry.h"
+
+#include "MathLib/MathTools.h"
+#include "MeshLib/Node.h"
+
+namespace MeshLib
+{
+
+ElementCoordinatesMappingLocal::ElementCoordinatesMappingLocal(
+    const Element& e,
+    const CoordinateSystem &global_coords)
+: _coords(global_coords), _matR2global(3,3)
+{
+    assert(e.getDimension() <= global_coords.getDimension());
+    for(unsigned i = 0; i < e.getNNodes(); i++)
+        _vec_nodes.push_back(new MeshLib::Node(*(e.getNode(i))));
+
+    getRotationMatrixToGlobal(e, global_coords, _vec_nodes, _matR2global);
+#ifdef OGS_USE_EIGEN
+    rotateToLocal(_matR2global.transpose(), _vec_nodes);
+#else
+    RotationMatrix* m(_matR2global.transpose());
+    rotateToLocal(*m, _vec_nodes);
+    delete m;
+#endif
+}
+
+ElementCoordinatesMappingLocal::~ElementCoordinatesMappingLocal()
+{
+    for (auto p : _vec_nodes) delete p;
+}
+
+void ElementCoordinatesMappingLocal::rotateToLocal(
+    const RotationMatrix &matR2local,
+    std::vector<MeshLib::Node*> &vec_nodes) const
+{
+    for (MeshLib::Node* node : vec_nodes)
+        node->setCoords((matR2local*static_cast<MathLib::Point3d>(*node)).getCoords());
+}
+
+void ElementCoordinatesMappingLocal::getRotationMatrixToGlobal(
+    const Element &e,
+    const CoordinateSystem &global_coords,
+    const std::vector<MeshLib::Node*> &vec_nodes,
+    RotationMatrix &matR) const
+{
+    const std::size_t global_dim = global_coords.getDimension();
+
+    // compute R in x=R*x' where x are original coordinates and x' are local coordinates
+    if (global_dim == e.getDimension()) {
+        matR.setIdentity();
+    } else if (e.getDimension() == 1) {
+        MathLib::Vector3 xx(*vec_nodes[0], *vec_nodes[1]);
+        xx.normalize();
+        if (global_dim == 2)
+            GeoLib::compute2DRotationMatrixToX(xx, matR);
+        else
+            GeoLib::compute3DRotationMatrixToX(xx, matR);
+        matR.transposeInPlace();
+    } else if (global_dim == 3 && e.getDimension() == 2) {
+        // get plane normal
+        MathLib::Vector3 plane_normal;
+        double d;
+        GeoLib::getNewellPlane (vec_nodes, plane_normal, d);
+        // compute a rotation matrix to XY
+        GeoLib::computeRotationMatrixToXY(plane_normal, matR);
+        // set a transposed matrix
+        matR.transposeInPlace();
+    }
+
+}
+
+} // MeshLib
diff --git a/MeshLib/ElementCoordinatesMappingLocal.h b/MeshLib/ElementCoordinatesMappingLocal.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a46788363ec78c2c5df40eb57b3a3600e4984d2
--- /dev/null
+++ b/MeshLib/ElementCoordinatesMappingLocal.h
@@ -0,0 +1,79 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#ifndef ELEMENTCOORDINATESMAPPINGLOCAL_H_
+#define ELEMENTCOORDINATESMAPPINGLOCAL_H_
+
+#include <vector>
+
+#ifdef OGS_USE_EIGEN
+#include <Eigen/Eigen>
+#endif
+
+#include "MathLib/Vector3.h"
+#include "MathLib/LinAlg/Dense/DenseMatrix.h"
+
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/CoordinateSystem.h"
+
+namespace MeshLib
+{
+
+#ifdef OGS_USE_EIGEN
+typedef Eigen::Matrix<double, 3u, 3u, Eigen::RowMajor> RotationMatrix;
+#else
+typedef MathLib::DenseMatrix<double> RotationMatrix;
+#endif
+
+/**
+ * This class maps node coordinates on intrinsic coordinates of the given element.
+ */
+class ElementCoordinatesMappingLocal
+{
+public:
+    /**
+     * Constructor
+     * \param e                     Mesh element whose node coordinates are mapped
+     * \param global_coord_system   Global coordinate system
+     */
+    ElementCoordinatesMappingLocal(const Element &e, const CoordinateSystem &global_coord_system);
+
+    /// Destructor
+    virtual ~ElementCoordinatesMappingLocal();
+
+    /// return the global coordinate system
+    const CoordinateSystem getGlobalCoordinateSystem() const { return _coords; }
+
+    /// return mapped coordinates of the node
+    const MeshLib::Node* getMappedCoordinates(size_t node_id) const
+    {
+        return _vec_nodes[node_id];
+    }
+
+    /// return a rotation matrix converting to global coordinates
+    const RotationMatrix& getRotationMatrixToGlobal() const {return _matR2global;}
+
+private:
+    /// rotate points to local coordinates
+    void rotateToLocal(const RotationMatrix &matR2local, std::vector<MeshLib::Node*> &vec_pt) const;
+
+    /// get a rotation matrix to the global coordinates
+    /// it computes R in x=R*x' where x is original coordinates and x' is local coordinates
+    void getRotationMatrixToGlobal(
+            const Element &e, const CoordinateSystem &coordinate_system,
+            const std::vector<MeshLib::Node*> &vec_pt, RotationMatrix &matR2original) const;
+
+private:
+    const CoordinateSystem _coords;
+    std::vector<MeshLib::Node*> _vec_nodes;
+    RotationMatrix _matR2global;
+};
+
+}
+
+#endif // ELEMENTCOORDINATESMAPPINGLOCAL_H_
diff --git a/Tests/MathLib/TestDenseMatrix.cpp b/Tests/MathLib/TestDenseMatrix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..41ad1fe1df845816808f7d489698c3d164fe420c
--- /dev/null
+++ b/Tests/MathLib/TestDenseMatrix.cpp
@@ -0,0 +1,67 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "gtest/gtest.h"
+
+#include "MathLib/LinAlg/Dense/DenseMatrix.h"
+#include "../TestTools.h"
+
+using namespace MathLib;
+
+TEST(MathLib, DenseMatrixTransposeInPlace)
+{
+    const double eps(std::numeric_limits<double>::epsilon());
+
+    // square matrix
+	DenseMatrix<double> m1(3,3);
+	unsigned cnt = 0;
+	for (unsigned i=0; i<m1.getNRows(); i++)
+		for (unsigned j=0; j<m1.getNCols(); j++)
+			m1(i,j) = cnt++;
+	double expected_m1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
+	ASSERT_EQ(3u, m1.getNRows());
+	ASSERT_EQ(3u, m1.getNCols());
+    ASSERT_ARRAY_NEAR(expected_m1, m1.data(), m1.size(), eps);
+	m1.transposeInPlace();
+	ASSERT_EQ(3u, m1.getNRows());
+	ASSERT_EQ(3u, m1.getNCols());
+	double expected_m1t[] = {0, 3, 6, 1, 4, 7, 2, 5, 8};
+    ASSERT_ARRAY_NEAR(expected_m1t, m1.data(), m1.size(), eps);
+
+    // non-square matrix 1
+	DenseMatrix<double> m2(2,3);
+	cnt = 0;
+	for (unsigned i=0; i<m2.getNRows(); i++)
+		for (unsigned j=0; j<m2.getNCols(); j++)
+			m2(i,j) = cnt++;
+	ASSERT_EQ(2u, m2.getNRows());
+	ASSERT_EQ(3u, m2.getNCols());
+	double expected_m2[] = {0, 1, 2, 3, 4, 5};
+    ASSERT_ARRAY_NEAR(expected_m2, m2.data(), m2.size(), eps);
+	m2.transposeInPlace();
+	ASSERT_EQ(3u, m2.getNRows());
+	ASSERT_EQ(2u, m2.getNCols());
+	double expected_m2t[] = {0, 3, 1, 4, 2, 5};
+    ASSERT_ARRAY_NEAR(expected_m2t, m2.data(), m2.size(), eps);
+
+    // non-square matrix 2
+	DenseMatrix<double> m3(3,2);
+	cnt = 0;
+	for (unsigned i=0; i<m3.getNRows(); i++)
+		for (unsigned j=0; j<m3.getNCols(); j++)
+			m3(i,j) = cnt++;
+	ASSERT_EQ(3u, m3.getNRows());
+	ASSERT_EQ(2u, m3.getNCols());
+	double expected_m3[] = {0, 1, 2, 3, 4, 5};
+    ASSERT_ARRAY_NEAR(expected_m3, m3.data(), m3.size(), eps);
+	m3.transposeInPlace();
+	ASSERT_EQ(2u, m3.getNRows());
+	ASSERT_EQ(3u, m3.getNCols());
+	double expected_m3t[] = {0, 2, 4, 1, 3, 5};
+    ASSERT_ARRAY_NEAR(expected_m3t, m3.data(), m3.size(), eps);
+}
diff --git a/Tests/MeshLib/TestCoordinatesMappingLocal.cpp b/Tests/MeshLib/TestCoordinatesMappingLocal.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e26792226911bb7276b31f1aff54d1c3f0c077c3
--- /dev/null
+++ b/Tests/MeshLib/TestCoordinatesMappingLocal.cpp
@@ -0,0 +1,260 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/LICENSE.txt
+ */
+
+#include <gtest/gtest.h>
+
+#include <limits>
+#include <algorithm>
+#include <vector>
+#include <cmath>
+
+#ifdef OGS_USE_EIGEN
+#include <Eigen/Eigen>
+#endif
+
+#include "GeoLib/AnalyticalGeometry.h"
+#include "MathLib/LinAlg/Dense/DenseMatrix.h"
+
+#include "MeshLib/Node.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/Elements/Line.h"
+#include "MeshLib/Elements/Quad.h"
+#include "MeshLib/ElementCoordinatesMappingLocal.h"
+
+#include "../TestTools.h"
+
+
+namespace
+{
+
+class TestLine2
+{
+public:
+    typedef MeshLib::Line ElementType;
+    static const unsigned e_nnodes = ElementType::n_all_nodes;
+
+    static MeshLib::Line* createY()
+    {
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        nodes[0] = new MeshLib::Node(0.0, -1.0, 0.0);
+        nodes[1] = new MeshLib::Node(0.0,  1.0, 0.0);
+        return new MeshLib::Line(nodes);
+    }
+
+    static MeshLib::Line* createZ()
+    {
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        nodes[0] = new MeshLib::Node(0.0, 0.0, -1.0);
+        nodes[1] = new MeshLib::Node(0.0, 0.0,  1.0);
+        return new MeshLib::Line(nodes);
+    }
+
+    static MeshLib::Line* createXY()
+    {
+        // 45degree inclined
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        nodes[0] = new MeshLib::Node(0.0, 0.0, 0.0);
+        nodes[1] = new MeshLib::Node(2./sqrt(2), 2./sqrt(2), 0.0);
+        return new MeshLib::Line(nodes);
+    }
+
+    static MeshLib::Line* createXYZ()
+    {
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        nodes[0] = new MeshLib::Node(0.0, 0.0, 0.0);
+        nodes[1] = new MeshLib::Node(2./sqrt(3), 2./sqrt(3), 2./sqrt(3));
+        return new MeshLib::Line(nodes);
+    }
+
+};
+
+class TestQuad4
+{
+ public:
+    // Element information
+    typedef MeshLib::Quad ElementType;
+    static const unsigned e_nnodes = ElementType::n_all_nodes;
+
+    // 2.5D case: inclined
+    static MeshLib::Quad* createXYZ()
+    {
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        // rotate 45 degree around x axis
+        nodes[0] = new MeshLib::Node( 1.0,  0.7071067811865475,  0.7071067811865475);
+        nodes[1] = new MeshLib::Node(-1.0,  0.7071067811865475,  0.7071067811865475);
+        nodes[2] = new MeshLib::Node(-1.0, -0.7071067811865475, -0.7071067811865475);
+        nodes[3] = new MeshLib::Node( 1.0, -0.7071067811865475, -0.7071067811865475);
+        return new MeshLib::Quad(nodes);
+    }
+
+    // 2.5D case: inclined
+    static MeshLib::Quad* createXZ()
+    {
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        nodes[0] = new MeshLib::Node( 1.0, 0.0,  1.0);
+        nodes[1] = new MeshLib::Node(-1.0, 0.0,  1.0);
+        nodes[2] = new MeshLib::Node(-1.0, 0.0, -1.0);
+        nodes[3] = new MeshLib::Node( 1.0, 0.0, -1.0);
+        return new MeshLib::Quad(nodes);
+    }
+
+    // 2.5D case: inclined
+    static MeshLib::Quad* createYZ()
+    {
+        MeshLib::Node** nodes = new MeshLib::Node*[e_nnodes];
+        nodes[0] = new MeshLib::Node(0.0,  1.0,  1.0);
+        nodes[1] = new MeshLib::Node(0.0, -1.0,  1.0);
+        nodes[2] = new MeshLib::Node(0.0, -1.0, -1.0);
+        nodes[3] = new MeshLib::Node(0.0,  1.0, -1.0);
+        return new MeshLib::Quad(nodes);
+    }
+
+};
+
+#if 0
+// keep this function for debugging
+void debugOutput(MeshLib::Element *ele, MeshLib::ElementCoordinatesMappingLocal &mapping)
+{
+    std::cout.precision(12);
+    std::cout << "original" << std::endl;
+    for (unsigned i=0; i<ele->getNNodes(); i++)
+        std::cout << *ele->getNode(i) << std::endl;
+    std::cout << "local coords=" << std::endl;
+    for (unsigned i=0; i<ele->getNNodes(); i++)
+        std::cout << *mapping.getMappedCoordinates(i) << std::endl;
+    std::cout << "R=\n" << mapping.getRotationMatrixToGlobal() << std::endl;
+    auto matR(mapping.getRotationMatrixToGlobal());
+    std::cout << "global coords=" << std::endl;
+    for (unsigned i=0; i<ele->getNNodes(); i++) {
+        double* raw = const_cast<double*>(&(*mapping.getMappedCoordinates(i))[0]);
+        Eigen::Map<Eigen::Vector3d> v(raw);
+        std::cout << (matR*v).transpose() << std::endl;
+    }
+}
+#endif
+
+// check if using the rotation matrix results in the original coordinates
+#define CHECK_COORDS(ele, mapping)\
+    for (unsigned ii=0; ii<ele->getNNodes(); ii++) {\
+    	MathLib::Point3d global(matR*static_cast<MathLib::Point3d>(*mapping.getMappedCoordinates(ii)));\
+        const double eps(std::numeric_limits<double>::epsilon());\
+        ASSERT_ARRAY_NEAR(&(*ele->getNode(ii))[0], global.getCoords(), 3u, eps);\
+    }
+
+} //namespace
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimLineY)
+{
+    auto ele = TestLine2::createY();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(MeshLib::CoordinateSystemType::Y));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    double exp_R[3*3] = {0, -1, 0,
+                         1,  0, 0,
+                         0,  0, 1};
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimLineZ)
+{
+    auto ele = TestLine2::createZ();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele,
+            MeshLib::CoordinateSystem(MeshLib::CoordinateSystemType::Z));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    double exp_R[3*3] = {0, 0, -1, 0, 1, 0, 1, 0, 0};
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimLineXY)
+{
+    auto ele = TestLine2::createXY();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    double exp_R[3*3] = {0.70710678118654757, -0.70710678118654757, 0,
+                         0.70710678118654757,  0.70710678118654757, 0,
+                         0,                    0,                   1};
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimLineXYZ)
+{
+    auto ele = TestLine2::createXYZ();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    double exp_R[3*3] = {0.57735026918962584, -0.81649658092772626,  0,
+                         0.57735026918962584,  0.40824829046386313, -0.70710678118654757,
+                         0.57735026918962584,  0.40824829046386313,  0.70710678118654757};
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimQuadXZ)
+{
+    auto ele = TestQuad4::createXZ();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    // results when using GeoLib::ComputeRotationMatrixToXY()
+    double exp_R[3*3] = {  1, 0,  0,
+                           0, 0, -1,
+                           0, 1,  0};
+
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimQuadYZ)
+{
+    auto ele = TestQuad4::createYZ();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    // results when using GeoLib::ComputeRotationMatrixToXY()
+    double exp_R[3*3] = { 0, 0, 1,
+                          0, 1, 0,
+                         -1, 0, 0};
+
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
+TEST(MeshLib, CoordinatesMappingLocalLowerDimQuadXYZ)
+{
+    auto ele = TestQuad4::createXYZ();
+    MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele));
+    auto matR(mapping.getRotationMatrixToGlobal());
+    //debugOutput(ele, mapping);
+
+    // results when using GeoLib::ComputeRotationMatrixToXY()
+    double exp_R[3*3] = {  1, 0, 0,
+                           0, 0.70710678118654757, -0.70710678118654757,
+                           0, 0.70710678118654757,  0.70710678118654757};
+
+    const double eps(std::numeric_limits<double>::epsilon());
+    ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps);
+    CHECK_COORDS(ele,mapping);
+}
+
diff --git a/Tests/NumLib/TestFe.cpp b/Tests/NumLib/TestFe.cpp
index 24ecfde7d9f863fbc773b5f52471efa79bdf9de1..834055a367cad392192ca7131fbb8b422cb91c3b 100644
--- a/Tests/NumLib/TestFe.cpp
+++ b/Tests/NumLib/TestFe.cpp
@@ -140,6 +140,10 @@ class NumLibFemIsoTest : public ::testing::Test, public T::TestFeType
     std::vector<const MeshElementType*> vec_eles;
     MeshElementType* mesh_element;
 
+ public:
+#ifdef OGS_USE_EIGEN
+   EIGEN_MAKE_ALIGNED_OPERATOR_NEW // required to use fixed size Eigen matrices
+#endif
 }; // NumLibFemIsoTest
 
 template <class T>
diff --git a/scripts/cmake/cmake/FindEigen3.cmake b/scripts/cmake/cmake/FindEigen3.cmake
index 2b9e6afae4dcc348c53d96b052efba5a3b161828..0f8c5d45c79ce9a97b224a4ae2f2949c3a58b30a 100644
--- a/scripts/cmake/cmake/FindEigen3.cmake
+++ b/scripts/cmake/cmake/FindEigen3.cmake
@@ -85,3 +85,6 @@ else ()
 
 endif()
 
+if(EIGEN3_INCLUDE_DIR)
+  message(STATUS "Eigen version ${EIGEN3_VERSION}")
+endif()