From c973ff65162268798c65af09fdeb564b5e44e68f Mon Sep 17 00:00:00 2001
From: Karsten Rink <karsten.rink@ufz.de>
Date: Fri, 11 May 2012 17:05:52 +0200
Subject: [PATCH] added edge and face information and subsequent construction
 and access to edge- and face-elements

---
 FileIO/MeshIO.h              |  1 +
 MeshLib/Elements/Cell.h      |  2 +-
 MeshLib/Elements/Edge.cpp    |  6 ++--
 MeshLib/Elements/Edge.h      | 17 ++++++++++-
 MeshLib/Elements/Element.cpp | 33 +++++++++++++++-----
 MeshLib/Elements/Element.h   | 16 +++++++---
 MeshLib/Elements/Face.cpp    |  2 ++
 MeshLib/Elements/Face.h      |  8 ++++-
 MeshLib/Elements/Hex.cpp     | 48 +++++++++++++++++++++++++++--
 MeshLib/Elements/Hex.h       | 14 ++++++++-
 MeshLib/Elements/Prism.cpp   | 59 ++++++++++++++++++++++++++++++++++--
 MeshLib/Elements/Prism.h     | 15 ++++++++-
 MeshLib/Elements/Pyramid.cpp | 58 +++++++++++++++++++++++++++++++++--
 MeshLib/Elements/Pyramid.h   | 15 ++++++++-
 MeshLib/Elements/Quad.cpp    | 16 ++++++++--
 MeshLib/Elements/Quad.h      |  6 +++-
 MeshLib/Elements/Tet.cpp     | 41 +++++++++++++++++++++++--
 MeshLib/Elements/Tet.h       | 14 ++++++++-
 MeshLib/Elements/Tet10.cpp   |  4 +--
 MeshLib/Elements/Tri.cpp     | 15 +++++++--
 MeshLib/Elements/Tri.h       |  7 ++++-
 MeshLib/Mesh.cpp             |  1 +
 MeshLib/Mesh.h               |  7 +++++
 23 files changed, 362 insertions(+), 43 deletions(-)

diff --git a/FileIO/MeshIO.h b/FileIO/MeshIO.h
index 2a935dcee07..1c58b75ad0b 100644
--- a/FileIO/MeshIO.h
+++ b/FileIO/MeshIO.h
@@ -48,6 +48,7 @@ protected:
 private:
 	MeshLib::Element* readElement(const std::string& line, const std::vector<MeshLib::Node*> &nodes);
 
+	double* _edge_length[2];
 	const MeshLib::Mesh* _mesh;
 
 };  /* class */
diff --git a/MeshLib/Elements/Cell.h b/MeshLib/Elements/Cell.h
index 4ed84103299..b9d54fed1cb 100644
--- a/MeshLib/Elements/Cell.h
+++ b/MeshLib/Elements/Cell.h
@@ -36,7 +36,7 @@ protected:
 	Cell(MshElemType::type type, unsigned value = 0);
 
 	/// Calculate the volume of this 3d element.
-	virtual double calcVolume() = 0;
+	virtual double computeVolume() = 0;
 
 	double _volume;
 
diff --git a/MeshLib/Elements/Edge.cpp b/MeshLib/Elements/Edge.cpp
index 66032d35039..5ebed85fae2 100644
--- a/MeshLib/Elements/Edge.cpp
+++ b/MeshLib/Elements/Edge.cpp
@@ -16,7 +16,7 @@ Edge::Edge(Node* nodes[2], unsigned value)
 	: Element(MshElemType::LINE, value)
 {
 	_nodes = nodes;
-	this->_length = this->calcLength();
+	this->_length = this->computeLength();
 }
 
 Edge::Edge(Node* n0, Node* n1, unsigned value)
@@ -26,7 +26,7 @@ Edge::Edge(Node* n0, Node* n1, unsigned value)
 	_nodes[0] = n0;
 	_nodes[1] = n1;
 
-	this->_length = this->calcLength();
+	this->_length = this->computeLength();
 }
 
 Edge::Edge(const Edge &edge)
@@ -42,7 +42,7 @@ Edge::~Edge()
 {
 }
 
-double Edge::calcLength()
+double Edge::computeLength()
 {
 	return sqrt(MathLib::sqrDist(_nodes[0]->getData(), _nodes[1]->getData()));
 }
diff --git a/MeshLib/Elements/Edge.h b/MeshLib/Elements/Edge.h
index 3eb34c56209..5f83e3c1857 100644
--- a/MeshLib/Elements/Edge.h
+++ b/MeshLib/Elements/Edge.h
@@ -38,9 +38,18 @@ public:
 	/// Destructor
 	virtual ~Edge();
 
