From 20368df10a55be52c03d3011b37403071f5a74f7 Mon Sep 17 00:00:00 2001
From: Norihiro Watanabe <norihiro.watanabe@ufz.de>
Date: Mon, 13 Jul 2015 23:38:58 +0200
Subject: [PATCH] add NodeSearch, ElementSearch, RemoveMeshComponents

---
 .../DataView/MeshElementRemovalDialog.cpp     |  13 +-
 Applications/Utils/FileConverter/GMSH2OGS.cpp |   7 +-
 .../Utils/MeshEdit/removeMeshElements.cpp     |   7 +-
 .../BoundaryElementsAlongPolyline.cpp         |   6 +-
 MeshGeoToolsLib/BoundaryElementsOnSurface.cpp |   6 +-
 MeshGeoToolsLib/BoundaryElementsSearcher.cpp  |   1 -
 MeshLib/CMakeLists.txt                        |   3 +-
 MeshLib/MeshEditing/ElementExtraction.cpp     | 168 ------------------
 MeshLib/MeshEditing/ElementExtraction.h       |  84 ---------
 MeshLib/MeshEditing/RemoveMeshComponents.cpp  | 132 ++++++++++++++
 MeshLib/MeshEditing/RemoveMeshComponents.h    |  42 +++++
 MeshLib/MeshEditing/removeMeshNodes.cpp       |  74 --------
 MeshLib/MeshEditing/removeMeshNodes.h         |  31 ----
 MeshLib/MeshGenerators/LayeredVolume.cpp      |   7 +-
 MeshLib/MeshQuality/MeshValidation.cpp        |   4 +-
 MeshLib/MeshSearch/ElementSearch.cpp          | 123 +++++++++++++
 MeshLib/MeshSearch/ElementSearch.h            |  63 +++++++
 MeshLib/MeshSearch/NodeSearch.cpp             |  94 ++++++++++
 MeshLib/MeshSearch/NodeSearch.h               |  52 ++++++
 MeshLib/MeshSearcher.cpp                      |  73 --------
 MeshLib/MeshSearcher.h                        |  43 -----
 ProcessLib/NeumannBc.h                        |   4 +-
 Tests/AssemblerLib/LocalToGlobalIndexMap.cpp  |   4 +-
 Tests/MeshLib/TestBoundaryElementSearch.cpp   |  14 +-
 Tests/MeshLib/TestDuplicate.cpp               |  16 +-
 Tests/MeshLib/TestRemove.cpp                  |  62 +++++++
 26 files changed, 622 insertions(+), 511 deletions(-)
 delete mode 100644 MeshLib/MeshEditing/ElementExtraction.cpp
 delete mode 100644 MeshLib/MeshEditing/ElementExtraction.h
 create mode 100644 MeshLib/MeshEditing/RemoveMeshComponents.cpp
 create mode 100644 MeshLib/MeshEditing/RemoveMeshComponents.h
 delete mode 100644 MeshLib/MeshEditing/removeMeshNodes.cpp
 delete mode 100644 MeshLib/MeshEditing/removeMeshNodes.h
 create mode 100644 MeshLib/MeshSearch/ElementSearch.cpp
 create mode 100644 MeshLib/MeshSearch/ElementSearch.h
 create mode 100644 MeshLib/MeshSearch/NodeSearch.cpp
 create mode 100644 MeshLib/MeshSearch/NodeSearch.h
 delete mode 100644 MeshLib/MeshSearcher.cpp
 delete mode 100644 MeshLib/MeshSearcher.h
 create mode 100644 Tests/MeshLib/TestRemove.cpp

diff --git a/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp b/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp
index f3655e1580e..31c983cb1f7 100644
--- a/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp
+++ b/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp
@@ -17,7 +17,8 @@
 #include "Mesh.h"
 #include "Elements/Element.h"
 #include "MeshLib/Node.h"
-#include "MeshEditing/ElementExtraction.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
+#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
 #include "AABB.h"
 #include "OGSError.h"
 
@@ -60,7 +61,8 @@ void MeshElementRemovalDialog::accept()
 
 	bool anything_checked (false);
 
