From b169338827ca21c241a9dc2849cd1ecba73c1b85 Mon Sep 17 00:00:00 2001
From: Norihiro Watanabe <norihiro.watanabe@ufz.de>
Date: Fri, 6 Feb 2015 18:21:21 +0100
Subject: [PATCH] remove Edge, Face, and Cell and add similar as rules

---
 MeshGeoToolsLib/HeuristicSearchLength.cpp   |  2 +-
 MeshLib/Elements/{Cell.cpp => CellRule.cpp} | 36 +++---------
 MeshLib/Elements/{Cell.h => CellRule.h}     | 43 ++++----------
 MeshLib/Elements/Edge.cpp                   | 20 -------
 MeshLib/Elements/Edge.h                     | 54 -----------------
 MeshLib/Elements/EdgeRule.h                 | 47 +++++++++++++++
 MeshLib/Elements/Face.cpp                   | 51 ----------------
 MeshLib/Elements/Face.h                     | 64 ---------------------
 MeshLib/Elements/FaceRule.cpp               | 34 +++++++++++
 MeshLib/Elements/FaceRule.h                 | 20 +++++--
 MeshLib/Elements/Hex.h                      |  3 +-
 MeshLib/Elements/HexRule8.h                 |  3 +-
 MeshLib/Elements/Line.h                     |  5 +-
 MeshLib/Elements/LineRule2.h                | 15 +----
 MeshLib/Elements/Prism.h                    |  3 +-
 MeshLib/Elements/PrismRule6.h               |  3 +-
 MeshLib/Elements/Pyramid.h                  |  3 +-
 MeshLib/Elements/PyramidRule5.h             |  3 +-
 MeshLib/Elements/Quad.h                     |  7 +--
 MeshLib/Elements/TemplateElement-impl.h     |  3 +
 MeshLib/Elements/TemplateElement.h          | 11 +++-
 MeshLib/Elements/Tet.h                      |  3 +-
 MeshLib/Elements/TetRule4.h                 |  3 +-
 MeshLib/Elements/Tri.h                      |  3 +-
 MeshLib/MeshSurfaceExtraction.cpp           | 10 ++--
 25 files changed, 156 insertions(+), 293 deletions(-)
 rename MeshLib/Elements/{Cell.cpp => CellRule.cpp} (54%)
 rename MeshLib/Elements/{Cell.h => CellRule.h} (52%)
 delete mode 100644 MeshLib/Elements/Edge.cpp
 delete mode 100644 MeshLib/Elements/Edge.h
 create mode 100644 MeshLib/Elements/EdgeRule.h
 delete mode 100644 MeshLib/Elements/Face.cpp
 delete mode 100644 MeshLib/Elements/Face.h
 create mode 100644 MeshLib/Elements/FaceRule.cpp