+	/// Returns the edge i of the element.
+	const Element* getEdge(unsigned i) const { return NULL; };
+
+	/// Returns the face i of the element.
+	const Element* getFace(unsigned i) const { return NULL; };
+
 	/// 1D elements have no edges
 	unsigned getNEdges() const { return 0; };
 
+	/// Get the number of nodes for face i.
+	unsigned getNFaceNodes(unsigned i) const { return 0; };
+
 	/// Get the number of faces for this element.
 	unsigned getNFaces() const { return 0; };
 
@@ -59,7 +68,13 @@ public:
 
 protected:
 	/// Calculate the length of this 1d element.
-	double calcLength();
+	double computeLength();
+
+	/// 1D elements have no edges.
+	Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return NULL; };
+
+	/// 1D elements have no faces.
+	Node* getFaceNode(unsigned face_id, unsigned node_id) const { return NULL; };
 
 	double _length;
 
diff --git a/MeshLib/Elements/Element.cpp b/MeshLib/Elements/Element.cpp
index e03a381d179..967e287e94a 100644
--- a/MeshLib/Elements/Element.cpp
+++ b/MeshLib/Elements/Element.cpp
@@ -7,6 +7,7 @@
 
 #include "Element.h"
 #include "Node.h"
+#include "Edge.h"
 
 #include <cassert>
 
@@ -27,23 +28,41 @@ Element::~Element()
 	delete[] this->_nodes;
 }
 
+const Element* Element::getEdge(unsigned i) const
+{
+	if (i < getNEdges())
+	{
+		Node** nodes = new Node*[2];
+		nodes[0] = getEdgeNode(i,0);
+		nodes[1] = getEdgeNode(i,1);
+		return new Edge(nodes);
+	}
+	std::cerr << "Error in MeshLib::Element::getEdge() - Index does not exist." << std::endl;
+	return NULL;
+}
+
 const Element* Element::getNeighbor(unsigned i) const
 {
-	assert(i < getNNeighbors() && "Error in MeshLib::Element::getNeighbor() - Index does not exist.");
-	return _neighbors[i];
+	if (i < getNNeighbors())
+		return _neighbors[i];
+	std::cerr << "Error in MeshLib::Element::getNeighbor() - Index does not exist." << std::endl;
+	return NULL;
 }
 
 const Node* Element::getNode(unsigned i) const
 {
-	assert(i < getNNodes() && "Error in MeshLib::Element::getNode() - Index does not exist.");
-	assert(_nodes[i] != NULL && "Error in MeshLib::Element::getNode() - Node is NULL.");
-	return _nodes[i];
+	if (i < getNNodes())
+		return _nodes[i];
+	std::cerr << "Error in MeshLib::Element::getNode() - Index does not exist." << std::endl;
+	return NULL;
 }
 
 unsigned Element::getNodeIndex(unsigned i) const 
 {
-	assert(i<getNNodes() && "Error in MeshLib::Element::getNodeIndex() - Index does not exist.");
-	return _nodes[i]->getID();
+	if (i<getNNodes())
+		return _nodes[i]->getID();
+	std::cerr << "Error in MeshLib::Element::getNodeIndex() - Index does not exist." << std::endl;
+	return NULL;
 }
 
 bool Element::hasNeighbor(Element* elem) const
diff --git a/MeshLib/Elements/Element.h b/MeshLib/Elements/Element.h
index af765dfd52e..7c29d7e32c9 100644
--- a/MeshLib/Elements/Element.h
+++ b/MeshLib/Elements/Element.h
@@ -36,9 +36,18 @@ public:
 	/// Get dimension of the mesh element.
 	virtual unsigned getDimension() const = 0;
 
+	/// Returns the edge i of the element.
+	const Element* getEdge(unsigned i) const;
+
+	/// Returns the face i of the element.
+	virtual const Element* getFace(unsigned i) const = 0;
+
 	/// Get the number of edges for this element.
 	virtual unsigned getNEdges() const = 0;
 
+	/// Get the number of nodes for face i.
+	virtual unsigned getNFaceNodes(unsigned i) const = 0;
+	
 	/// Get the number of faces for this element.
 	virtual unsigned getNFaces() const = 0;
 
@@ -66,13 +75,12 @@ public:
 	virtual ~Element();
 
 protected:
-/*
-	/// Constructor for a generic mesh element containing an array of mesh nodes.
-	Element(Node** nodes, MshElemType::type type, unsigned value = 0);
-*/
 	/// Constructor for a generic mesh element without an array of mesh nodes.
 	Element(MshElemType::type type, unsigned value = 0);
 
