From e0147442149a1bdf77ec82e43b4f922f8c342b4c Mon Sep 17 00:00:00 2001
From: Karsten Rink <karsten.rink@ufz.de>
Date: Fri, 10 Aug 2012 10:16:05 +0200
Subject: [PATCH] added first version to find and store neighbours of all
 elements during mesh initialisation (work in progress)

---
 GeoLib/Station.cpp                 |  2 +-
 GeoLib/Station.h                   |  2 +-
 MeshLib/Elements/Element.cpp       | 32 ++++++++++++++++++++++
 MeshLib/Elements/Element.h         |  7 +++++
 MeshLib/Elements/Face.cpp          |  4 +--
 MeshLib/Elements/Face.h            |  2 +-
 MeshLib/Mesh.cpp                   | 43 ++++++++++++++++++++++--------
 MeshLib/Node.h                     |  6 ++---
 SimpleTests/MeshTests/MeshRead.cpp | 11 ++++++++
 9 files changed, 89 insertions(+), 20 deletions(-)

diff --git a/GeoLib/Station.cpp b/GeoLib/Station.cpp
index 6a04446937c..fa8205bccf7 100644
--- a/GeoLib/Station.cpp
+++ b/GeoLib/Station.cpp
@@ -243,7 +243,7 @@ int StationBorehole::addLayer(std::list<std::string> fields, StationBorehole* bo
 	return 1;
 }
 
-int StationBorehole::addStratigraphy(const std::vector<Point*> &profile, const std::vector<std::string> soil_names)
+int StationBorehole::addStratigraphy(const std::vector<Point*> &profile, const std::vector<std::string> &soil_names)
 {
 	if (((profile.size()-1) == soil_names.size()) && (soil_names.size()>0))
 	{
diff --git a/GeoLib/Station.h b/GeoLib/Station.h
index 0005b310a8a..4333eaf814d 100644
--- a/GeoLib/Station.h
+++ b/GeoLib/Station.h
@@ -221,7 +221,7 @@ public:
 	                                      std::string date = "");
 
 	/// Adds a stratigraphy to a borehole given a vector of points of length "n" and a vector of soil names of length "n-1".
-	int addStratigraphy(const std::vector<Point*> &profile, const std::vector<std::string> soil_names);
+	int addStratigraphy(const std::vector<Point*> &profile, const std::vector<std::string> &soil_names);
 
 	/// Reads the stratigraphy for a specified station from a file
 	static int addStratigraphy(const std::string &path, StationBorehole* borehole);
diff --git a/MeshLib/Elements/Element.cpp b/MeshLib/Elements/Element.cpp
index b952c3fe319..7341c11e565 100644
--- a/MeshLib/Elements/Element.cpp
+++ b/MeshLib/Elements/Element.cpp
@@ -33,6 +33,38 @@ Element::~Element()
 	delete[] this->_nodes;
 }
 
+bool Element::addNeighbor(Element* e)
+{
+	unsigned n(0);
+	unsigned nNeighbors (this->getNNeighbors());
+	for (n=0; n<nNeighbors; n++)
+	{
+		if (this->_neighbors[n] == e)
+			return false;
+		if (this->_neighbors[n] == NULL)
+			break;
+	}
+
+	if (n<nNeighbors)
+	{
+		const unsigned nNodes (this->getNNodes());
+		const unsigned eNodes (e->getNNodes());
+		const Node* const* e_nodes = e->getNodes();
+		unsigned count(0);
+		for (unsigned i(0); i<nNodes; i++)
+			for (unsigned j(0); j<eNodes; j++)
+				if (_nodes[i] == e_nodes[j])
+					//std::cout << _nodes[i]->getID() << " == " << e_nodes[j]->getID() << std::endl;
+					// increment shared nodes counter and check if enough nodes are similar to be sure e is a neighbour of this
+					if ((++count)>=this->getDimension())
+					{
+						_neighbors[n]=e;
+						return true;
+					}
+	}
+	return false;
+}
+
 const Element* Element::getEdge(unsigned i) const
 {
 	if (i < getNEdges())
diff --git a/MeshLib/Elements/Element.h b/MeshLib/Elements/Element.h
index fe665baf358..2ff19bc4114 100644
--- a/MeshLib/Elements/Element.h
+++ b/MeshLib/Elements/Element.h
@@ -35,6 +35,13 @@ public:
 	/// Compute the minimum and maximum squared edge length for this element
 	virtual void computeSqrEdgeLengthRange(double &min, double &max) const;
 
+	/**
+	 * \brief Tries to add an element e as neighbour to this element. 
+	 * If the elements really are neighbours, the element is added to the
+	 * neighbour-ist and true is returned. Otherwise false is returned.
+	 */
+	bool addNeighbor(Element* e);
+
 	/// Returns the length, area or volume of a 1D, 2D or 3D element
 	virtual double getContent() const = 0;
 
diff --git a/MeshLib/Elements/Face.cpp b/MeshLib/Elements/Face.cpp
index d3d097fe2fd..eb9d58c362d 100644
--- a/MeshLib/Elements/Face.cpp
+++ b/MeshLib/Elements/Face.cpp
@@ -34,7 +34,7 @@ Face::~Face()
 	delete[] this->_neighbors;
 }
 
-const double* Face::getSurfaceNormal() const
+void Face::getSurfaceNormal(double normal[3]) const
 {
 	const double edge1[3] = { (*this->_nodes[0])[0]-(*this->_nodes[1])[0],
 				 			  (*this->_nodes[0])[1]-(*this->_nodes[1])[1],
@@ -42,9 +42,7 @@ const double* Face::getSurfaceNormal() const
 	const double edge2[3] = { (*this->_nodes[1])[0]-(*this->_nodes[2])[0],
 							  (*this->_nodes[1])[1]-(*this->_nodes[2])[1],
 							  (*this->_nodes[1])[2]-(*this->_nodes[2])[2] };
-	double normal[3];
 	MathLib::crossProd(edge1, edge2, normal);
-	return normal;
 }
 
 }