diff --git a/MeshGeoToolsLib/HeuristicSearchLength.cpp b/MeshGeoToolsLib/HeuristicSearchLength.cpp
index fbe7c6bbfd7..fc884a8c27a 100644
--- a/MeshGeoToolsLib/HeuristicSearchLength.cpp
+++ b/MeshGeoToolsLib/HeuristicSearchLength.cpp
@@ -35,7 +35,7 @@ HeuristicSearchLength::HeuristicSearchLength(MeshLib::Mesh const& mesh, LengthTy
 			std::size_t const n_edges((*it)->getNEdges());
 			for (std::size_t k(0); k<n_edges; k++) {
 				double const len =
-					static_cast<MeshLib::Line const*>((*it)->getEdge(k))->getLength();
+					static_cast<MeshLib::Line const*>((*it)->getEdge(k))->getContent();
 				sum += len;
 				sum_of_sqr += len*len;
 			}
diff --git a/MeshLib/Elements/Cell.cpp b/MeshLib/Elements/CellRule.cpp
similarity index 54%
rename from MeshLib/Elements/Cell.cpp
rename to MeshLib/Elements/CellRule.cpp
index aa07e8a1d69..62fd5d4dbdf 100644
--- a/MeshLib/Elements/Cell.cpp
+++ b/MeshLib/Elements/CellRule.cpp
@@ -1,9 +1,4 @@
 /**
- * \file
- * \author Karsten Rink
- * \date   2012-05-02
- * \brief  Implementation of the Cell class.
- *
  * \copyright
  * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
@@ -12,41 +7,29 @@
  *
  */
 
-#include "Cell.h"
+#include "CellRule.h"
 
 #include "MathLib/Vector3.h"
 #include "MeshLib/Node.h"
-#include "MeshLib/Elements/Face.h"
+#include "Element.h"
+#include "FaceRule.h"
 
 namespace MeshLib {
 
-#ifndef WIN32
-/// \todo Windows compiler does not accept this definition and issues a linking error.
-const unsigned Cell::dimension;
-#endif
-
-Cell::Cell(unsigned value, std::size_t id)
-	: Element(value, id)
-{
-}
-
-Cell::~Cell()
-{}
-
-bool Cell::testElementNodeOrder() const
+bool CellRule::testElementNodeOrder(const Element* e)
 {
-	const MathLib::Vector3 c (getCenterOfGravity());
-	const unsigned nFaces (this->getNFaces());
+	const MathLib::Vector3 c (e->getCenterOfGravity());
+	const unsigned nFaces (e->getNFaces());
 	for (unsigned j=0; j<nFaces; ++j)
 	{
-		MeshLib::Face const*const face (dynamic_cast<const MeshLib::Face*>(this->getFace(j)));
+		MeshLib::Element const*const face (e->getFace(j));
 		// Node 1 is checked below because that way all nodes are used for the test
 		// at some point, while for node 0 at least one node in every element
 		// type would be used for checking twice and one wouldn't be checked at
 		// all. (based on the definition of the _face_nodes variable)
 		const MeshLib::Node x (*(face->getNode(1)));
 		const MathLib::Vector3 cx (c, x);
-		const double s = MathLib::scalarProduct(face->getSurfaceNormal(), cx);
+		const double s = MathLib::scalarProduct(FaceRule::getSurfaceNormal(face), cx);
 		delete face;
 		if (s >= 0)
 			return false;
@@ -54,5 +37,4 @@ bool Cell::testElementNodeOrder() const
 	return true;
 }
 
-}
-
+} /* namespace */
diff --git a/MeshLib/Elements/Cell.h b/MeshLib/Elements/CellRule.h
similarity index 52%
rename from MeshLib/Elements/Cell.h
rename to MeshLib/Elements/CellRule.h
index 66ce7cce3bb..06c93621694 100644
--- a/MeshLib/Elements/Cell.h
+++ b/MeshLib/Elements/CellRule.h
@@ -1,9 +1,4 @@
 /**
- * \file
- * \author Karsten Rink
- * \date   2012-05-02
- * \brief  Definition of the Cell class.
- *
  * \copyright
  * Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
@@ -12,46 +7,32 @@
  *
  */
 
-#ifndef CELL_H_
-#define CELL_H_
+#ifndef CELLRULE_H_
+#define CELLRULE_H_
 
-#include "Element.h"
+namespace MeshLib
+{
 
-namespace MeshLib {
+class Element;
 
-/**
- * Virtual base class for 3d mesh elements.
- */
-class Cell : public Element
+class CellRule
 {
 public:
 	/// Constant: Dimension of this mesh element
 	static const unsigned dimension = 3u;
 
-	/// Get the volume of this 3d element.
-	virtual double getVolume() const { return getContent(); }
-
-	/// Destructor
-	virtual ~Cell();
-
 	/**
 	 * Checks if the node order of an element is correct by testing surface normals.
-	 * For 3D elements true is returned if the normals of all faces points away from the centre of 
+	 * For 3D elements true is returned if the normals of all faces points away from the centre of
 	 * the element.
-	 * Note: This method might give wrong results if something else is wrong with the element 
-	 * (non-planar faces, non-convex geometry, possibly zero volume) which causes the calculated 
+	 * Note: This method might give wrong results if something else is wrong with the element
+	 * (non-planar faces, non-convex geometry, possibly zero volume) which causes the calculated
 	 * center of gravity to lie outside of the actual element
 	 */
-	virtual bool testElementNodeOrder() const;
-
-protected:
-	/// Constructor
-	/// @param value  element value
-	/// @param id     element id
-	Cell(unsigned value, std::size_t id);
+	static bool testElementNodeOrder(const Element* /*e*/);
 }; /* class */
 
-}
+} /* namespace */
 
-#endif /* CELL_H_ */
+#endif /* CELLRULE_H_ */
 
diff --git a/MeshLib/Elements/Edge.cpp b/MeshLib/Elements/Edge.cpp
deleted file mode 100644
index bf0395fa3a4..00000000000
--- a/MeshLib/Elements/Edge.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * \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 "Edge.h"
-
-namespace MeshLib {
-
-#ifndef WIN32
-/// \todo Windows compiler does not accept this definition and issues a linking error.
-const unsigned Edge::dimension;
-#endif
-
-} /* namespace */
-
diff --git a/MeshLib/Elements/Edge.h b/MeshLib/Elements/Edge.h
deleted file mode 100644
index df7eadd129e..00000000000
--- a/MeshLib/Elements/Edge.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2012-05-02
- * \brief  Definition of the Face class.
- *
- * \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 EDGE_H_
-#define EDGE_H_
-
-#include "Element.h"
-
-namespace MeshLib {
-
-/**
- * Virtual base class for 1d mesh elements.
- */
-class Edge : public Element
-{
-public:
-	/// Constant: Dimension of this mesh element
-	static const unsigned dimension = 1u;
-
-	/// Get the length of this 1d element.
-	virtual double getLength() const { return _content; }
-
-	/// Destructor
-	virtual ~Edge() {}
-
-	/**
-	* Checks if the node order of an element is correct by testing surface normals.
-	* For 1D elements this always returns true.
-	*/
-	virtual bool testElementNodeOrder() const { return true; }
-
-protected:
-	/// Constructor
-	/// @param value  element value
-	/// @param id     element id
-	Edge(unsigned value, std::size_t id) : Element(value, id) {}
-
-}; /* class */
-
-} /* namespace */
-
-#endif /* EDGE_H_ */
-
diff --git a/MeshLib/Elements/EdgeRule.h b/MeshLib/Elements/EdgeRule.h
new file mode 100644
index 00000000000..5ee42447de6
--- /dev/null
+++ b/MeshLib/Elements/EdgeRule.h
@@ -0,0 +1,47 @@
+/**
+ * \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 EDGERULE_H_
+#define EDGERULE_H_
+
+namespace MeshLib
+{
+
+class Element;
+
+class EdgeRule
+{
+public:
+	/// Constant: Dimension of this mesh element
+	static const unsigned dimension = 1u;
+
+	/// Constant: The number of faces
+	static const unsigned n_faces = 0;
+
+	/// Constant: The number of edges
+	static const unsigned n_edges = 0;
+
+	/// Get the number of nodes for face i.
+	static unsigned getNFaceNodes(unsigned /*i*/) { return 0; }
+
+	/// Returns the i-th face of the element.
+	static const Element* getFace(const Element* /*e*/, unsigned /*i*/) { return nullptr; }
+
+	/**
+	* Checks if the node order of an element is correct by testing surface normals.
+	* For 1D elements this always returns true.
+	*/
+	static bool testElementNodeOrder(const Element* /*e*/) { return true; }
+
+}; /* class */
+
+} /* namespace */
+
+#endif /* EDGERULE_H_ */
+
diff --git a/MeshLib/Elements/Face.cpp b/MeshLib/Elements/Face.cpp
deleted file mode 100644
index 5c597851be3..00000000000
--- a/MeshLib/Elements/Face.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2012-05-02
- * \brief  Implementation of the Face class.
- *
- * \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 "Face.h"
-
-#include "MathLib/MathTools.h"
-#include "MathLib/Vector3.h"
-
-#include "Line.h"
-
-namespace MeshLib {
-
-#ifndef WIN32
-/// \todo Windows compiler does not accept this definition and issues a linking error.
-const unsigned Face::dimension;
-#endif // WIN32
-
-Face::Face(unsigned value, std::size_t id)
-	: Element(value, id)
-{
-}
-
-Face::~Face()
-{}
-
-MathLib::Vector3 Face::getSurfaceNormal() const
-{
-	const MathLib::Vector3 u (*_nodes[1], *_nodes[0]);
-	const MathLib::Vector3 v (*_nodes[1], *_nodes[2]);
-	return MathLib::crossProduct(u,v);
-}
-
-bool Face::testElementNodeOrder() const
-{
-	MathLib::Vector3 up_vec (0,0,1);
-	return (MathLib::scalarProduct(this->getSurfaceNormal(), up_vec) < 0) ? true : false;
-}
-
-}
-
diff --git a/MeshLib/Elements/Face.h b/MeshLib/Elements/Face.h
deleted file mode 100644
index 220c561ad7a..00000000000
--- a/MeshLib/Elements/Face.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2012-05-02
- * \brief  Definition of the Face class.
- *
- * \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 FACE_H_
-#define FACE_H_
-
-#include "GeoLib/Point.h"
-
-#include "MathLib/Vector3.h"
-
-#include "Element.h"
-
-namespace MeshLib {
-
-/**
- * Virtual base class for 2d mesh elements.
- */
-class Face : public Element
-{
-public:
-	/// Constant: Dimension of this mesh element
-	static const unsigned dimension = 2u;
-
-	/// Get the area of this 2d element.
-	virtual double getArea() const { return _content; }
-
-	/// Returns the surface normal of a 2D element.
-	MathLib::Vector3 getSurfaceNormal() const;
-
-	/// Destructor
-	virtual ~Face();
-
-	/**
-	 * Checks if the node order of an element is correct by testing surface normals.
-	 * For 2D elements true is returned if the normal points (roughly) upwards.
-	 */
-	virtual bool testElementNodeOrder() const;
-
-protected:
-	/// Constructor
-	/// @param value  element value
-	/// @param id     element id
-	Face(unsigned value, std::size_t id);
-
-private:
-
-
-}; /* class */
-
-} /* namespace */
-
-#endif /* FACE_H_ */
-
diff --git a/MeshLib/Elements/FaceRule.cpp b/MeshLib/Elements/FaceRule.cpp
new file mode 100644
index 00000000000..dda853336e4
--- /dev/null
+++ b/MeshLib/Elements/FaceRule.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 "FaceRule.h"
+
+#include "MathLib/MathTools.h"
+#include "MeshLib/Node.h"
+#include "Element.h"
+
+namespace MeshLib
+{
+
+bool FaceRule::testElementNodeOrder(const Element* e)
+{
+	MathLib::Vector3 up_vec (0,0,1);
+	return (MathLib::scalarProduct(getSurfaceNormal(e), up_vec) < 0) ? true : false;
+}
+
+MathLib::Vector3 FaceRule::getSurfaceNormal(const Element* e)
+{
+	Node * const * _nodes = e->getNodes();
+	const MathLib::Vector3 u (*_nodes[1], *_nodes[0]);
+	const MathLib::Vector3 v (*_nodes[1], *_nodes[2]);
+	return MathLib::crossProduct(u,v);
+}
+
+} /* namespace */
+
diff --git a/MeshLib/Elements/FaceRule.h b/MeshLib/Elements/FaceRule.h
index b68cf4c4d93..66cd734ce31 100644
--- a/MeshLib/Elements/FaceRule.h
+++ b/MeshLib/Elements/FaceRule.h
@@ -10,16 +10,18 @@
 #ifndef FACERULE_H_
 #define FACERULE_H_
 