+	/// Return a specific edge node.
+	virtual Node* getEdgeNode(unsigned edge_id, unsigned node_id) const = 0;
+
 	Node** _nodes;
 	MshElemType::type _type;
 	unsigned _value;
diff --git a/MeshLib/Elements/Face.cpp b/MeshLib/Elements/Face.cpp
index 80b1f9112e1..d8ae6693c42 100644
--- a/MeshLib/Elements/Face.cpp
+++ b/MeshLib/Elements/Face.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "Face.h"
+#include "Edge.h"
 
 namespace MeshLib {
 /*
@@ -25,5 +26,6 @@ Face::~Face()
 }
 
 
+
 }
 
diff --git a/MeshLib/Elements/Face.h b/MeshLib/Elements/Face.h
index de97de3945a..6cb14a41aeb 100644
--- a/MeshLib/Elements/Face.h
+++ b/MeshLib/Elements/Face.h
@@ -24,6 +24,12 @@ public:
 	/// Get dimension of the mesh element.
 	unsigned getDimension() const { return 2; };
 
+	/// Returns the face i of the element.
+	const Element* getFace(unsigned i) const { return this->getEdge(i); };
+
+	/// Get the number of nodes for face i.
+	unsigned getNFaceNodes(unsigned i) const { return 2; };
+
 	/// 2D elements have no faces.
 	unsigned getNFaces() const { return 0; };
 
@@ -39,7 +45,7 @@ protected:
 	Face(MshElemType::type type, unsigned value = 0);
 
 	/// Calculate the area of this 2d element.
-	virtual double calcArea() = 0;
+	virtual double computeArea() = 0;
 
 	double _area;
 
diff --git a/MeshLib/Elements/Hex.cpp b/MeshLib/Elements/Hex.cpp
index c1ce664eb57..2bdb6028816 100644
--- a/MeshLib/Elements/Hex.cpp
+++ b/MeshLib/Elements/Hex.cpp
@@ -7,12 +7,40 @@
 
 #include "Hex.h"
 #include "Node.h"
+#include "Quad.h"
 
 #include "MathTools.h"
 
 
 namespace MeshLib {
 
+const unsigned Hex::_face_nodes[6][4] =
+{
+	{0, 3, 2, 1}, // Face 0
+	{0, 1, 5, 4}, // Face 1
+	{1, 2, 6, 5}, // Face 2
+	{2, 3, 7, 6}, // Face 3
+	{3, 0, 4, 7}, // Face 4
+	{4, 5, 6, 7}  // Face 5
+};
+ 
+const unsigned Hex::_edge_nodes[12][2] =
+{
+	{0, 1}, // Edge 0
+	{1, 2}, // Edge 1
+	{2, 3}, // Edge 2
+	{0, 3}, // Edge 3
+	{0, 4}, // Edge 4
+	{1, 5}, // Edge 5
+	{2, 6}, // Edge 6
+	{3, 7}, // Edge 7
+	{4, 5}, // Edge 8
+	{5, 6}, // Edge 9
+	{6, 7}, // Edge 10
+	{4, 7}  // Edge 11
+};
+
+
 Hex::Hex(Node* nodes[8], unsigned value)
 	: Cell(MshElemType::HEXAHEDRON, value)
 {
@@ -20,7 +48,7 @@ Hex::Hex(Node* nodes[8], unsigned value)
 	_neighbors = new Element*[6];
 	for (unsigned i=0; i<6; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Hex::Hex(Node* n0, Node* n1, Node* n2, Node* n3, Node* n4, Node* n5, Node* n6, Node* n7, unsigned value)
@@ -38,7 +66,7 @@ Hex::Hex(Node* n0, Node* n1, Node* n2, Node* n3, Node* n4, Node* n5, Node* n6, N
 	_neighbors = new Element*[6];
 	for (unsigned i=0; i<6; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Hex::Hex(const Hex &hex)
@@ -57,7 +85,7 @@ Hex::~Hex()
 {
 }
 
-double Hex::calcVolume()
+double Hex::computeVolume()
 {
 	return MathLib::calcTetrahedronVolume(_nodes[4]->getData(), _nodes[7]->getData(), _nodes[5]->getData(), _nodes[0]->getData())
 		 + MathLib::calcTetrahedronVolume(_nodes[5]->getData(), _nodes[3]->getData(), _nodes[1]->getData(), _nodes[0]->getData())
@@ -67,5 +95,19 @@ double Hex::calcVolume()
 		 + MathLib::calcTetrahedronVolume(_nodes[3]->getData(), _nodes[7]->getData(), _nodes[5]->getData(), _nodes[2]->getData());
 }
 
+const Element* Hex::getFace(unsigned i) const
+{
+	if (i<this->getNFaces())
+	{
+		unsigned nFaceNodes (this->getNFaceNodes(i));
+		Node** nodes = new Node*[nFaceNodes];
+		for (unsigned j=0; j<nFaceNodes; j++)
+			nodes[j] = _nodes[_face_nodes[i][j]];
+		return new Quad(nodes);
+	}
+	std::cerr << "Error in MeshLib::Element::getFace() - Index does not exist." << std::endl;
+	return NULL;
+}
+
 }
 
diff --git a/MeshLib/Elements/Hex.h b/MeshLib/Elements/Hex.h
index a78a02bf830..bc221c97ac5 100644
--- a/MeshLib/Elements/Hex.h
+++ b/MeshLib/Elements/Hex.h
@@ -46,9 +46,15 @@ public:
 	/// Destructor
 	virtual ~Hex();
 
+	/// Returns the face i of the element.
+	const Element* getFace(unsigned i) const;
+
 	/// Get the number of edges for this element.
 	unsigned getNEdges() const { return 12; };
 
+	/// Get the number of nodes for face i.
+	unsigned getNFaceNodes(unsigned i) const { return 4; };
+
 	/// Get the number of faces for this element.
 	unsigned getNFaces() const { return 6; };
 
@@ -60,7 +66,13 @@ public:
 
 protected:
 	/// Calculates the volume of a convex hexahedron by partitioning it into six tetrahedra.
-	double calcVolume();
+	double computeVolume();
+
+	/// Return a specific edge node.
+	inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; };
+
+	static const unsigned _face_nodes[6][4];
+	static const unsigned _edge_nodes[12][2];
 
 }; /* class */
 
diff --git a/MeshLib/Elements/Prism.cpp b/MeshLib/Elements/Prism.cpp
index 8ba4843a594..e27affafba8 100644
--- a/MeshLib/Elements/Prism.cpp
+++ b/MeshLib/Elements/Prism.cpp
@@ -7,11 +7,38 @@
 
 #include "Prism.h"
 #include "Node.h"
+#include "Tri.h"
+#include "Quad.h"
 
 #include "MathTools.h"
 
 namespace MeshLib {
 
+const unsigned Prism::_face_nodes[5][4] =
+{
+	{0, 2, 1, 99}, // Face 0
+	{0, 1, 4,  3}, // Face 1
+	{1, 2, 5,  4}, // Face 2
+	{2, 0, 3,  5}, // Face 3
+	{3, 4, 5, 99}  // Face 4
+};
+ 
+const unsigned Prism::_edge_nodes[9][2] =
+{
+	{0, 1}, // Edge 0
+	{1, 2}, // Edge 1
+	{0, 2}, // Edge 2
+	{0, 3}, // Edge 3
+	{1, 4}, // Edge 4
+	{2, 5}, // Edge 5
+	{3, 4}, // Edge 6
+	{4, 5}, // Edge 7
+	{3, 5}  // Edge 8
+};
+
+const unsigned Prism::_n_face_nodes[5] = { 3, 4, 4, 4, 3 };
+
+
 Prism::Prism(Node* nodes[6], unsigned value)
 	: Cell(MshElemType::PRISM, value)
 {
@@ -19,7 +46,7 @@ Prism::Prism(Node* nodes[6], unsigned value)
 	_neighbors = new Element*[5];
 	for (unsigned i=0; i<5; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Prism::Prism(Node* n0, Node* n1, Node* n2, Node* n3, Node* n4, Node* n5, unsigned value)
@@ -35,7 +62,7 @@ Prism::Prism(Node* n0, Node* n1, Node* n2, Node* n3, Node* n4, Node* n5, unsigne
 	_neighbors = new Element*[5];
 	for (unsigned i=0; i<5; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Prism::Prism(const Prism &prism)
@@ -54,12 +81,38 @@ Prism::~Prism()
 {
 }
 
-double Prism::calcVolume()
+double Prism::computeVolume()
 {
 	return MathLib::calcTetrahedronVolume(_nodes[0]->getData(), _nodes[1]->getData(), _nodes[2]->getData(), _nodes[3]->getData())
 		 + MathLib::calcTetrahedronVolume(_nodes[1]->getData(), _nodes[4]->getData(), _nodes[2]->getData(), _nodes[3]->getData())
 		 + MathLib::calcTetrahedronVolume(_nodes[2]->getData(), _nodes[4]->getData(), _nodes[5]->getData(), _nodes[3]->getData());
 }
 
+const Element* Prism::getFace(unsigned i) const
+{
+	if (i<this->getNFaces())
+	{
+		unsigned nFaceNodes (this->getNFaceNodes(i));
+		Node** nodes = new Node*[nFaceNodes];
+		for (unsigned j=0; j<nFaceNodes; j++)
+			nodes[j] = _nodes[_face_nodes[i][j]];
+
+		if (i==0 || i==4)
+			return new Tri(nodes);
+		else
+			return new Quad(nodes);
+	}
+	std::cerr << "Error in MeshLib::Element::getFace() - Index does not exist." << std::endl;
+	return NULL;
+}
+
+unsigned Prism::getNFaceNodes(unsigned i) const
+{
+	if (i<5)
+		return _n_face_nodes[i];
+	std::cerr << "Error in MeshLib::Element::getNFaceNodes() - Index does not exist." << std::endl;
+	return 0;
+}
+
 }
 
diff --git a/MeshLib/Elements/Prism.h b/MeshLib/Elements/Prism.h
index f7781110f08..d4604e63f63 100644
--- a/MeshLib/Elements/Prism.h
+++ b/MeshLib/Elements/Prism.h
@@ -44,9 +44,15 @@ public:
 	/// Destructor
 	virtual ~Prism();
 
+	/// Returns the face i of the element.
+	const Element* getFace(unsigned i) const;
+
 	/// Get the number of edges for this element.
 	unsigned getNEdges() const { return 9; };
 
+	/// Get the number of nodes for face i.
+	unsigned getNFaceNodes(unsigned i) const;
+
 	/// Get the number of faces for this element.
 	unsigned getNFaces() const { return 5; };
 
@@ -58,7 +64,14 @@ public:
 
 protected:
 	/// Calculates the volume of a prism by subdividing it into three tetrahedra.
-	double calcVolume();
+	double computeVolume();
+
+	/// Return a specific edge node.
+	inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; };
+
+	static const unsigned _face_nodes[5][4];
+	static const unsigned _edge_nodes[9][2];
+	static const unsigned _n_face_nodes[5];
 
 }; /* class */
 
diff --git a/MeshLib/Elements/Pyramid.cpp b/MeshLib/Elements/Pyramid.cpp
index ad78982230b..cb3ba05b958 100644
--- a/MeshLib/Elements/Pyramid.cpp
+++ b/MeshLib/Elements/Pyramid.cpp
@@ -7,11 +7,37 @@
 
 #include "Pyramid.h"
 #include "Node.h"
+#include "Tri.h"
+#include "Quad.h"
 
 #include "MathTools.h"
 
 namespace MeshLib {
 
+const unsigned Pyramid::_face_nodes[5][4] =
+{
+	{0, 1, 4, 99}, // Face 0
+	{1, 2, 4, 99}, // Face 1
+	{2, 3, 4, 99}, // Face 2
+	{3, 0, 4, 99}, // Face 3
+	{0, 3, 2,  1}  // Face 4
+};
+ 
+const unsigned Pyramid::_edge_nodes[8][2] =
+{
+	{0, 1}, // Edge 0
+	{1, 2}, // Edge 1
+	{2, 3}, // Edge 2
+	{0, 3}, // Edge 3
+	{0, 4}, // Edge 4
+	{1, 4}, // Edge 5
+	{2, 4}, // Edge 6
+	{3, 4}  // Edge 7
+};
+
+const unsigned Pyramid::_n_face_nodes[5] = { 3, 3, 3, 3, 4 };
+
+
 Pyramid::Pyramid(Node* nodes[5], unsigned value)
 	: Cell(MshElemType::PYRAMID, value)
 {
@@ -19,7 +45,7 @@ Pyramid::Pyramid(Node* nodes[5], unsigned value)
 	_neighbors = new Element*[5];
 	for (unsigned i=0; i<5; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Pyramid::Pyramid(Node* n0, Node* n1, Node* n2, Node* n3, Node* n4, unsigned value)
@@ -35,7 +61,7 @@ Pyramid::Pyramid(Node* n0, Node* n1, Node* n2, Node* n3, Node* n4, unsigned valu
 	for (unsigned i=0; i<5; i++)
 		_neighbors[i] = NULL;
 
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Pyramid::Pyramid(const Pyramid &pyramid)
@@ -55,11 +81,37 @@ Pyramid::~Pyramid()
 {
 }
 
-double Pyramid::calcVolume()
+double Pyramid::computeVolume()
 {
 	return MathLib::calcTetrahedronVolume(_nodes[0]->getData(), _nodes[1]->getData(), _nodes[2]->getData(), _nodes[4]->getData())
 		 + MathLib::calcTetrahedronVolume(_nodes[2]->getData(), _nodes[3]->getData(), _nodes[0]->getData(), _nodes[4]->getData());
 }
 
+const Element* Pyramid::getFace(unsigned i) const
+{
+	if (i<this->getNFaces())
+	{
+		unsigned nFaceNodes (this->getNFaceNodes(i));
+		Node** nodes = new Node*[nFaceNodes];
+		for (unsigned j=0; j<nFaceNodes; j++)
+			nodes[j] = _nodes[_face_nodes[i][j]];
+
+		if (i<4)
+			return new Tri(nodes);
+		else
+			return new Quad(nodes);
+	}
+	std::cerr << "Error in MeshLib::Element::getFace() - Index does not exist." << std::endl;
+	return NULL;
+}
+
+unsigned Pyramid::getNFaceNodes(unsigned i) const
+{
+	if (i<5)
+		return _n_face_nodes[i];
+	std::cerr << "Error in MeshLib::Element::getNFaceNodes() - Index does not exist." << std::endl;
+	return 0;
+}
+
 }
 
diff --git a/MeshLib/Elements/Pyramid.h b/MeshLib/Elements/Pyramid.h
index f22435e3a7e..35eb1da3837 100644
--- a/MeshLib/Elements/Pyramid.h
+++ b/MeshLib/Elements/Pyramid.h
@@ -44,9 +44,15 @@ public:
 	/// Destructor
 	virtual ~Pyramid();
 
+	/// Returns the face i of the element.
+	const Element* getFace(unsigned i) const;
+
 	/// Get the number of edges for this element.
 	unsigned getNEdges() const { return 8; };
 
+	/// Get the number of nodes for face i.
+	unsigned getNFaceNodes(unsigned i) const;
+
 	/// Get the number of faces for this element.
 	unsigned getNFaces() const { return 5; };
 
@@ -58,7 +64,14 @@ public:
 
 protected:
 	/// Calculates the volume of a prism by subdividing it into two tetrahedra.
-	double calcVolume();
+	double computeVolume();
+
+	/// Return a specific edge node.
+	inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; };
+
+	static const unsigned _face_nodes[5][4];
+	static const unsigned _edge_nodes[8][2];
+	static const unsigned _n_face_nodes[5];
 
 }; /* class */
 
diff --git a/MeshLib/Elements/Quad.cpp b/MeshLib/Elements/Quad.cpp
index 2fda1b6dfdd..573a738abac 100644
--- a/MeshLib/Elements/Quad.cpp
+++ b/MeshLib/Elements/Quad.cpp
@@ -12,6 +12,16 @@
 	
 namespace MeshLib {
 
+
+const unsigned Quad::_edge_nodes[4][2] =
+{
+	{0, 1}, // Edge 0
+	{1, 2}, // Edge 1
+	{0, 2}, // Edge 2
+	{0, 3}  // Edge 3
+};
+
+
 Quad::Quad(Node* nodes[4], unsigned value)
 	: Face(MshElemType::TRIANGLE, value)
 {
@@ -19,7 +29,7 @@ Quad::Quad(Node* nodes[4], unsigned value)
 	_neighbors = new Element*[4];
 	for (unsigned i=0; i<4; i++)
 		_neighbors[i] = NULL;
-	this->_area = this->calcArea();
+	this->_area = this->computeArea();
 }
 
 Quad::Quad(Node* n0, Node* n1, Node* n2, Node* n3, unsigned value)
@@ -33,7 +43,7 @@ Quad::Quad(Node* n0, Node* n1, Node* n2, Node* n3, unsigned value)
 	_neighbors = new Element*[4];
 	for (unsigned i=0; i<4; i++)
 		_neighbors[i] = NULL;
-	this->_area = this->calcArea();
+	this->_area = this->computeArea();
 }
 
 Quad::Quad(const Quad &quad)
@@ -53,7 +63,7 @@ Quad::~Quad()
 {
 }
 
-double Quad::calcArea()
+double Quad::computeArea()
 {
 	return MathLib::calcTriangleArea(_nodes[0]->getData(), _nodes[1]->getData(), _nodes[2]->getData())
          + MathLib::calcTriangleArea(_nodes[2]->getData(), _nodes[3]->getData(), _nodes[0]->getData());
diff --git a/MeshLib/Elements/Quad.h b/MeshLib/Elements/Quad.h
index fdc7aea0212..305ec5bb9a8 100644
--- a/MeshLib/Elements/Quad.h
+++ b/MeshLib/Elements/Quad.h
@@ -54,8 +54,12 @@ public:
 
 protected:
 	/// Calculates the area of a convex quadliteral by dividing it into two triangles.
-	double calcArea();
+	double computeArea();
 
+	/// Return a specific edge node.
+	inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; };
+
+	static const unsigned _edge_nodes[4][2];
 
 }; /* class */
 
diff --git a/MeshLib/Elements/Tet.cpp b/MeshLib/Elements/Tet.cpp
index c51918dd60d..3da481e49aa 100644
--- a/MeshLib/Elements/Tet.cpp
+++ b/MeshLib/Elements/Tet.cpp
@@ -7,11 +7,32 @@
 
 #include "Tet.h"
 #include "Node.h"
+#include "Tri.h"
 
 #include "MathTools.h"
 
 namespace MeshLib {
 
+
+const unsigned Tet::_face_nodes[4][3] =
+{
+	{0, 2, 1}, // Face 0
+	{0, 1, 3}, // Face 1
+	{1, 2, 3}, // Face 2
+	{2, 0, 3}  // Face 3
+};
+ 
+const unsigned Tet::_edge_nodes[6][2] =
+{
+	{0, 1}, // Edge 0
+	{1, 2}, // Edge 1
+	{0, 2}, // Edge 2
+	{0, 3}, // Edge 3
+	{1, 3}, // Edge 4
+	{2, 3}  // Edge 5
+};
+
+
 Tet::Tet(Node* nodes[4], unsigned value)
 	: Cell(MshElemType::TETRAHEDRON, value)
 {
@@ -19,7 +40,7 @@ Tet::Tet(Node* nodes[4], unsigned value)
 	_neighbors = new Element*[4];
 	for (unsigned i=0; i<4; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Tet::Tet(Node* n0, Node* n1, Node* n2, Node* n3, unsigned value)
@@ -33,7 +54,7 @@ Tet::Tet(Node* n0, Node* n1, Node* n2, Node* n3, unsigned value)
 	_neighbors = new Element*[4];
 	for (unsigned i=0; i<4; i++)
 		_neighbors[i] = NULL;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 }
 
 Tet::Tet(unsigned value)
@@ -61,10 +82,24 @@ Tet::~Tet()
 {
 }
 
-double Tet::calcVolume()
+double Tet::computeVolume()
 {
 	return MathLib::calcTetrahedronVolume(_nodes[0]->getData(), _nodes[1]->getData(), _nodes[2]->getData(), _nodes[3]->getData());
 }
 
+const Element* Tet::getFace(unsigned i) const
+{
+	if (i<this->getNFaces())
+	{
+		unsigned nFaceNodes (this->getNFaceNodes(i));
+		Node** nodes = new Node*[nFaceNodes];
+		for (unsigned j=0; j<nFaceNodes; j++)
+			nodes[j] = _nodes[_face_nodes[i][j]];
+		return new Tri(nodes);
+	}
+	std::cerr << "Error in MeshLib::Element::getFace() - Index does not exist." << std::endl;
+	return NULL;
+}
+
 }
 
diff --git a/MeshLib/Elements/Tet.h b/MeshLib/Elements/Tet.h
index a9b7f4dd8b1..8eed8e4cd70 100644
--- a/MeshLib/Elements/Tet.h
+++ b/MeshLib/Elements/Tet.h
@@ -45,9 +45,15 @@ public:
 	/// Destructor
 	virtual ~Tet();
 
+	/// Returns the face i of the element.
+	const Element* getFace(unsigned i) const;
+
 	/// Get the number of edges for this element.
 	unsigned getNEdges() const { return 6; };
 	
+	/// Get the number of nodes for face i.
+	unsigned getNFaceNodes(unsigned i) const { return 3; };
+
 	/// Get the number of faces for this element.
 	unsigned getNFaces() const { return 4; };
 
@@ -62,7 +68,13 @@ protected:
 	Tet(unsigned value = 0);
 
 	/// Calculates the volume of a tetrahedron via the determinant of the matrix given by its four points.
-	double calcVolume();
+	double computeVolume();
+
+	/// Return a specific edge node.
+	inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; };
+
+	static const unsigned _face_nodes[4][3];
+	static const unsigned _edge_nodes[6][2];
 
 }; /* class */
 
diff --git a/MeshLib/Elements/Tet10.cpp b/MeshLib/Elements/Tet10.cpp
index c795668dc0e..cd65836d38f 100644
--- a/MeshLib/Elements/Tet10.cpp
+++ b/MeshLib/Elements/Tet10.cpp
@@ -14,7 +14,7 @@ Tet10::Tet10(Node* nodes[10], unsigned value)
 	: Tet(value), FemElem()
 {
 	_nodes = nodes;
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 	this->calcCentroid();
 }
 
@@ -31,7 +31,7 @@ Tet10::Tet10(const Tet &tet)
 		//TODO: Calculate additional nodes!
 	}
 
-	this->_volume = this->calcVolume();
+	this->_volume = this->computeVolume();
 	this->calcCentroid();
 }
 
