From 3c6a1ee5eccaaa434b19b6d9da83432afe716abb Mon Sep 17 00:00:00 2001
From: Norihiro Watanabe <norihiro.watanabe@ufz.de>
Date: Thu, 4 Sep 2014 19:08:13 +0200
Subject: [PATCH] introduce BoundaryElementsAlongPolyline and
 BoundaryElementsAlongSurface to own boundary elements

---
 .../BoundaryElementsAlongPolyline.cpp         | 67 +++++++++++++++
 .../BoundaryElementsAlongPolyline.h           | 69 ++++++++++++++++
 .../BoundaryElementsAlongSurface.cpp          | 56 +++++++++++++
 .../BoundaryElementsAlongSurface.h            | 69 ++++++++++++++++
 MeshGeoToolsLib/BoundaryElementsSearcher.cpp  | 81 ++++++++++++-------
 MeshGeoToolsLib/BoundaryElementsSearcher.h    | 45 +++++++----
 6 files changed, 341 insertions(+), 46 deletions(-)
 create mode 100644 MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp
 create mode 100644 MeshGeoToolsLib/BoundaryElementsAlongPolyline.h
 create mode 100644 MeshGeoToolsLib/BoundaryElementsAlongSurface.cpp
 create mode 100644 MeshGeoToolsLib/BoundaryElementsAlongSurface.h