diff --git a/MeshLib/Elements/Face.h b/MeshLib/Elements/Face.h
index 1aa9e38f739..5da618a501e 100644
--- a/MeshLib/Elements/Face.h
+++ b/MeshLib/Elements/Face.h
@@ -43,7 +43,7 @@ public:
 	unsigned getNFaces() const { return 0; };
 
 	/// Returns the surface normal of a 2D element.
-	const double* getSurfaceNormal() const;
+	void getSurfaceNormal(double normal[3]) const;
 
 	/// Destructor
 	virtual ~Face();
diff --git a/MeshLib/Mesh.cpp b/MeshLib/Mesh.cpp
index 98573cab59f..b92bf46f9b6 100644
--- a/MeshLib/Mesh.cpp
+++ b/MeshLib/Mesh.cpp
@@ -35,6 +35,8 @@ Mesh::Mesh(const std::string &name, const std::vector<Node*> &nodes, const std::
 Mesh::Mesh(const Mesh &mesh)
 	: _name(mesh.getName()), _nodes(mesh.getNodes()), _elements(mesh.getElements())
 {
+	this->setElementInformationForNodes();
+	this->setNeighborInformationForElements();
 }
 
 Mesh::~Mesh()
@@ -105,21 +107,40 @@ void Mesh::setEdgeLengthRange(const double &min_length, const double &max_length
 
 void Mesh::setNeighborInformationForElements()
 {
-	/* TODO
-	const size_t nElements(_elements.size());
-	std::vector<std::vector<char>> nb (nElements, std::vector<char>(nElements));
-
-	for (unsigned i=0; i<nElements; i++)
+	const size_t nElements = _elements.size();
+	for (unsigned m(0); m<nElements; m++)
 	{
-		Element* elem = _elements[i];
-		const size_t nNodes (elem->getNNodes());
-		for (unsigned j=0; j<nNodes; j++)
+		// create vector with all elements connected to current element (includes lots of doubles!)
+		std::vector<Element*> neighbors;
+		const size_t nNodes (_elements[m]->getNNodes());
+		for (unsigned n(0); n<nNodes; n++)
 		{
-			const Node* node = elem->getNode(j);
-
+			const std::vector<Element*> conn_elems (_elements[m]->getNode(n)->getElements());
+			neighbors.insert(neighbors.end(), conn_elems.begin(), conn_elems.end());
 		}
+		
+		const unsigned nNeighbors ( neighbors.size() );
+		/*std::vector<bool> done (nNeighbors, false);
+		// mark off the element itself
+		for (unsigned j(0); j<nNeighbors; j++)
+			if (neighbors[j] == _elements[m])
+				done[j] = true;
+				*/
+		// check if connected element is indeed a neighbour and mark all doubles of that element as 'done'
+		for (unsigned i(0); i<nNeighbors; i++)
+			//if (!done[i])
+			{
+				if (_elements[m]->addNeighbor(neighbors[i]))
+				{
+					neighbors[i]->addNeighbor(_elements[m]);
+				}/*
+					for (unsigned j(0); j<nNeighbors; j++)
+						if (!done[j] && (neighbors[j] == neighbors[i]))
+							done[j] = true;
+							*/
+					
+			}
 	}
-	*/
 }
 
 }
diff --git a/MeshLib/Node.h b/MeshLib/Node.h
index aa59cc0230d..0514b963d87 100644
--- a/MeshLib/Node.h
+++ b/MeshLib/Node.h
@@ -48,7 +48,7 @@ public:
 	const Element* getElement(unsigned idx) const { return _elements[idx]; };
 
 	/// Get all elements the node is part of.
-	const std::vector<const Element*> getElements() const { return _elements; };
+	const std::vector<Element*> getElements() const { return _elements; };
 
 	/// Get number of elements the node is part of.
 	size_t getNElements() const { return _elements.size(); };
@@ -61,9 +61,9 @@ protected:
 	 * Add an element the node is part of.
 	 * This method is called by Mesh::addElement(Element*), see friend definition.
 	 */
-	void addElement(const Element* elem) { _elements.push_back(elem); };
+	void addElement(Element* elem) { _elements.push_back(elem); };
 
-	std::vector<const Element*> _elements;
+	std::vector<Element*> _elements;
 
 }; /* class */
 
diff --git a/SimpleTests/MeshTests/MeshRead.cpp b/SimpleTests/MeshTests/MeshRead.cpp
index 0dadf05f8bb..49b513f9f3f 100644
--- a/SimpleTests/MeshTests/MeshRead.cpp
+++ b/SimpleTests/MeshTests/MeshRead.cpp
@@ -55,6 +55,17 @@ int main(int argc, char *argv[])
 //	std::cout << "time for reading: " << run_time.elapsed() << " s" << std::endl;
 	INFO ("time for reading: %f s", run_time.elapsed());
 #endif
+/*
+	unsigned elem_id = 1;
+	const MeshLib::Element* e = mesh->getElement(elem_id);
+	const size_t nElems = mesh->getNElements();
+	for (unsigned i=0; i< e->getNNeighbors(); i++)
+	{
+		for (unsigned j=0; j< nElems; j++)
+			if (mesh->getElement(j) == e->getNeighbor(i))
+				std::cout << "neighbour of " << elem_id << " : " << j << std::endl;
+	}
+*/
 	delete mesh;
 	delete logogCout;
 	LOGOG_SHUTDOWN();
-- 
GitLab