diff --git a/MeshLib/Elements/Tri.cpp b/MeshLib/Elements/Tri.cpp
index dde86a7170c..ebb911d3929 100644
--- a/MeshLib/Elements/Tri.cpp
+++ b/MeshLib/Elements/Tri.cpp
@@ -12,6 +12,15 @@
 
 namespace MeshLib {
 
+
+const unsigned Tri::_edge_nodes[3][2] =
+{
+	{0, 1}, // Edge 0
+	{1, 2}, // Edge 1
+	{0, 2}  // Edge 2
+};
+
+
 Tri::Tri(Node* nodes[3], unsigned value)
 	: Face(MshElemType::TRIANGLE, value)
 {
@@ -19,7 +28,7 @@ Tri::Tri(Node* nodes[3], unsigned value)
 	_neighbors = new Element*[3];
 	for (unsigned i=0; i<3; i++)
 		_neighbors[i] = NULL;
-	this->_area = this->calcArea();
+	this->_area = this->computeArea();
 }
 
 Tri::Tri(Node* n0, Node* n1, Node* n2, unsigned value)
@@ -32,7 +41,7 @@ Tri::Tri(Node* n0, Node* n1, Node* n2, unsigned value)
 	_neighbors = new Element*[3];
 	for (unsigned i=0; i<3; i++)
 		_neighbors[i] = NULL;
-	this->_area = this->calcArea();
+	this->_area = this->computeArea();
 }
 
 Tri::Tri(const Tri &tri)