-	MeshLib::ElementExtraction ex(*_project.getMesh(this->meshNameComboBox->currentText().toStdString()));
+	const MeshLib::Mesh* msh = _project.getMesh(this->meshNameComboBox->currentText().toStdString());
+	MeshLib::ElementSearch ex(*msh);
 	if (this->elementTypeCheckBox->isChecked())
 	{
 		QList<QListWidgetItem*> items = this->elementTypeListWidget->selectedItems();
@@ -105,15 +107,14 @@ void MeshElementRemovalDialog::accept()
 
 	if (anything_checked)
 	{
-		MeshLib::Mesh* new_mesh = ex.removeMeshElements(this->newMeshNameEdit->text().toStdString());
+		MeshLib::Mesh* new_mesh = MeshLib::removeElements(*msh, ex.getSearchedElementIDs(), this->newMeshNameEdit->text().toStdString());
 		if (new_mesh)
 			emit meshAdded(new_mesh);
 		else
 		{
-			const unsigned error_code (ex.getErrorCode());
-			if (error_code == 1)
+			if (new_mesh == nullptr)
 				OGSError::box("The current selection removes ALL mesh elements.\nPlease change the selection.");
-			if (error_code == 2)
+			if (ex.getSearchedElementIDs().empty())
 				OGSError::box("The current selection removes NO mesh elements.");
 			delete new_mesh;
 			return;
diff --git a/Applications/Utils/FileConverter/GMSH2OGS.cpp b/Applications/Utils/FileConverter/GMSH2OGS.cpp
index 3dea6a21764..1dd60c566aa 100644
--- a/Applications/Utils/FileConverter/GMSH2OGS.cpp
+++ b/Applications/Utils/FileConverter/GMSH2OGS.cpp
@@ -36,8 +36,9 @@
 #include "FileIO/VtkIO/VtuInterface.h"
 
 // MeshLib
-#include "MeshLib/MeshEditing/ElementExtraction.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
 #include "MeshLib/Mesh.h"
+#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
 
 int main (int argc, char* argv[])
 {
@@ -96,9 +97,9 @@ int main (int argc, char* argv[])
 
 	// *** remove line elements on request
 	if (exclude_lines_arg.getValue()) {
-		auto ex = MeshLib::ElementExtraction(*mesh);
+		auto ex = MeshLib::ElementSearch(*mesh);
 		ex.searchByElementType(MeshLib::MeshElemType::LINE);
-		auto m = ex.removeMeshElements(mesh->getName()+"-withoutLines");
+		auto m = MeshLib::removeElements(*mesh, ex.getSearchedElementIDs(), mesh->getName()+"-withoutLines");
 		if (m != nullptr) {
 			INFO("Removed %d lines.", mesh->getNElements() - m->getNElements());
 			std::swap(m, mesh);
diff --git a/Applications/Utils/MeshEdit/removeMeshElements.cpp b/Applications/Utils/MeshEdit/removeMeshElements.cpp
index 4a953ea0cd0..71d1f853a2d 100644
--- a/Applications/Utils/MeshEdit/removeMeshElements.cpp
+++ b/Applications/Utils/MeshEdit/removeMeshElements.cpp
@@ -29,7 +29,8 @@
 #include "MeshLib/Node.h"
 #include "Elements/Element.h"
 #include "MeshEnums.h"
-#include "MeshEditing/ElementExtraction.h"
+#include "MeshSearch/ElementSearch.h"
+#include "MeshEditing/RemoveMeshComponents.h"
 
 int main (int argc, char* argv[])
 {
@@ -84,7 +85,7 @@ int main (int argc, char* argv[])
 
 	MeshLib::Mesh const*const mesh (FileIO::readMeshFromFile(mesh_in.getValue()));
 	INFO("Mesh read: %d nodes, %d elements.", mesh->getNNodes(), mesh->getNElements());
-	MeshLib::ElementExtraction ex(*mesh);
+	MeshLib::ElementSearch ex(*mesh);
 
 	// search elements IDs to be removed
 	if (zveArg.isSet()) {
@@ -142,7 +143,7 @@ int main (int argc, char* argv[])
 	}
 
 	// remove the elements and create a new mesh object.
-	MeshLib::Mesh const*const new_mesh = ex.removeMeshElements(mesh->getName());
+	MeshLib::Mesh const*const new_mesh = MeshLib::removeElements(*mesh, ex.getSearchedElementIDs(), mesh->getName());
 
 	// write into a file
 	FileIO::Legacy::MeshIO meshIO;
diff --git a/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp b/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp
index 5398b975c16..c6e24e76aca 100644
--- a/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp
+++ b/MeshGeoToolsLib/BoundaryElementsAlongPolyline.cpp
@@ -16,7 +16,7 @@
 #include "MeshLib/Node.h"
 #include "MeshLib/Elements/Element.h"
 #include "MeshLib/Elements/Line.h"
-#include "MeshLib/MeshSearcher.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
 
 #include "MeshGeoToolsLib/MeshNodeSearcher.h"
 
@@ -28,7 +28,9 @@ BoundaryElementsAlongPolyline::BoundaryElementsAlongPolyline(MeshLib::Mesh const
 {
 	// search nodes and elements located along the polyline
 	auto node_ids_on_poly = mshNodeSearcher.getMeshNodeIDsAlongPolyline(ply);
-	auto ele_ids_near_ply = MeshLib::getConnectedElementIDs(_mesh, node_ids_on_poly);
+	MeshLib::ElementSearch es(_mesh);
+	es.searchByNodeIDs(node_ids_on_poly);
+	auto &ele_ids_near_ply = es.getSearchedElementIDs();
 
 	// check all edges of the elements near the polyline
 	for (auto ele_id : ele_ids_near_ply) {
diff --git a/MeshGeoToolsLib/BoundaryElementsOnSurface.cpp b/MeshGeoToolsLib/BoundaryElementsOnSurface.cpp
index 83c154dfb3f..5bdd855da40 100644
--- a/MeshGeoToolsLib/BoundaryElementsOnSurface.cpp
+++ b/MeshGeoToolsLib/BoundaryElementsOnSurface.cpp
@@ -12,7 +12,7 @@
 
 #include "MeshLib/Mesh.h"
 #include "MeshLib/Elements/Element.h"
-#include "MeshLib/MeshSearcher.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
 
 #include "MeshGeoToolsLib/MeshNodeSearcher.h"
 
@@ -24,7 +24,9 @@ BoundaryElementsOnSurface::BoundaryElementsOnSurface(MeshLib::Mesh const& mesh,
 {
 	// 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);
+	MeshLib::ElementSearch es(_mesh);
+	es.searchByNodeIDs(node_ids_on_sfc);
+	auto &ele_ids_near_sfc = es.getSearchedElementIDs();
 
 	// get a list of faces made of the nodes
 	for (auto ele_id : ele_ids_near_sfc) {
diff --git a/MeshGeoToolsLib/BoundaryElementsSearcher.cpp b/MeshGeoToolsLib/BoundaryElementsSearcher.cpp
index 9a9a096f25b..85ef0201c60 100644
--- a/MeshGeoToolsLib/BoundaryElementsSearcher.cpp
+++ b/MeshGeoToolsLib/BoundaryElementsSearcher.cpp
@@ -14,7 +14,6 @@
 
 #include "MeshLib/Mesh.h"
 #include "MeshLib/Elements/Element.h"
-#include "MeshLib/MeshSearcher.h"
 
 #include "MeshGeoToolsLib/MeshNodeSearcher.h"
 #include "MeshGeoToolsLib/BoundaryElementsAlongPolyline.h"
diff --git a/MeshLib/CMakeLists.txt b/MeshLib/CMakeLists.txt
index 8a41843600c..0ce23cbf767 100644
--- a/MeshLib/CMakeLists.txt
+++ b/MeshLib/CMakeLists.txt
@@ -9,9 +9,10 @@ endif()
 GET_SOURCE_FILES(SOURCES_ELEMENTS Elements)
 GET_SOURCE_FILES(SOURCES_EDITING MeshEditing)
 GET_SOURCE_FILES(SOURCES_GENERATORS MeshGenerators)
+GET_SOURCE_FILES(SOURCES_SEARCH MeshSearch)
 
 GET_SOURCE_FILES(SOURCES_QUALITY MeshQuality)
-set(SOURCES ${SOURCES_MESHLIB} ${SOURCES_ELEMENTS} ${SOURCES_EDITING} ${SOURCES_GENERATORS} ${SOURCES_QUALITY})
+set(SOURCES ${SOURCES_MESHLIB} ${SOURCES_ELEMENTS} ${SOURCES_EDITING} ${SOURCES_GENERATORS} ${SOURCES_QUALITY} ${SOURCES_SEARCH})
 
 # Create the library
 add_library(MeshLib STATIC ${SOURCES})
diff --git a/MeshLib/MeshEditing/ElementExtraction.cpp b/MeshLib/MeshEditing/ElementExtraction.cpp
deleted file mode 100644
index fbf8d8b83ac..00000000000
--- a/MeshLib/MeshEditing/ElementExtraction.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2013-04-04
- * \brief  Implementation of ElementExtraction.
- *
- * \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 "ElementExtraction.h"
-
-#include "logog/include/logog.hpp"
-
-#include "GeoLib/AABB.h"
-
-#include "MeshLib/Mesh.h"
-#include "MeshLib/Elements/Element.h"
-#include "MeshLib/MeshQuality/MeshValidation.h"
-
-#include "DuplicateMeshComponents.h"
-
-namespace MeshLib {
-
-ElementExtraction::ElementExtraction(const MeshLib::Mesh &mesh)
-	: _mesh(mesh), _error_code(0)
-{
-}
-
-ElementExtraction::~ElementExtraction()
-{
-}
-
-MeshLib::Mesh* ElementExtraction::removeMeshElements(const std::string &new_mesh_name)
-{
-	if (_marked_elements.empty())
-	{
-		INFO("No elements to remove");
-		_error_code = 2;
-		return nullptr;
-	}
-
-	INFO("Removing total %d elements...", _marked_elements.size());
-	std::vector<MeshLib::Element*> tmp_elems = excludeElementCopy(
-		_mesh.getElements(),
-		_marked_elements
-	);
-	INFO("%d elements remain in mesh.", tmp_elems.size());
-	std::vector<MeshLib::Node*> new_nodes = MeshLib::copyNodeVector(_mesh.getNodes());
-	std::vector<MeshLib::Element*> new_elems = MeshLib::copyElementVector(tmp_elems, new_nodes);
-
-	if (!new_elems.empty())
-	{
-		MeshLib::Mesh* new_mesh = new MeshLib::Mesh(new_mesh_name,
-			new_nodes, new_elems,
-			_mesh.getProperties().excludeCopyProperties(_marked_elements)
-		);
-		MeshValidation::removeUnusedMeshNodes(*new_mesh);
-		return new_mesh;
-	}
-	else
-	{
-		INFO("Current selection removes all elements.");
-		_error_code = 1;
-		return nullptr;
-	}
-}
-
-std::size_t ElementExtraction::searchByMaterialID(int const matID)
-{
-	boost::optional<MeshLib::PropertyVector<int> const&> opt_pv(
-		this->_mesh.getProperties().getPropertyVector<int>("MaterialIDs")
-	);
-	if (!opt_pv)
-		return 0;
-
-	MeshLib::PropertyVector<int> const& pv(opt_pv.get());
-
-	std::vector<std::size_t> matchedIDs;
-	for (std::size_t i(0); i<pv.getNumberOfTuples(); ++i) {
-		if (pv[i]==matID)
-			matchedIDs.push_back(i);
-	}
-
-	this->updateUnion(matchedIDs);
-	return matchedIDs.size();
-}
-
-std::size_t ElementExtraction::searchByElementType(MeshElemType eleType)
-{
-	const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements());
-	std::vector<std::size_t> matchedIDs;
-	std::size_t i = 0;
-	for (MeshLib::Element* ele : ele_vec) {
-		if (ele->getGeomType()==eleType)
-			matchedIDs.push_back(i);
-		i++;
-	}
-	this->updateUnion(matchedIDs);
-	return matchedIDs.size();
-}
-
-std::size_t ElementExtraction::searchByContent(double eps)
-{
-	const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements());
-	std::vector<std::size_t> matchedIDs;
-	std::size_t i = 0;
-	for (MeshLib::Element* ele : ele_vec) {
-		if (ele->getContent() < eps)
-			matchedIDs.push_back(i);
-		i++;
-	}
-	this->updateUnion(matchedIDs);
-	return matchedIDs.size();
-}
-
-std::size_t ElementExtraction::searchByBoundingBox(
-	GeoLib::AABB<MathLib::Point3d> const& aabb)
-{
-	const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements());
-
-	std::vector<std::size_t> matchedIDs;
-	const std::size_t n_elems(ele_vec.size());
-	for (std::size_t i = 0; i<n_elems; i++)
-	{
-		std::size_t nElemNodes (ele_vec[i]->getNBaseNodes());
-		for (std::size_t j=0; j<nElemNodes; ++j)
-			if (!aabb.containsPoint(*ele_vec[i]->getNode(j)))
-			{
-				matchedIDs.push_back(i);
-				break;
-			}
-	}
-	this->updateUnion(matchedIDs);
-	return matchedIDs.size();
-}
-
-std::vector<MeshLib::Element*> ElementExtraction::excludeElementCopy(
-	std::vector<MeshLib::Element*> const& vec_src_eles,
-	std::vector<std::size_t> const& vec_removed) const
-{
-	std::vector<MeshLib::Element*> vec_dest_eles(vec_src_eles.size()-vec_removed.size());
-
-	unsigned cnt (0);
-	for (std::size_t i=0; i<vec_removed[0]; ++i)
-		vec_dest_eles[cnt++] = vec_src_eles[i];
-	for (std::size_t i=1; i<vec_removed.size(); ++i)
-		for (std::size_t j=vec_removed[i-1]+1; j<vec_removed[i]; ++j)
-			vec_dest_eles[cnt++] = vec_src_eles[j];
-	for (std::size_t i=vec_removed.back()+1; i<vec_src_eles.size(); ++i)
-		vec_dest_eles[cnt++] = vec_src_eles[i];
-
-	return vec_dest_eles;
-}
-
-void ElementExtraction::updateUnion(const std::vector<std::size_t> &vec)
-{
-	std::vector<std::size_t> vec_temp(vec.size() + _marked_elements.size());
-	auto it = std::set_union(vec.begin(), vec.end(), _marked_elements.begin(), _marked_elements.end(), vec_temp.begin());
-	vec_temp.resize(it - vec_temp.begin());
-	_marked_elements.assign(vec_temp.begin(), vec_temp.end());
-}
-
-} // end namespace MeshLib
diff --git a/MeshLib/MeshEditing/ElementExtraction.h b/MeshLib/MeshEditing/ElementExtraction.h
deleted file mode 100644
index 718419e4fa5..00000000000
--- a/MeshLib/MeshEditing/ElementExtraction.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2013-04-04
- * \brief  Definition of the ElementExtraction
- *
- * \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 ELEMENTEXTRACTION_H
-#define ELEMENTEXTRACTION_H
-
-#include <string>
-#include <vector>
-
-#include "GeoLib/AABB.h"
-
-#include "MeshLib/MeshEnums.h"
-#include "MeshLib/Node.h"
-
-namespace MeshLib {
-
-// forward declarations
-class Mesh;
-class Element;
-
-class ElementExtraction
-{
-public:
-	ElementExtraction(const MeshLib::Mesh &mesh);
-
-	~ElementExtraction();
-
-	/// The error code determined during element extraction
-	/// (0 = no errors, 1 = all elements selected, 2 = no elements selected)
-	unsigned getErrorCode() { return _error_code; }
-
-	/// Removes all mesh elements marked by search-methods.
-	MeshLib::Mesh* removeMeshElements(const std::string &new_mesh_name);
-
-	/// Marks all elements with the given Material ID.
-	std::size_t searchByMaterialID(int const matID);
-
-	/// Marks all elements of the given element type.
-	std::size_t searchByElementType(MeshElemType eleType);
-
-	/// Marks all elements with a volume smaller than eps.
-	std::size_t searchByContent(double eps = std::numeric_limits<double>::epsilon());
-
-	/// Marks all elements with at least one node outside the bounding box spanned by x1 and x2;
-	std::size_t searchByBoundingBox(GeoLib::AABB<MathLib::Point3d> const& aabb);
-
-
-private:
-	/// Updates the vector of marked elements with values from vec.
-	void updateUnion(const std::vector<std::size_t> &vec);
-
-	/// Returns a vector of shallow copies of the elements in the source vector.
-	/// The vector vec_removed contains the position of elements within the
-	/// source vector that should not be copied to the returned vector.
-	/// @param vec_src_eles vector of source elements which are shallow copied
-	/// @param vec_removed contains positions of elements in vec_src_eles that
-	///        should not be copied
-	/// @return vector of elements (shallow copy!)
-	std::vector<MeshLib::Element*> excludeElementCopy(
-		std::vector<MeshLib::Element*> const& vec_src_eles,
-		std::vector<std::size_t> const& vec_removed) const;
-
-	/// The mesh from which elements should be removed.
-	const MeshLib::Mesh &_mesh;
-	/// The vector of element indices that should be removed.
-	std::vector<std::size_t> _marked_elements;
-	/// An error code during mesh element extraction for checking the result from outside (0 = no errors).
-	unsigned _error_code;
-};
-
-} // end namespace MeshLib
-
-#endif //ELEMENTEXTRACTION_H
diff --git a/MeshLib/MeshEditing/RemoveMeshComponents.cpp b/MeshLib/MeshEditing/RemoveMeshComponents.cpp
new file mode 100644
index 00000000000..72505f98a78
--- /dev/null
+++ b/MeshLib/MeshEditing/RemoveMeshComponents.cpp
@@ -0,0 +1,132 @@
+/**
+ * \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 "RemoveMeshComponents.h"
+
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/MeshQuality/MeshValidation.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
+#include "MeshLib/MeshSearch/NodeSearch.h"
+#include "DuplicateMeshComponents.h"
+
+namespace MeshLib
+{
+
+namespace details
+{
+
+std::vector<MeshLib::Element*> excludeElementCopy(
+	std::vector<MeshLib::Element*> const& vec_src_eles,
+	std::vector<std::size_t> const& vec_removed)
+{
+	std::vector<MeshLib::Element*> vec_dest_eles(vec_src_eles.size()-vec_removed.size());
+
+	unsigned cnt (0);
+	for (std::size_t i=0; i<vec_removed[0]; ++i)
+		vec_dest_eles[cnt++] = vec_src_eles[i];
+	for (std::size_t i=1; i<vec_removed.size(); ++i)
+		for (std::size_t j=vec_removed[i-1]+1; j<vec_removed[i]; ++j)
+			vec_dest_eles[cnt++] = vec_src_eles[j];
+	for (std::size_t i=vec_removed.back()+1; i<vec_src_eles.size(); ++i)
+		vec_dest_eles[cnt++] = vec_src_eles[i];
+
+	return vec_dest_eles;
+}
+
+} // details
+
+MeshLib::Mesh* removeElements(const MeshLib::Mesh& mesh, const std::vector<std::size_t> &removed_element_ids, const std::string &new_mesh_name)
+{
+	if (removed_element_ids.empty())
+	{
+		INFO("No elements to remove");
+		return nullptr;
+	}
+
+	INFO("Removing total %d elements...", removed_element_ids.size());
+	std::vector<MeshLib::Element*> tmp_elems = details::excludeElementCopy(
+		mesh.getElements(),
+		removed_element_ids
+	);
+	INFO("%d elements remain in mesh.", tmp_elems.size());
+
+	// copy node and element objects
+	std::vector<MeshLib::Node*> new_nodes = MeshLib::copyNodeVector(mesh.getNodes());
+	std::vector<MeshLib::Element*> new_elems = MeshLib::copyElementVector(tmp_elems, new_nodes);
+
+	// delete unused nodes
+	NodeSearch ns(mesh);
+	ns.searchByElementIDs(removed_element_ids, true);
+	auto &removed_node_ids(ns.getSearchedNodeIDs());
+	INFO("Removing total %d nodes...", removed_node_ids.size());
+	for (auto nodeid : removed_node_ids)
+	{
+		delete new_nodes[nodeid];
+		new_nodes[nodeid] = nullptr;
+	}
+	new_nodes.erase(std::remove(new_nodes.begin(), new_nodes.end(), nullptr), new_nodes.end());
+
+	if (!new_elems.empty())
+	{
+		MeshLib::Mesh* new_mesh = new MeshLib::Mesh(new_mesh_name,
+			new_nodes, new_elems,
+			mesh.getProperties().excludeCopyProperties(removed_element_ids)
+		);
+		return new_mesh;
+	}
+	else
+	{
+		INFO("Current selection removes all elements.");
+		return nullptr;
+	}
+}
+
+MeshLib::Mesh* removeNodes(const MeshLib::Mesh &mesh, const std::vector<std::size_t> &del_nodes_idx, const std::string &new_mesh_name)
+{
+	if (del_nodes_idx.empty())
+		return nullptr;
+
+	// copy node and element objects
+	std::vector<MeshLib::Node*> new_nodes = MeshLib::copyNodeVector(mesh.getNodes());
+	std::vector<MeshLib::Element*> new_elems = MeshLib::copyElementVector(mesh.getElements(), new_nodes);
+
+	// delete nodes
+	for (auto nodeid : del_nodes_idx)
+	{
+		delete new_nodes[nodeid];
+		new_nodes[nodeid] = nullptr;
+	}
+	new_nodes.erase(std::remove(new_nodes.begin(), new_nodes.end(), nullptr), new_nodes.end());
+
+	// delete elements
+	MeshLib::ElementSearch es(mesh);
+	es.searchByNodeIDs(del_nodes_idx);
+	auto& removed_element_ids = es.getSearchedElementIDs();
+	for (auto eid : removed_element_ids)
+	{
+		delete new_elems[eid];
+		new_elems[eid] = nullptr;
+	}
+	new_elems.erase(std::remove(new_elems.begin(), new_elems.end(), nullptr), new_elems.end());
+
+	if (!new_elems.empty())
+	{
+		MeshLib::Mesh* new_mesh = new MeshLib::Mesh(new_mesh_name,
+			new_nodes, new_elems,
+			mesh.getProperties().excludeCopyProperties(removed_element_ids)
+		);
+		return new_mesh;
+	}
+	else
+	{
+		return nullptr;
+	}
+}
+} // end namespace MeshLib
+
diff --git a/MeshLib/MeshEditing/RemoveMeshComponents.h b/MeshLib/MeshEditing/RemoveMeshComponents.h
new file mode 100644
index 00000000000..3e78e89f868
--- /dev/null
+++ b/MeshLib/MeshEditing/RemoveMeshComponents.h
@@ -0,0 +1,42 @@
+/**
+ * \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 REMOVEMESHCOMPONENTS_H_
+#define REMOVEMESHCOMPONENTS_H_
+
+#include <string>
+#include <vector>
+
+namespace MeshLib
+{
+class Mesh;
+class Element;
+
+/**
+ * Removes mesh elements and returns a new mesh object. The original mesh is kept unchanged.
+ * @param mesh                 an original mesh whose elements are removed
+ * @param removed_element_ids  a vector of element indices to be removed
+ * @param new_mesh_name        a new mesh name
+ * @return a new mesh object
+ */
+MeshLib::Mesh* removeElements(const MeshLib::Mesh& mesh,
+		const std::vector<std::size_t> &removed_element_ids, const std::string &new_mesh_name);
+
+/**
+ * Removes the mesh nodes (and connected elements) given in the nodes-list from the mesh.
+ * @param mesh                 an original mesh whose elements are removed
+ * @param removed_node_ids     a vector of node indices to be removed
+ * @param new_mesh_name        a new mesh name
+ * @return a new mesh object
+ */
+MeshLib::Mesh* removeNodes(const MeshLib::Mesh &mesh, const std::vector<std::size_t> &removed_node_ids, const std::string &new_mesh_name);
+
+} // end namespace MeshLib
+
+#endif //REMOVEMESHCOMPONENTS_H_
diff --git a/MeshLib/MeshEditing/removeMeshNodes.cpp b/MeshLib/MeshEditing/removeMeshNodes.cpp
deleted file mode 100644
index c662bb84074..00000000000
--- a/MeshLib/MeshEditing/removeMeshNodes.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2013-04-04
- * \brief  Implementation of removeMeshNodes.
- *
- * \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 "removeMeshNodes.h"
-
-#include "MeshLib/Mesh.h"
-#include "MeshLib/Node.h"
-#include "MeshLib/Elements/Element.h"
-
-namespace MeshLib {
-
-void removeMeshNodes(MeshLib::Mesh &mesh, const std::vector<std::size_t> &del_nodes_idx)
-{
-	const size_t nDelNodes = del_nodes_idx.size();
-	if (nDelNodes == 0)
-		return;
-
-	std::vector<MeshLib::Node*>& nodes (mesh._nodes);
-	std::vector<MeshLib::Element*>& elements = mesh._elements;
-	bool elements_removed (false);
-
-	// delete nodes
-	for (std::size_t i = 0; i < nDelNodes; ++i)
-	{
-		const unsigned idx (del_nodes_idx[i]);
-		std::vector<MeshLib::Element*> conn_elems (nodes[idx]->getElements());
-
-		// delete elements connected to these nodes
-		for (std::size_t j = 0; j < conn_elems.size(); ++j)
-		{
-			elements_removed = true;
-			auto del_elem (std::find(elements.begin(), elements.end(), conn_elems[j]));
-			delete *del_elem;
-			*del_elem = nullptr;
-		}
-
-		delete nodes[idx];
-		nodes[idx] = nullptr;
-	}
-
-	// due to element removal neighbourhoods have to be reset and additional nodes
-	// might need to be deleted as they are no longer part of any element
-	if (elements_removed)
-	{
-		auto elem_vec_end = std::remove(elements.begin(), elements.end(), nullptr);
-		elements.erase(elem_vec_end, elements.end());
-		mesh.resetElementsConnectedToNodes();
-		for (auto node = nodes.begin(); node != nodes.end(); ++node)
-			if ((*node) && (*node)->getNElements() == 0)
-			{
-				delete *node;
-				*node = nullptr;
-			}
-	}
-
-	auto node_vec_end = std::remove(nodes.begin(), nodes.end(), nullptr);
-	nodes.erase(node_vec_end, nodes.end());
-
-	mesh.resetNodeIDs(); // set new node-IDs
-}
-
-
-} // end namespace MeshLib
diff --git a/MeshLib/MeshEditing/removeMeshNodes.h b/MeshLib/MeshEditing/removeMeshNodes.h
deleted file mode 100644
index 87619353aa2..00000000000
--- a/MeshLib/MeshEditing/removeMeshNodes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * \file
- * \author Karsten Rink
- * \date   2013-04-04
- * \brief  Definition of the removeMeshNodes
- *
- * \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 REMOVEMESHNODES_H
-#define REMOVEMESHNODES_H
-
-#include <vector>
-
-namespace MeshLib {
-
-// forward declarations
-class Mesh;
-
-	/// Removes the mesh nodes (and connected elements) given in the nodes-list from the mesh.
-	/// \warning This function actually modifies the mesh, it might make sense to copy the mesh before using this function.
-	void removeMeshNodes(MeshLib::Mesh &mesh, const std::vector<std::size_t> &nodes);
-
-} // end namespace MeshLib
-
-#endif //REMOVEMESHNODES_H
diff --git a/MeshLib/MeshGenerators/LayeredVolume.cpp b/MeshLib/MeshGenerators/LayeredVolume.cpp
index f955a5fe389..463006dd3a7 100644
--- a/MeshLib/MeshGenerators/LayeredVolume.cpp
+++ b/MeshLib/MeshGenerators/LayeredVolume.cpp
@@ -20,9 +20,10 @@
 
 #include "MeshLib/Elements/Tri.h"
 #include "MeshLib/Elements/Quad.h"
-#include "MeshLib/MeshEditing/ElementExtraction.h"
 #include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
+#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
 #include "MeshLib/MeshGenerators/MeshLayerMapper.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
 
 
 bool LayeredVolume::createRasterLayers(const MeshLib::Mesh &mesh,
@@ -38,9 +39,9 @@ bool LayeredVolume::createRasterLayers(const MeshLib::Mesh &mesh,
 		return false;
 
 	// remove line elements, only tri + quad remain
-	MeshLib::ElementExtraction ex(mesh);
+	MeshLib::ElementSearch ex(mesh);
 	ex.searchByElementType(MeshLib::MeshElemType::LINE);
-	MeshLib::Mesh* top (ex.removeMeshElements("MeshLayer"));
+	MeshLib::Mesh* top (removeElements(mesh, ex.getSearchedElementIDs(), "MeshLayer"));
 	if (top==nullptr)
 		top = new MeshLib::Mesh(mesh);
 
diff --git a/MeshLib/MeshQuality/MeshValidation.cpp b/MeshLib/MeshQuality/MeshValidation.cpp
index 940461ae573..06cd0a77e1e 100644
--- a/MeshLib/MeshQuality/MeshValidation.cpp
+++ b/MeshLib/MeshQuality/MeshValidation.cpp
@@ -23,8 +23,8 @@
 #include "MeshLib/Mesh.h"
 #include "MeshLib/Node.h"
 #include "MeshLib/Elements/Element.h"
-#include "MeshLib/MeshEditing/removeMeshNodes.h"
 #include "MeshLib/MeshEditing/MeshRevision.h"
+#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
 #include "MeshLib/MeshSurfaceExtraction.h"
 
 namespace MeshLib {
@@ -65,7 +65,7 @@ std::vector<std::size_t> MeshValidation::findUnusedMeshNodes(const MeshLib::Mesh
 std::vector<std::size_t> MeshValidation::removeUnusedMeshNodes(MeshLib::Mesh &mesh)
 {
 	std::vector<std::size_t> del_node_idx = MeshValidation::findUnusedMeshNodes(mesh);
-	MeshLib::removeMeshNodes(mesh, del_node_idx);
+	MeshLib::removeNodes(mesh, del_node_idx, mesh.getName());
 
 	if (!del_node_idx.empty())
 		INFO("Removed %d unused mesh nodes.", del_node_idx.size());
diff --git a/MeshLib/MeshSearch/ElementSearch.cpp b/MeshLib/MeshSearch/ElementSearch.cpp
new file mode 100644
index 00000000000..61441cbdefc
--- /dev/null
+++ b/MeshLib/MeshSearch/ElementSearch.cpp
@@ -0,0 +1,123 @@
+/**
+ * \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 "ElementSearch.h"
+
+#include <logog/include/logog.hpp>
+
+#include "MeshLib/Mesh.h"
+#include "MeshLib/Node.h"
+#include "MeshLib/Elements/Element.h"
+
+namespace MeshLib {
+
+ElementSearch::ElementSearch(const MeshLib::Mesh &mesh)
+	: _mesh(mesh)
+{
+}
+
+ElementSearch::~ElementSearch()
+{
+}
+
+std::size_t ElementSearch::searchByMaterialID(int const matID)
+{
+	boost::optional<MeshLib::PropertyVector<int> const&> opt_pv(
+		this->_mesh.getProperties().getPropertyVector<int>("MaterialIDs")
+	);
+	if (!opt_pv)
+		return 0;
+
+	MeshLib::PropertyVector<int> const& pv(opt_pv.get());
+
+	std::vector<std::size_t> matchedIDs;
+	for (std::size_t i(0); i<pv.getNumberOfTuples(); ++i) {
+		if (pv[i]==matID)
+			matchedIDs.push_back(i);
+	}
+
+	this->updateUnion(matchedIDs);
+	return matchedIDs.size();
+}
+
+std::size_t ElementSearch::searchByElementType(MeshElemType eleType)
+{
+	const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements());
+	std::vector<std::size_t> matchedIDs;
+	std::size_t i = 0;
+	for (MeshLib::Element* ele : ele_vec) {
+		if (ele->getGeomType()==eleType)
+			matchedIDs.push_back(i);
+		i++;
+	}
+	this->updateUnion(matchedIDs);
+	return matchedIDs.size();
+}
+
+std::size_t ElementSearch::searchByContent(double eps)
+{
+	const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements());
+	std::vector<std::size_t> matchedIDs;
+	std::size_t i = 0;
+	for (MeshLib::Element* ele : ele_vec) {
+		if (ele->getContent() < eps)
+			matchedIDs.push_back(i);
+		i++;
+	}
+	this->updateUnion(matchedIDs);
+	return matchedIDs.size();
+}
+
+std::size_t ElementSearch::searchByBoundingBox(
+	GeoLib::AABB<MathLib::Point3d> const& aabb)
+{
+	const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements());
+
+	std::vector<std::size_t> matchedIDs;
+	const std::size_t n_elems(ele_vec.size());
+	for (std::size_t i = 0; i<n_elems; i++)
+	{
+		std::size_t nElemNodes (ele_vec[i]->getNBaseNodes());
+		for (std::size_t j=0; j<nElemNodes; ++j)
+			if (!aabb.containsPoint(*ele_vec[i]->getNode(j)))
+			{
+				matchedIDs.push_back(i);
+				break;
+			}
+	}
+	this->updateUnion(matchedIDs);
+	return matchedIDs.size();
+}
+
+std::size_t ElementSearch::searchByNodeIDs(const std::vector<std::size_t> &nodes)
+{
+	std::vector<std::size_t> connected_elements;
+	std::for_each(nodes.begin(), nodes.end(),
+		[&](std::size_t node_id)
+		{
+			for (auto* e : _mesh.getNode(node_id)->getElements()) {
+				connected_elements.push_back(e->getID());
+			}
+		});
+	std::sort(connected_elements.begin(), connected_elements.end());
+	auto it = std::unique(connected_elements.begin(), connected_elements.end());
+	connected_elements.resize(std::distance(connected_elements.begin(),it));
+	this->updateUnion(connected_elements);
+	return connected_elements.size();
+}
+
+void ElementSearch::updateUnion(const std::vector<std::size_t> &vec)
+{
+	std::vector<std::size_t> vec_temp(vec.size() + _marked_elements.size());
+	auto it = std::set_union(vec.begin(), vec.end(), _marked_elements.begin(), _marked_elements.end(), vec_temp.begin());
+	vec_temp.resize(it - vec_temp.begin());
+	_marked_elements.assign(vec_temp.begin(), vec_temp.end());
+}
+
+} // end namespace MeshLib
diff --git a/MeshLib/MeshSearch/ElementSearch.h b/MeshLib/MeshSearch/ElementSearch.h
new file mode 100644
index 00000000000..85715826feb
--- /dev/null
+++ b/MeshLib/MeshSearch/ElementSearch.h
@@ -0,0 +1,63 @@
+/**
+ * \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 ELEMENTSEARCH_H_
+#define ELEMENTSEARCH_H_
+
+#include <limits>
+#include <vector>
+
+#include "GeoLib/AABB.h"
+#include "MeshLib/MeshEnums.h"
+
+namespace MeshLib {
+
+// forward declarations
+class Mesh;
+class Element;
+
+/// Element search class
+class ElementSearch
+{
+public:
+	explicit ElementSearch(const MeshLib::Mesh &mesh);
+
+	~ElementSearch();
+
+	/// return marked elements
+	const std::vector<std::size_t>& getSearchedElementIDs() const { return _marked_elements; }
+
+	/// Marks all elements with the given Material ID.
+	std::size_t searchByMaterialID(int const matID);
+
+	/// Marks all elements of the given element type.
+	std::size_t searchByElementType(MeshElemType eleType);
+
+	/// Marks all elements with a volume smaller than eps.
+	std::size_t searchByContent(double eps = std::numeric_limits<double>::epsilon());
+
+	/// Marks all elements with at least one node outside the bounding box spanned by x1 and x2;
+	std::size_t searchByBoundingBox(GeoLib::AABB<MathLib::Point3d> const& aabb);
+
+	/// Marks all elements connecting to any of the given nodes
+	std::size_t searchByNodeIDs(const std::vector<std::size_t> &node_ids);
+
+private:
+	/// Updates the vector of marked elements with values from vec.
+	void updateUnion(const std::vector<std::size_t> &vec);
+
+	/// The mesh from which elements should be removed.
+	const MeshLib::Mesh &_mesh;
+	/// The vector of element indices that should be removed.
+	std::vector<std::size_t> _marked_elements;
+};
+
+} // end namespace MeshLib
+
+#endif //ELEMENTEXTRACTION_H
diff --git a/MeshLib/MeshSearch/NodeSearch.cpp b/MeshLib/MeshSearch/NodeSearch.cpp
new file mode 100644
index 00000000000..a697705dd49
--- /dev/null
+++ b/MeshLib/MeshSearch/NodeSearch.cpp
@@ -0,0 +1,94 @@
+/**
+ * \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 "NodeSearch.h"
+
+#include <set>
+
+#include <logog/include/logog.hpp>
+
+#include "MeshLib/Mesh.h"
+#include "MeshLib/Node.h"
+#include "MeshLib/Elements/Element.h"
+
+namespace MeshLib {
+
+NodeSearch::NodeSearch(const MeshLib::Mesh &mesh)
+	: _mesh(mesh)
+{
+}
+
+NodeSearch::~NodeSearch()
+{
+}
+
+std::size_t NodeSearch::searchByElementIDs(const std::vector<std::size_t> &elements, bool only_match_all_connected_elements)
+{
+	std::vector<std::size_t> connected_nodes;
+	if (only_match_all_connected_elements)
+	{
+		std::vector<std::size_t> node_marked_counts(_mesh.getNNodes(), 0); //this approach is not optimum for memory size
+		std::for_each(elements.begin(), elements.end(),
+			[&](std::size_t eid)
+			{
+				auto* e = _mesh.getElement(eid);
+				for (unsigned i=0; i<e->getNBaseNodes(); i++) {
+					node_marked_counts[e->getNodeIndex(i)]++;
+				}
+			});
+		for (std::size_t i=0; i<node_marked_counts.size(); i++)
+		{
+			if (node_marked_counts[i] == _mesh.getNode(i)->getElements().size())
+				connected_nodes.push_back(i);
+		}
+	} else {
+		std::for_each(elements.begin(), elements.end(),
+			[&](std::size_t eid)
+			{
+				auto* e = _mesh.getElement(eid);
+				for (unsigned i=0; i<e->getNBaseNodes(); i++) {
+					connected_nodes.push_back(e->getNodeIndex(i));
+				}
+			});
+		std::sort(connected_nodes.begin(), connected_nodes.end());
+		auto it = std::unique(connected_nodes.begin(), connected_nodes.end());
+		connected_nodes.resize(std::distance(connected_nodes.begin(),it));
+	}
+	this->updateUnion(connected_nodes);
+	return connected_nodes.size();
+}
+
+void NodeSearch::updateUnion(const std::vector<std::size_t> &vec)
+{
+	std::vector<std::size_t> vec_temp(vec.size() + _marked_nodes.size());
+	auto it = std::set_union(vec.begin(), vec.end(), _marked_nodes.begin(), _marked_nodes.end(), vec_temp.begin());
+	vec_temp.resize(it - vec_temp.begin());
+	_marked_nodes.assign(vec_temp.begin(), vec_temp.end());
+}
+
+std::vector<Node*> getNodes(std::vector<Element*> const& elements)
+{
+	std::set<Node*> nodes_set;
+	for (auto e : elements)
+	{
+		Node* const* nodes = e->getNodes();
+		unsigned const nnodes = e->getNNodes();
+		nodes_set.insert(nodes, nodes + nnodes);
+	}
+
+	std::vector<Node*> nodes;
+	nodes.reserve(nodes_set.size());
+
+	std::move(nodes_set.cbegin(), nodes_set.cend(),
+		std::back_inserter(nodes));
+
+	return nodes;
+}
+
+} // end namespace MeshLib
diff --git a/MeshLib/MeshSearch/NodeSearch.h b/MeshLib/MeshSearch/NodeSearch.h
new file mode 100644
index 00000000000..3dddc285303
--- /dev/null
+++ b/MeshLib/MeshSearch/NodeSearch.h
@@ -0,0 +1,52 @@
+/**
+ * \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 NODESEARCH_H_
+#define NODESEARCH_H_
+
+#include <vector>
+
+namespace MeshLib
+{
+
+// forward declarations
+class Mesh;
+class Element;
+class Node;
+
+/// Node search class
+class NodeSearch
+{
+public:
+	explicit NodeSearch(const MeshLib::Mesh &mesh);
+
+	~NodeSearch();
+
+	/// return marked node IDs
+	const std::vector<std::size_t>& getSearchedNodeIDs() const {return _marked_nodes; }
+
+	/// Marks all nodes connecting to any of the given elements
+	std::size_t searchByElementIDs(const std::vector<std::size_t> &element_ids, bool only_match_all_connected_elements = false);
+
+private:
+	/// Updates the vector of marked items with values from vec.
+	void updateUnion(const std::vector<std::size_t> &vec);
+
+	/// The mesh from which elements should be removed.
+	const MeshLib::Mesh &_mesh;
+	/// The vector of element indices that should be removed.
+	std::vector<std::size_t> _marked_nodes;
+};
+
+/// Create a vector of unique nodes used by given elements.
+std::vector<Node*> getNodes(std::vector<Element*> const& elements);
+
+} // end namespace MeshLib
+
+#endif //NODESEARCH_H_
diff --git a/MeshLib/MeshSearcher.cpp b/MeshLib/MeshSearcher.cpp
deleted file mode 100644
index a3df803b8e7..00000000000
--- a/MeshLib/MeshSearcher.cpp
+++ /dev/null
@@ -1,73 +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 "MeshSearcher.h"
-
-#include <algorithm>
-
-#include "Mesh.h"
-#include "Node.h"
-#include "Elements/Element.h"
-
-namespace MeshLib
-{
-
-std::vector<std::size_t> getConnectedElementIDs(MeshLib::Mesh const& msh, const std::vector<std::size_t> &nodes)
-{
-	std::vector<std::size_t> connected_elements;
-	std::for_each(nodes.begin(), nodes.end(),
-		[&](std::size_t node_id)
-		{
-			for (auto* e : msh.getNode(node_id)->getElements()) {
-				connected_elements.push_back(e->getID());
-			}
-		});
-	std::sort(connected_elements.begin(), connected_elements.end());
-	auto it = std::unique(connected_elements.begin(), connected_elements.end());
-	connected_elements.resize(std::distance(connected_elements.begin(),it));
-	return connected_elements;
-}
-
-std::vector<std::size_t> getConnectedNodeIDs(const std::vector<MeshLib::Element*> &elements)
-{
-	std::vector<std::size_t> connected_nodes;
-	std::for_each(elements.begin(), elements.end(),
-		[&](MeshLib::Element* e)
-		{
-			for (unsigned i=0; i<e->getNBaseNodes(); i++)
-				connected_nodes.push_back(e->getNodeIndex(i));
-		});
-	std::sort(connected_nodes.begin(), connected_nodes.end());
-	auto it = std::unique(connected_nodes.begin(), connected_nodes.end());
-	connected_nodes.resize(std::distance(connected_nodes.begin(),it));
-	return connected_nodes;
-}
-
-std::vector<Node*>
-selectNodes(std::vector<Element*> const& elements)
-{
-	std::set<Node*> nodes_set;
-	for (auto e : elements)
-	{
-		Node* const* nodes = e->getNodes();
-		unsigned const nnodes = e->getNNodes();
-		nodes_set.insert(nodes, nodes + nnodes);
-	}
-
-	std::vector<Node*> nodes;
-	nodes.reserve(nodes_set.size());
-
-	std::move(nodes_set.cbegin(), nodes_set.cend(),
-		std::back_inserter(nodes));
-
-	return nodes;
-}
-
-} // end namespace MeshLib
-
diff --git a/MeshLib/MeshSearcher.h b/MeshLib/MeshSearcher.h
deleted file mode 100644
index 1a211880d73..00000000000
--- a/MeshLib/MeshSearcher.h
+++ /dev/null
@@ -1,43 +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
- *
- */
-
-#ifndef MESHSEARCHER_H_
-#define MESHSEARCHER_H_
-
-#include <vector>
-
-
-namespace MeshLib
-{
-// forward declarations
-class Mesh;
-class Element;
-class Node;
-
-/**
- * get a vector of elements connected to given nodes
- * @param msh       a mesh object
- * @param node_ids  a vector of mesh node ids
- * @return a vector of element ids which connect to the given nodes
- */
-std::vector<std::size_t> getConnectedElementIDs(MeshLib::Mesh const& msh, const std::vector<std::size_t> &node_ids);
-
-/**
- * get a vector of node ID connected to given elements
- * @param elements  a vector of a pointer to a mesh element object
- * @return a vector of node ID
- */
-std::vector<std::size_t> getConnectedNodeIDs(const std::vector<MeshLib::Element*> &elements);
-
-/// Create a vector of unique nodes used by given elements.
-std::vector<Node*> selectNodes(std::vector<Element*> const& elements);
-
-} // end namespace MeshLib
-
-#endif //MESHSEARCHER_H_
diff --git a/ProcessLib/NeumannBc.h b/ProcessLib/NeumannBc.h
index c1349964d11..b31b3d6aea2 100644
--- a/ProcessLib/NeumannBc.h
+++ b/ProcessLib/NeumannBc.h
@@ -21,10 +21,10 @@
 #include "AssemblerLib/LocalDataInitializer.h"
 #include "AssemblerLib/LocalAssemblerBuilder.h"
 #include "MeshLib/MeshSubset.h"
+#include "MeshLib/MeshSearch/NodeSearch.h"
 
 #include "NeumannBcConfig.h"
 #include "NeumannBcAssembler.h"
-#include "MeshLib/MeshSearcher.h"
 
 namespace ProcessLib
 {
@@ -64,7 +64,7 @@ public:
                 std::back_inserter(_elements),
                 std::mem_fn(&MeshLib::Element::clone));
 
-        std::vector<MeshLib::Node*> nodes = MeshLib::selectNodes(_elements);
+        std::vector<MeshLib::Node*> nodes = MeshLib::getNodes(_elements);
 
         _mesh_subset_all_nodes =
             mesh_subset_all_nodes.getIntersectionByNodes(nodes);
diff --git a/Tests/AssemblerLib/LocalToGlobalIndexMap.cpp b/Tests/AssemblerLib/LocalToGlobalIndexMap.cpp
index b73bdcdf86c..f625863b20a 100644
--- a/Tests/AssemblerLib/LocalToGlobalIndexMap.cpp
+++ b/Tests/AssemblerLib/LocalToGlobalIndexMap.cpp
@@ -14,7 +14,7 @@
 #include "AssemblerLib/LocalToGlobalIndexMap.h"
 #include "MeshLib/MeshGenerators/MeshGenerator.h"
 
-#include "MeshLib/MeshSearcher.h"
+#include "MeshLib/MeshSearch/NodeSearch.h"
 #include "MeshLib/MeshSubsets.h"
 #include "MeshLib/Mesh.h"
 
@@ -88,7 +88,7 @@ TEST_F(AssemblerLibLocalToGlobalIndexMapTest, SubsetByComponent)
         some_elements.push_back(const_cast<MeshLib::Element*>(mesh->getElement(id)));
 
     // Find unique node ids of the selected elements for testing.
-    std::vector<MeshLib::Node*> selected_nodes = MeshLib::selectNodes(some_elements);
+    std::vector<MeshLib::Node*> selected_nodes = MeshLib::getNodes(some_elements);
 
     MeshLib::MeshSubset const* const selected_subset =
         nodesSubset->getIntersectionByNodes(selected_nodes);
diff --git a/Tests/MeshLib/TestBoundaryElementSearch.cpp b/Tests/MeshLib/TestBoundaryElementSearch.cpp
index ad27a40a0e8..f5b74b9bd98 100644
--- a/Tests/MeshLib/TestBoundaryElementSearch.cpp
+++ b/Tests/MeshLib/TestBoundaryElementSearch.cpp
@@ -15,7 +15,7 @@
 #include "MeshLib/Node.h"
 #include "MeshLib/Elements/Element.h"
 #include "MeshLib/MeshGenerators/MeshGenerator.h"
-#include "MeshLib/MeshSearcher.h"
+#include "MeshLib/MeshSearch/NodeSearch.h"
 #include "MeshGeoToolsLib/MeshNodeSearcher.h"
 #include "MeshGeoToolsLib/HeuristicSearchLength.h"
 #include "MeshGeoToolsLib/BoundaryElementsSearcher.h"
@@ -151,7 +151,11 @@ TEST_F(MeshLibBoundaryElementSearchInSimpleHexMesh, SurfaceSearch)
 	double sum_area_b = std::accumulate(found_faces_sfc_b.begin(), found_faces_sfc_b.end(), 0.0,
 				[](double v, MeshLib::Element*e){return v+e->getContent();});
 	ASSERT_EQ(_geometric_size*_geometric_size, sum_area_b);
-	auto connected_nodeIDs_b = MeshLib::getConnectedNodeIDs(found_faces_sfc_b);
+	MeshLib::NodeSearch ns(*_hex_mesh);
+	std::vector<std::size_t> found_faces_sfc_b_ids;
+	for (auto e : found_faces_sfc_b) found_faces_sfc_b_ids.push_back(e->getID());
+	ns.searchByElementIDs(found_faces_sfc_b_ids);
+	auto& connected_nodeIDs_b = ns.getSearchedNodeIDs();
 	ASSERT_EQ(n_nodes_2d, connected_nodeIDs_b.size());
 	for (auto nodeID : connected_nodeIDs_b)
 		ASSERT_EQ(0.0, (*_hex_mesh->getNode(nodeID))[2]); // check z coordinates
@@ -162,7 +166,11 @@ TEST_F(MeshLibBoundaryElementSearchInSimpleHexMesh, SurfaceSearch)
 	double sum_area_f = std::accumulate(found_faces_sfc_f.begin(), found_faces_sfc_f.end(), 0.0,
 				[](double v, MeshLib::Element*e){return v+e->getContent();});
 	ASSERT_EQ(_geometric_size*_geometric_size, sum_area_f);
-	auto connected_nodeIDs_f = MeshLib::getConnectedNodeIDs(found_faces_sfc_f);
+	MeshLib::NodeSearch ns_f(*_hex_mesh);
+    std::vector<std::size_t> found_faces_sfc_f_ids;
+    for (auto e : found_faces_sfc_f) found_faces_sfc_f_ids.push_back(e->getID());
+	ns_f.searchByElementIDs(found_faces_sfc_f_ids);
+	auto& connected_nodeIDs_f = ns_f.getSearchedNodeIDs();
 	ASSERT_EQ(n_nodes_2d, connected_nodeIDs_f.size());
 	for (auto nodeID : connected_nodeIDs_f)
 		ASSERT_EQ(0.0, (*_hex_mesh->getNode(nodeID))[1]); // check y coordinates
diff --git a/Tests/MeshLib/TestDuplicate.cpp b/Tests/MeshLib/TestDuplicate.cpp
index 9bd7169e50c..b6f2638aaaa 100644
--- a/Tests/MeshLib/TestDuplicate.cpp
+++ b/Tests/MeshLib/TestDuplicate.cpp
@@ -19,7 +19,7 @@
 #include "MeshLib/Node.h"
 #include "Elements/Element.h"
 #include "MeshEditing/DuplicateMeshComponents.h"
-#include "MeshEditing/removeMeshNodes.h"
+#include "MeshEditing/RemoveMeshComponents.h"
 #include "MeshGenerators/MeshGenerator.h"
 #include "MeshQuality/MeshValidation.h"
 #include "MathTools.h"
@@ -38,14 +38,14 @@ TEST(MeshLib, Duplicate)
 	ASSERT_EQ (mesh->getNNodes(), new_mesh.getNNodes());
 
 	std::vector<std::size_t> del_idx(1,1);
-	MeshLib::removeMeshNodes(*mesh, del_idx);
+	std::unique_ptr<MeshLib::Mesh> mesh2(MeshLib::removeNodes(*mesh, del_idx, "mesh2"));
 
-	ASSERT_EQ (mesh->getNElements(), new_mesh.getNElements()-2);
-	ASSERT_EQ (mesh->getNNodes(), new_mesh.getNNodes()-2);
+	ASSERT_EQ (mesh2->getNElements(), new_mesh.getNElements()-2);
+	ASSERT_EQ (mesh2->getNNodes(), new_mesh.getNNodes()-2);
 
-	ASSERT_DOUBLE_EQ (4.0, MathLib::sqrDist(*mesh->getNode(0), *new_mesh.getNode(0)));
-	ASSERT_DOUBLE_EQ (0.0, MathLib::sqrDist(*mesh->getNode(0), *new_mesh.getNode(2)));
+	ASSERT_DOUBLE_EQ (4.0, MathLib::sqrDist(*mesh2->getNode(0), *new_mesh.getNode(0)));
+	ASSERT_DOUBLE_EQ (0.0, MathLib::sqrDist(*mesh2->getNode(0), *new_mesh.getNode(2)));
 
-	ASSERT_DOUBLE_EQ (4.0, MathLib::sqrDist(*mesh->getElement(0)->getNode(0), *new_mesh.getElement(0)->getNode(0)));
-	ASSERT_DOUBLE_EQ (0.0, MathLib::sqrDist(*mesh->getElement(0)->getNode(0), *new_mesh.getElement(2)->getNode(0)));
+	ASSERT_DOUBLE_EQ (4.0, MathLib::sqrDist(*mesh2->getElement(0)->getNode(0), *new_mesh.getElement(0)->getNode(0)));
+	ASSERT_DOUBLE_EQ (0.0, MathLib::sqrDist(*mesh2->getElement(0)->getNode(0), *new_mesh.getElement(2)->getNode(0)));
 }
diff --git a/Tests/MeshLib/TestRemove.cpp b/Tests/MeshLib/TestRemove.cpp
new file mode 100644
index 00000000000..b753a8ebbc3
--- /dev/null
+++ b/Tests/MeshLib/TestRemove.cpp
@@ -0,0 +1,62 @@
+/**
+ * @file TestDuplicate.cpp
+ * @author Karsten Rink
+ * @date 2013-03-25
+ * @brief Tests for Duplicate functions
+ *
+ * @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 <memory>
+
+#include "gtest/gtest.h"
+
+#include "Mesh.h"
+#include "MeshLib/Node.h"
+#include "Elements/Element.h"
+#include "MeshEditing/RemoveMeshComponents.h"
+#include "MeshGenerators/MeshGenerator.h"
+#include "MeshQuality/MeshValidation.h"
+#include "MathTools.h"
+
+TEST(MeshLib, RemoveNodes)
+{
+	auto mesh = std::unique_ptr<MeshLib::Mesh>{
+		MeshLib::MeshGenerator::generateLineMesh(1.0, 9)};
+
+	std::vector<std::size_t> removed_node_ids;
+	for (std::size_t i=0; i<5; i++)
+		removed_node_ids.push_back(i);
+
+	auto new_mesh = std::unique_ptr<MeshLib::Mesh>{
+		MeshLib::removeNodes(*mesh, removed_node_ids, "")};
+
+	ASSERT_EQ(5u, new_mesh->getNNodes());
+	ASSERT_EQ(5u, new_mesh->getNBaseNodes());
+	ASSERT_EQ(4u, new_mesh->getNElements());
+	for (std::size_t i=0; i<new_mesh->getNNodes(); i++)
+		ASSERT_TRUE(*mesh->getNode(5+i) == *new_mesh->getNode(i));
+}
+
+TEST(MeshLib, RemoveElements)
+{
+	auto mesh = std::unique_ptr<MeshLib::Mesh>{
+		MeshLib::MeshGenerator::generateLineMesh(1.0, 9)};
+
+	std::vector<std::size_t> removed_ele_ids;
+	for (std::size_t i=0; i<5; i++)
+		removed_ele_ids.push_back(i);
+
+	auto new_mesh = std::unique_ptr<MeshLib::Mesh>{
+		MeshLib::removeElements(*mesh, removed_ele_ids, "")};
+
+	ASSERT_EQ(5u, new_mesh->getNNodes());
+	ASSERT_EQ(5u, new_mesh->getNBaseNodes());
+	ASSERT_EQ(4u, new_mesh->getNElements());
+	for (std::size_t i=0; i<new_mesh->getNNodes(); i++)
+		ASSERT_TRUE(*mesh->getNode(5+i) == *new_mesh->getNode(i));
+}
-- 
GitLab