-#include "MeshLib/MeshEnums.h"
+#include "MathLib/Vector3.h"
 #include "Element.h"
 
-namespace MeshLib {
+namespace MeshLib
+{
 
-/**
- */
 class FaceRule
 {
 public:
+	/// Constant: Dimension of this mesh element
+	static const unsigned dimension = 2u;
+
 	/// Returns the face i of the element.
 	static const Element* getFace(const Element* e, unsigned i) { return e->getEdge(i); }
 
@@ -28,6 +30,16 @@ public:
 
 	/// Constant: The number of faces
 	static const unsigned n_faces = 0;
+
+	/**
+	 * Checks if the node order of an element is correct by testing surface normals.
+	 * For 2D elements true is returned if the normal points (roughly) upwards.
+	 */
+	static bool testElementNodeOrder(const Element* /*e*/);
+
+	/// Returns the surface normal of a 2D element.
+	static MathLib::Vector3 getSurfaceNormal(const Element* e);
+
 }; /* class */
 
 } /* namespace */
diff --git a/MeshLib/Elements/Hex.h b/MeshLib/Elements/Hex.h
index 08be8f713d4..f8f1ff5dabd 100644
--- a/MeshLib/Elements/Hex.h
+++ b/MeshLib/Elements/Hex.h
@@ -16,11 +16,10 @@
 #define HEX_H_
 
 #include "TemplateElement.h"
-#include "Cell.h"
 #include "HexRule8.h"
 
 namespace MeshLib {
-typedef TemplateElement<Cell, HexRule8> Hex;
+typedef TemplateElement<Element, HexRule8> Hex;
 }
 
 #endif /* HEX_H_ */
diff --git a/MeshLib/Elements/HexRule8.h b/MeshLib/Elements/HexRule8.h
index 5bd2646f438..6c07d23ddf1 100644
--- a/MeshLib/Elements/HexRule8.h
+++ b/MeshLib/Elements/HexRule8.h
@@ -13,6 +13,7 @@
 #include "MeshLib/MeshEnums.h"
 #include "Element.h"
 #include "EdgeReturn.h"
+#include "CellRule.h"
 
 namespace MeshLib
 {
@@ -42,7 +43,7 @@ namespace MeshLib
  *
  * @endcode
  */
-class HexRule8
+class HexRule8 : public CellRule
 {
 public:
 	/// Constant: The number of base nodes for this element
diff --git a/MeshLib/Elements/Line.h b/MeshLib/Elements/Line.h
index 938ed32cdbf..8e6eea1199b 100644
--- a/MeshLib/Elements/Line.h
+++ b/MeshLib/Elements/Line.h
@@ -16,14 +16,13 @@
 #define LINE_H_
 
 #include "TemplateElement.h"
-#include "Edge.h"
 #include "LineRule2.h"
 #include "LineRule3.h"
 
 namespace MeshLib {
 
-typedef TemplateElement<Edge, LineRule2> Line;
-typedef TemplateElement<Edge, LineRule3> Line3;
+typedef TemplateElement<Element, LineRule2> Line;
+typedef TemplateElement<Element, LineRule3> Line3;
 
 }
 
diff --git a/MeshLib/Elements/LineRule2.h b/MeshLib/Elements/LineRule2.h
index 86719f1921b..8b5ef8a16cd 100644
--- a/MeshLib/Elements/LineRule2.h
+++ b/MeshLib/Elements/LineRule2.h
@@ -12,6 +12,7 @@
 
 #include "MeshLib/MeshEnums.h"
 #include "Element.h"
+#include "EdgeRule.h"
 #include "EdgeReturn.h"
 
 namespace MeshLib
@@ -23,7 +24,7 @@ namespace MeshLib
  *  0--------1
  * @endcode
  */
-class LineRule2
+class LineRule2 : public EdgeRule
 {
 public:
 	/// Constant: The number of base nodes for this element
@@ -38,12 +39,6 @@ public:
 	/// Constant: The FEM type of the element
 	static const CellType cell_type = CellType::LINE2;
 
-	/// Constant: The number of faces
-	static const unsigned n_faces = 0;
-
-	/// Constant: The number of edges
-	static const unsigned n_edges = 0;
-
 	/// Constant: The number of neighbors
 	static const unsigned n_neighbors = 2;
 
@@ -53,12 +48,6 @@ public:
 	/// Edge rule
 	typedef NoEdgeReturn EdgeReturn;
 
-	/// Get the number of nodes for face i.
-	static unsigned getNFaceNodes(unsigned /*i*/) { return 0; }
-
-	/// Returns the i-th face of the element.
-	static const Element* getFace(const Element* /*e*/, unsigned /*i*/) { return nullptr; }
-
 	/**
 	 * Checks if a point is inside the element.
 	 * @param pnt a 3D MathLib::Point3d object
diff --git a/MeshLib/Elements/Prism.h b/MeshLib/Elements/Prism.h
index 5fc96f59d37..ad6c2bf58c2 100644
--- a/MeshLib/Elements/Prism.h
+++ b/MeshLib/Elements/Prism.h
@@ -16,12 +16,11 @@
 #define PRISM_H_
 
 #include "TemplateElement.h"
-#include "Cell.h"
 #include "PrismRule6.h"
 
 namespace MeshLib {
 
-typedef TemplateElement<Cell, PrismRule6> Prism;
+typedef TemplateElement<Element, PrismRule6> Prism;
 
 }
 
diff --git a/MeshLib/Elements/PrismRule6.h b/MeshLib/Elements/PrismRule6.h
index d75543fba5d..56bc44d81ef 100644
--- a/MeshLib/Elements/PrismRule6.h
+++ b/MeshLib/Elements/PrismRule6.h
@@ -13,6 +13,7 @@
 #include "MeshLib/MeshEnums.h"
 #include "Element.h"
 #include "EdgeReturn.h"
+#include "CellRule.h"
 
 namespace MeshLib
 {
@@ -40,7 +41,7 @@ namespace MeshLib
  *
  * @endcode
  */
-class PrismRule6
+class PrismRule6 : public CellRule
 {
 public:
 	/// Constant: The number of base nodes for this element
diff --git a/MeshLib/Elements/Pyramid.h b/MeshLib/Elements/Pyramid.h
index 42cf46a813a..1e4421f500a 100644
--- a/MeshLib/Elements/Pyramid.h
+++ b/MeshLib/Elements/Pyramid.h
@@ -16,12 +16,11 @@
 #define PYRAMID_H_
 
 #include "TemplateElement.h"
-#include "Cell.h"
 #include "PyramidRule5.h"
 
 namespace MeshLib {
 
-typedef TemplateElement<Cell, PyramidRule5> Pyramid;
+typedef TemplateElement<Element, PyramidRule5> Pyramid;
 
 }
 
diff --git a/MeshLib/Elements/PyramidRule5.h b/MeshLib/Elements/PyramidRule5.h
index c6c8975d50f..ff3c6ceb11a 100644
--- a/MeshLib/Elements/PyramidRule5.h
+++ b/MeshLib/Elements/PyramidRule5.h
@@ -13,6 +13,7 @@
 #include "MeshLib/MeshEnums.h"
 #include "Element.h"
 #include "EdgeReturn.h"
+#include "CellRule.h"
 
 namespace MeshLib
 {
@@ -39,7 +40,7 @@ namespace MeshLib
  * @endcode
 
  */
-class PyramidRule5
+class PyramidRule5 : public CellRule
 {
 public:
 	/// Constant: The number of base nodes for this element
diff --git a/MeshLib/Elements/Quad.h b/MeshLib/Elements/Quad.h
index 482a49f973f..6be29a91e1e 100644
--- a/MeshLib/Elements/Quad.h
+++ b/MeshLib/Elements/Quad.h
@@ -16,7 +16,6 @@
 #define QUAD_H_
 
 #include "TemplateElement.h"
-#include "Face.h"
 #include "QuadRule4.h"
 #include "QuadRule8.h"
 #include "QuadRule9.h"
@@ -24,9 +23,9 @@
 namespace MeshLib
 {
 
-typedef TemplateElement<Face, QuadRule4> Quad;
-typedef TemplateElement<Face, QuadRule8> Quad8;
-typedef TemplateElement<Face, QuadRule9> Quad9;
+typedef TemplateElement<Element, QuadRule4> Quad;
+typedef TemplateElement<Element, QuadRule8> Quad8;
+typedef TemplateElement<Element, QuadRule9> Quad9;
 
 }
 
diff --git a/MeshLib/Elements/TemplateElement-impl.h b/MeshLib/Elements/TemplateElement-impl.h
index c5304bed0ab..37018153acd 100644
--- a/MeshLib/Elements/TemplateElement-impl.h
+++ b/MeshLib/Elements/TemplateElement-impl.h
@@ -19,6 +19,9 @@ const unsigned TemplateElement<T_BASE, ELEMENT_RULE>::n_all_nodes;
 
 template <class T_BASE, class ELEMENT_RULE>
 const unsigned TemplateElement<T_BASE, ELEMENT_RULE>::n_base_nodes;
+
+template <class T_BASE, class ELEMENT_RULE>
+const unsigned TemplateElement<T_BASE, ELEMENT_RULE>::dimension;
 #endif // WIN32
 
 template <class T_BASE, class ELEMENT_RULE>
diff --git a/MeshLib/Elements/TemplateElement.h b/MeshLib/Elements/TemplateElement.h
index 1db5102762d..367f1f3e160 100644
--- a/MeshLib/Elements/TemplateElement.h
+++ b/MeshLib/Elements/TemplateElement.h
@@ -39,7 +39,7 @@ public:
 	static const unsigned n_base_nodes = ELEMENT_RULE::n_base_nodes;
 
 	/// Constant: The dimension of this element
-	using T_BASE::dimension;
+	static const unsigned dimension = ELEMENT_RULE::dimension;
 
 	/**
 	 * Constructor with an array of mesh nodes.
@@ -145,6 +145,15 @@ public:
 			return nullptr;
 	}
 
+	/**
+	* Checks if the node order of an element is correct by testing surface normals.
+	* For 1D elements this always returns true.
+	*/
+	virtual bool testElementNodeOrder() const
+	{
+		return ELEMENT_RULE::testElementNodeOrder(this);
+	}
+
 };
 
 } // MeshLib
diff --git a/MeshLib/Elements/Tet.h b/MeshLib/Elements/Tet.h
index 3505c2d849e..b8ce5281e18 100644
--- a/MeshLib/Elements/Tet.h
+++ b/MeshLib/Elements/Tet.h
@@ -16,12 +16,11 @@
 #define TET_H_
 
 #include "TemplateElement.h"
-#include "Cell.h"
 #include "TetRule4.h"
 
 namespace MeshLib {
 
-typedef TemplateElement<Cell,TetRule4> Tet;
+typedef TemplateElement<Element,TetRule4> Tet;
 
 }
 
diff --git a/MeshLib/Elements/TetRule4.h b/MeshLib/Elements/TetRule4.h
index 324eeb4c601..d894a167255 100644
--- a/MeshLib/Elements/TetRule4.h
+++ b/MeshLib/Elements/TetRule4.h
@@ -13,6 +13,7 @@
 #include "MeshLib/MeshEnums.h"
 #include "Element.h"
 #include "EdgeReturn.h"
+#include "CellRule.h"
 
 namespace MeshLib
 {
@@ -37,7 +38,7 @@ namespace MeshLib
  *
  * @endcode
  */
-class TetRule4
+class TetRule4 : public CellRule
 {
 public:
 	/// Constant: The number of base nodes for this element
diff --git a/MeshLib/Elements/Tri.h b/MeshLib/Elements/Tri.h
index 78c6ed84d39..0a43e95c943 100644
--- a/MeshLib/Elements/Tri.h
+++ b/MeshLib/Elements/Tri.h
@@ -16,12 +16,11 @@
 #define TRI_H_
 
 #include "TemplateElement.h"
-#include "Face.h"
 #include "TriRule3.h"
 
 namespace MeshLib {
 
-typedef TemplateElement<Face,TriRule3> Tri;
+typedef TemplateElement<Element,TriRule3> Tri;
 
 }
 
diff --git a/MeshLib/MeshSurfaceExtraction.cpp b/MeshLib/MeshSurfaceExtraction.cpp
index 1b3e8c58cff..c5fe86d26f5 100644
--- a/MeshLib/MeshSurfaceExtraction.cpp
+++ b/MeshLib/MeshSurfaceExtraction.cpp
@@ -22,8 +22,6 @@
 
 #include "MeshLib/Mesh.h"
 #include "MeshLib/Elements/Line.h"
-#include "MeshLib/Elements/Face.h"
-#include "MeshLib/Elements/Cell.h"
 #include "MeshLib/Elements/Tri.h"
 #include "MeshLib/Elements/Quad.h"
 #include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
@@ -176,8 +174,8 @@ void MeshSurfaceExtraction::get2DSurfaceElements(const std::vector<MeshLib::Elem
 		{
 			if (!complete_surface)
 			{
-				MeshLib::Face* face = static_cast<MeshLib::Face*>(*elem);
-				if (MathLib::scalarProduct(face->getSurfaceNormal().getNormalizedVector(), norm_dir) > cos_theta)
+				MeshLib::Element* face = *elem;
+				if (MathLib::scalarProduct(FaceRule::getSurfaceNormal(face).getNormalizedVector(), norm_dir) > cos_theta)
 					continue;
 			}
 			sfc_elements.push_back(*elem);
@@ -192,10 +190,10 @@ void MeshSurfaceExtraction::get2DSurfaceElements(const std::vector<MeshLib::Elem
 				if ((*elem)->getNeighbor(j) != nullptr)
 					continue;
 
-				const MeshLib::Face* face = static_cast<const MeshLib::Face*>((*elem)->getFace(j));
+				const MeshLib::Element* face = (*elem)->getFace(j);
 				if (!complete_surface)
 				{
-					if (MathLib::scalarProduct(face->getSurfaceNormal().getNormalizedVector(), norm_dir) < cos_theta)
+					if (MathLib::scalarProduct(FaceRule::getSurfaceNormal(face).getNormalizedVector(), norm_dir) < cos_theta)
 					{
 						delete face;
 						continue;
-- 
GitLab