@@ -52,7 +61,7 @@ Tri::~Tri()
 {
 }
 
-double Tri::calcArea()
+double Tri::computeArea()
 {
 	return MathLib::calcTriangleArea(_nodes[0]->getData(), _nodes[1]->getData(), _nodes[2]->getData());
 }
diff --git a/MeshLib/Elements/Tri.h b/MeshLib/Elements/Tri.h
index 37abfecfd2e..9ab7c925081 100644
--- a/MeshLib/Elements/Tri.h
+++ b/MeshLib/Elements/Tri.h
@@ -54,7 +54,12 @@ public:
 
 protected:
 	/// Calculates the area of the triangle by returning half of the area of the corresponding parallelogram.
-	double calcArea();
+	double computeArea();
+
+	/// Return a specific edge node.
+	inline Node* getEdgeNode(unsigned edge_id, unsigned node_id) const { return _nodes[_edge_nodes[edge_id][node_id]]; };
+	
+	static const unsigned _edge_nodes[3][2];
 
 }; /* class */
 
diff --git a/MeshLib/Mesh.cpp b/MeshLib/Mesh.cpp
index d9784233051..cf99e0ea349 100644
--- a/MeshLib/Mesh.cpp
+++ b/MeshLib/Mesh.cpp
@@ -20,6 +20,7 @@ namespace MeshLib {
 Mesh::Mesh(const std::string &name, const std::vector<Node*> &nodes, const std::vector<Element*> &elements)
 	: _name(name), _nodes(nodes), _elements(elements)
 {
+	double _edge_length[2] = {0, 0};
 	this->makeNodesUnique();
 	this->setElementInformationForNodes();
 	this->setNeighborInformationForElements();
diff --git a/MeshLib/Mesh.h b/MeshLib/Mesh.h
index abdfbe036b9..9959cc8d89c 100644
--- a/MeshLib/Mesh.h
+++ b/MeshLib/Mesh.h
@@ -40,6 +40,12 @@ public:
 	/// Add an element to the mesh.
 	void addElement(Element* elem);
 
+	/// Get the minimum edge length over all elements of the mesh.
+	double getMinEdgeLength() { return _edge_length[0]; };
+
+	/// Get the maximum edge length over all elements of the mesh.
+	double getMaxEdgeLength() { return _edge_length[1]; };
+
 	/// Get the node with the given index.
 	const Node* getNode(unsigned idx) const { return _nodes[idx]; };
 
@@ -71,6 +77,7 @@ protected:
 	/// Fills in the neighbor-information for elements.
 	void setNeighborInformationForElements();
 
+	static double _edge_length[2];
 	std::string _name;
 	std::vector<Node*> _nodes;
 	std::vector<Element*> _elements;
-- 
GitLab