diff --git a/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp b/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp
new file mode 100644
index 00000000000..8c5ef49e5cb
--- /dev/null
+++ b/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp
@@ -0,0 +1,67 @@
+/**
+ * @copyright
+ * Copyright (c) 2012-2014, 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 "BoundaryElementsAlongPolyline.h"
+
+#include "GeoLib/Polyline.h"
+
+#include "MeshLib/Mesh.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/MeshSearcher.h"
+
+#include "MeshGeoToolsLib/MeshNodeSearcher.h"
+
+namespace MeshGeoToolsLib
+{
+
+BoundaryElementsAlongPolyline::BoundaryElementsAlongPolyline(MeshLib::Mesh const& mesh, MeshNodeSearcher &mshNodeSearcher, GeoLib::Polyline const& ply)
+: _mesh(mesh), _ply(ply)
+{
+	// search elements near the polyline
+	auto node_ids_on_poly = mshNodeSearcher.getMeshNodeIDsAlongPolyline(ply);
+	auto ele_ids_near_poly = MeshLib::getConnectedElementIDs(_mesh, node_ids_on_poly);
+
+	// get a list of edges made of the nodes
+	for (auto ele_id : ele_ids_near_poly) {
+		auto* e = _mesh.getElement(ele_id);
+		// skip internal elements
+		bool isOuterElement = false;
+		for (unsigned i=0; i<e->getNNeighbors(); i++) {
+			if (!e->getNeighbor(i)) {
+				isOuterElement = true;
+				break;
+			}
+		}
+		if (!isOuterElement)
+			continue;
+		// find edges on polyline
+		for (unsigned i=0; i<e->getNEdges(); i++) {
+			auto* edge = e->getEdge(i);
+			// check
+			size_t cnt_match = 0;
+			for (size_t j=0; j<edge->getNNodes(); j++) {
+				if (std::find(node_ids_on_poly.begin(), node_ids_on_poly.end(), edge->getNodeIndex(j)) != node_ids_on_poly.end())
+					cnt_match++;
+				else
+					break;
+			}
+			// update the list
+			if (cnt_match==edge->getNNodes())
+				_boundary_elements.push_back(const_cast<MeshLib::Element*>(edge));
+		}
+	}
+}
+
+BoundaryElementsAlongPolyline::~BoundaryElementsAlongPolyline()
+{
+	for (auto p : _boundary_elements)
+		delete p;
+}
+
+} // end namespace MeshGeoTools
+
diff --git a/MeshGeoToolsLib/BoundaryElementsAlongPolyline.h b/MeshGeoToolsLib/BoundaryElementsAlongPolyline.h
new file mode 100644
index 00000000000..3374d0a7a7f
--- /dev/null
+++ b/MeshGeoToolsLib/BoundaryElementsAlongPolyline.h
@@ -0,0 +1,69 @@
+/**
+ * @copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/LICENSE.txt
+ */
+#ifndef BOUNDARYELEMENTSALONGPOLYLINE_H_
+#define BOUNDARYELEMENTSALONGPOLYLINE_H_
+
+#include <vector>
+
+namespace GeoLib
+{
+class Polyline;
+}
+
+namespace MeshLib
+{
+class Mesh;
+class Element;
+}
+
+namespace MeshGeoToolsLib
+{
+class MeshNodeSearcher;
+
+/**
+ * This class collects element edges located along a polyline.
+ * Note that internal edges are not collected in this class.
+ */
+class BoundaryElementsAlongPolyline
+{
+public:
+	/**
+	 * Constructor
+	 * @param mesh             a mesh object
+	 * @param mshNodeSearcher  a MeshNodeSearcher object which is internally used to search mesh nodes
+	 * @param ply              a polyline object where edges are searched
+	 */
+	BoundaryElementsAlongPolyline(MeshLib::Mesh const& mesh, MeshNodeSearcher &mshNodeSearcher, GeoLib::Polyline const& ply);
+
+	/// destructor
+	virtual ~BoundaryElementsAlongPolyline();
+
+	/// return the mesh object
+	MeshLib::Mesh const& getMesh() const {return _mesh;}
+
+	/**
+	 * Deploying this method the user can get access to the underlying
+	 * GeoLib::Polyline.
+	 * @return the underlying GeoLib::Polyline
+	 */
+	GeoLib::Polyline const& getPolyline () const {return _ply;}
+
+	/**
+	 * Return the vector of boundary elements
+	 */
+	std::vector<MeshLib::Element*> const& getBoundaryElements() const {return _boundary_elements; }
+
+private:
+	MeshLib::Mesh const& _mesh;
+	GeoLib::Polyline const& _ply;
+	std::vector<MeshLib::Element*> _boundary_elements;
+};
+
+} // end namespace MeshGeoTools
+
+#endif /* BOUNDARYELEMENTSALONGPOLYLINE_H_ */
diff --git a/MeshGeoToolsLib/BoundaryElementsAlongSurface.cpp b/MeshGeoToolsLib/BoundaryElementsAlongSurface.cpp
new file mode 100644
index 00000000000..2c8e4511aab
--- /dev/null
+++ b/MeshGeoToolsLib/BoundaryElementsAlongSurface.cpp
@@ -0,0 +1,56 @@
+/**
+ * @copyright
+ * Copyright (c) 2012-2014, 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 "BoundaryElementsAlongSurface.h"
+
+#include "GeoLib/Surface.h"
+
+#include "MeshLib/Mesh.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/MeshSearcher.h"
+
+#include "MeshGeoToolsLib/MeshNodeSearcher.h"
+
+namespace MeshGeoToolsLib
+{
+
+BoundaryElementsAlongSurface::BoundaryElementsAlongSurface(MeshLib::Mesh const& mesh, MeshNodeSearcher &mshNodeSearcher, GeoLib::Surface const& sfc)
+: _mesh(mesh), _sfc(sfc)
+{
+	// search elements near the polyline
+	auto node_ids_on_sfc = mshNodeSearcher.getMeshNodeIDsAlongSurface(sfc);
+	auto ele_ids_near_sfc = MeshLib::getConnectedElementIDs(_mesh, node_ids_on_sfc);
+
+	// get a list of edges made of the nodes
+	for (auto ele_id : ele_ids_near_sfc) {
+		auto* e = _mesh.getElement(ele_id);
+		for (unsigned i=0; i<e->getNEdges(); i++) {
+			auto* edge = e->getEdge(i);
+			// check
+			size_t cnt_match = 0;
+			for (size_t j=0; j<edge->getNNodes(); j++) {
+				if (std::find(node_ids_on_sfc.begin(), node_ids_on_sfc.end(), edge->getNodeIndex(j)) != node_ids_on_sfc.end())
+					cnt_match++;
+				else
+					break;
+			}
+			// update the list
+			if (cnt_match==edge->getNNodes())
+				_boundary_elements.push_back(const_cast<MeshLib::Element*>(edge));
+		}
+	}
+}
+
+BoundaryElementsAlongSurface::~BoundaryElementsAlongSurface()
+{
+	for (auto p : _boundary_elements)
+		delete p;
+}
+
+} // end namespace MeshGeoTools
+
diff --git a/MeshGeoToolsLib/BoundaryElementsAlongSurface.h b/MeshGeoToolsLib/BoundaryElementsAlongSurface.h
new file mode 100644
index 00000000000..c4d4e209f58
--- /dev/null
+++ b/MeshGeoToolsLib/BoundaryElementsAlongSurface.h
@@ -0,0 +1,69 @@
+/**
+ * @copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/LICENSE.txt
+ */
+#ifndef BOUNDARYELEMENTSALONGSURFACE_H_
+#define BOUNDARYELEMENTSALONGSURFACE_H_
+
+#include <vector>
+
+namespace GeoLib
+{
+class Surface;
+}
+
+namespace MeshLib
+{
+class Mesh;
+class Element;
+}
+
+namespace MeshGeoToolsLib
+{
+class MeshNodeSearcher;
+
+/**
+ * This class collects element faces located along a surface.
+ * Note that internal faces are not collected in this class.
+ */
+class BoundaryElementsAlongSurface
+{
+public:
+	/**
+	 * Constructor
+	 * @param mesh             a mesh object
+	 * @param mshNodeSearcher  a MeshNodeSearcher object which is internally used to search mesh nodes
+	 * @param sfc              a surface object where face elements are searched for
+	 */
+	BoundaryElementsAlongSurface(MeshLib::Mesh const& mesh, MeshNodeSearcher &mshNodeSearcher, GeoLib::Surface const& sfc);
+
+	/// destructor
+	virtual ~BoundaryElementsAlongSurface();
+
+	/// return the mesh object
+	MeshLib::Mesh const& getMesh() const {return _mesh;}
+
+	/**
+	 * Deploying this method the user can get access to the underlying
+	 * GeoLib::Surface.
+	 * @return the underlying GeoLib::Surface
+	 */
+	GeoLib::Surface const& getSurface() const {return _sfc;}
+
+	/**
+	 * Return the vector of boundary elements
+	 */
+	std::vector<MeshLib::Element*> const& getBoundaryElements() const {return _boundary_elements;}
+
+private:
+	MeshLib::Mesh const& _mesh;
+	GeoLib::Surface const& _sfc;
+	std::vector<MeshLib::Element*> _boundary_elements;
+};
+
+} // end namespace MeshGeoTools
+
+#endif /* BOUNDARYELEMENTSALONGSURFACE_H_ */
diff --git a/MeshGeoToolsLib/BoundaryElementsSearcher.cpp b/MeshGeoToolsLib/BoundaryElementsSearcher.cpp
index 6a39db82578..5b623037bcb 100644
--- a/MeshGeoToolsLib/BoundaryElementsSearcher.cpp
+++ b/MeshGeoToolsLib/BoundaryElementsSearcher.cpp
@@ -1,6 +1,6 @@
 /**
  * @copyright
- * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/LICENSE.txt
@@ -8,58 +8,77 @@
 
 #include "BoundaryElementsSearcher.h"
 
+#include "GeoLib/GeoObject.h"
+#include "GeoLib/Polyline.h"
+#include "GeoLib/Surface.h"
+
+#include "MeshLib/Mesh.h"
 #include "MeshLib/Elements/Element.h"
 #include "MeshLib/MeshSearcher.h"
 
+#include "MeshGeoToolsLib/MeshNodeSearcher.h"
+#include "MeshGeoToolsLib/BoundaryElementsAlongPolyline.h"
+#include "MeshGeoToolsLib/BoundaryElementsAlongSurface.h"
+
+
 namespace MeshGeoToolsLib
 {
 
 BoundaryElementsSearcher::BoundaryElementsSearcher(MeshLib::Mesh const& mesh, MeshNodeSearcher &mshNodeSearcher) : _mesh(mesh), _mshNodeSearcher(mshNodeSearcher)
 {}
 
-std::vector<MeshLib::Element*> BoundaryElementsSearcher::getBoundaryElements(GeoLib::GeoObject const& geoObj)
+BoundaryElementsSearcher::~BoundaryElementsSearcher()
+{
+	for (auto p : _boundary_elements_along_polylines)
+		delete p;
+	for (auto p : _boundary_elements_along_surfaces)
+		delete p;
+}
+
+std::vector<MeshLib::Element*> const& BoundaryElementsSearcher::getBoundaryElements(GeoLib::GeoObject const& geoObj)
 {
-	std::vector<MeshLib::Element*> vec_elements;
 	switch (geoObj.getGeoType()) {
 	case GeoLib::GEOTYPE::POLYLINE:
-		vec_elements = this->getBoundaryElementsAlongPolyline(*dynamic_cast<const GeoLib::Polyline*>(&geoObj));
+		return this->getBoundaryElementsAlongPolyline(*dynamic_cast<const GeoLib::Polyline*>(&geoObj));
 		break;
-	default:
+	case GeoLib::GEOTYPE::SURFACE:
+		return this->getBoundaryElementsAlongSurface(*dynamic_cast<const GeoLib::Surface*>(&geoObj));
 		break;
+	default:
+		const static std::vector<MeshLib::Element*> dummy;
+		return dummy;
 	}
-	return vec_elements;
 }
 
-std::vector<MeshLib::Element*> BoundaryElementsSearcher::getBoundaryElementsAlongPolyline(GeoLib::Polyline const& ply)
+std::vector<MeshLib::Element*> const& BoundaryElementsSearcher::getBoundaryElementsAlongPolyline(GeoLib::Polyline const& ply)
 {
-	// serach elements near the polyline
-	auto node_ids_on_poly = _mshNodeSearcher.getMeshNodeIDsAlongPolyline(ply);
-	auto ele_ids_near_poly = MeshLib::getConnectedElementIDs(_mesh, node_ids_on_poly);
-
-	// get a list of edges made of the nodes
-	std::vector<MeshLib::Element*> vec_edges_on_poly;
-	for (auto ele_id : ele_ids_near_poly) {
-		auto* e = _mesh.getElement(ele_id);
-		for (unsigned i=0; i<e->getNEdges(); i++) {
-			auto* edge = e->getEdge(i);
-			//TODO where should we store and delete this new object?
-			//TODO avoid duplicated entries
-			// check
-			size_t cnt_match = 0;
-			for (size_t j=0; j<edge->getNNodes(); j++) {
-				if (std::find(node_ids_on_poly.begin(), node_ids_on_poly.end(), edge->getNodeIndex(j)) != node_ids_on_poly.end())
-					cnt_match++;
-				else
-					break;
-			}
-			// update the list
-			if (cnt_match==edge->getNNodes())
-				vec_edges_on_poly.push_back(const_cast<MeshLib::Element*>(edge));
+	std::vector<BoundaryElementsAlongPolyline*>::const_iterator it(_boundary_elements_along_polylines.begin());
+	for (; it != _boundary_elements_along_polylines.end(); ++it) {
+		if (&(*it)->getPolyline() == &ply) {
+			// we calculated mesh nodes for this polyline already
+			return (*it)->getBoundaryElements();
 		}
 	}
-	return vec_edges_on_poly;
+
+	_boundary_elements_along_polylines.push_back(
+			new BoundaryElementsAlongPolyline(_mesh, _mshNodeSearcher, ply));
+	return _boundary_elements_along_polylines.back()->getBoundaryElements();
 }
 
+std::vector<MeshLib::Element*> const& BoundaryElementsSearcher::getBoundaryElementsAlongSurface(GeoLib::Surface const& sfc)
+{
+	std::vector<BoundaryElementsAlongSurface*>::const_iterator it(_boundary_elements_along_surfaces.begin());
+	for (; it != _boundary_elements_along_surfaces.end(); ++it) {
+		if (&(*it)->getSurface() == &sfc) {
+			// we calculated mesh nodes for this surface already
+			return (*it)->getBoundaryElements();
+		}
+	}
+
+	_boundary_elements_along_surfaces.push_back(
+			new BoundaryElementsAlongSurface(_mesh, _mshNodeSearcher, sfc));
+	return _boundary_elements_along_surfaces.back()->getBoundaryElements();
+}
 
 } // end namespace MeshGeoTools
 
diff --git a/MeshGeoToolsLib/BoundaryElementsSearcher.h b/MeshGeoToolsLib/BoundaryElementsSearcher.h
index 3dc41aabec8..98f083b344f 100644
--- a/MeshGeoToolsLib/BoundaryElementsSearcher.h
+++ b/MeshGeoToolsLib/BoundaryElementsSearcher.h
@@ -1,6 +1,6 @@
 /**
  * @copyright
- * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/LICENSE.txt
@@ -10,23 +10,28 @@
 
 #include <vector>
 
-// GeoLib
-#include "Point.h"
-#include "Polyline.h"
-
-// MeshLib
-#include "Mesh.h"
-#include "Node.h"
+namespace GeoLib
+{
+class GeoObject;
+class Polyline;
+class Surface;
+}
 
-// MeshGeoToolsLib
-#include "MeshNodeSearcher.h"
+namespace MeshLib
+{
+class Mesh;
+class Element;
+}
 
 namespace MeshGeoToolsLib
 {
+class MeshNodeSearcher;
+class BoundaryElementsAlongPolyline;
+class BoundaryElementsAlongSurface;
 
 /**
- * This class searches and creates boundary elements located on a given geometric object.
- * Boundary elements will be created from edges or faces of existing domain elements.
+ * This class searches boundary elements located on a given geometric object, i.e. polyline and surface.
+ * Note that internal boundaries are currently not supported.
  */
 class BoundaryElementsSearcher
 {
@@ -39,7 +44,7 @@ public:
 	BoundaryElementsSearcher(MeshLib::Mesh const& mesh, MeshNodeSearcher &mshNodeSearcher);
 
 	/// destructor
-	virtual ~BoundaryElementsSearcher() {}
+	virtual ~BoundaryElementsSearcher();
 
 	/**
 	 * generate boundary elements on the given geometric object (point, polyline, surface).
@@ -47,18 +52,28 @@ public:
 	 * @param geoObj a GeoLib::GeoObject where the nearest mesh node is searched for
 	 * @return a vector of boundary element objects
 	 */
-	std::vector<MeshLib::Element*> getBoundaryElements(GeoLib::GeoObject const& geoObj);
+	std::vector<MeshLib::Element*> const& getBoundaryElements(GeoLib::GeoObject const& geoObj);
 
 	/**
 	 * generate boundary elements on the given polyline.
 	 * @param ply the GeoLib::Polyline the nearest mesh nodes are searched for
 	 * @return a vector of boundary element objects
 	 */
-	std::vector<MeshLib::Element*> getBoundaryElementsAlongPolyline(GeoLib::Polyline const& ply);
+	std::vector<MeshLib::Element*> const& getBoundaryElementsAlongPolyline(GeoLib::Polyline const& ply);
+
+	/**
+	 * generate boundary elements on the given surface.
+	 * @param sfc the GeoLib::Surface the nearest mesh nodes are searched for
+	 * @return a vector of boundary element objects
+	 */
+	std::vector<MeshLib::Element*> const& getBoundaryElementsAlongSurface(GeoLib::Surface const& sfc);
+
 
 private:
 	MeshLib::Mesh const& _mesh;
 	MeshNodeSearcher &_mshNodeSearcher;
+	std::vector<BoundaryElementsAlongPolyline*> _boundary_elements_along_polylines;
+	std::vector<BoundaryElementsAlongSurface*> _boundary_elements_along_surfaces;
 };
 
 } // end namespace MeshGeoTools
-- 
GitLab