From 23cf5b28633e64a6a66ce3cf6819ef6a12b990f9 Mon Sep 17 00:00:00 2001
From: Karsten Rink <karsten.rink@ufz.de>
Date: Fri, 21 Feb 2014 12:19:55 +0100
Subject: [PATCH] moved Mesh::removeUnusedMeshNodes() to new
 MeshQualityController class and removed duplicate code from removeMeshNodes
 command line tool

---
 Gui/DataView/MshLayerMapper.cpp               |  1 -
 Gui/mainwindow.cpp                            |  5 ++
 MeshLib/Mesh.cpp                              | 25 --------
 MeshLib/Mesh.h                                | 10 +++-
 MeshLib/MeshEditing/removeMeshNodes.cpp       | 14 ++---
 MeshLib/MeshEditing/removeMeshNodes.h         |  3 +-
 MeshLib/MeshQuality/MeshQualityController.cpp | 57 +++++++++++++++++++
 MeshLib/MeshQuality/MeshQualityController.h   | 44 ++++++++++++++
 MeshLib/Node.h                                |  1 -
 Utils/MeshEdit/moveMeshNodes.cpp              |  3 +-
 Utils/MeshEdit/removeMeshNodes.cpp            |  4 +-
 11 files changed, 122 insertions(+), 45 deletions(-)
 create mode 100644 MeshLib/MeshQuality/MeshQualityController.cpp
 create mode 100644 MeshLib/MeshQuality/MeshQualityController.h

diff --git a/Gui/DataView/MshLayerMapper.cpp b/Gui/DataView/MshLayerMapper.cpp
index b5614bc24fd..f718910e14f 100644
--- a/Gui/DataView/MshLayerMapper.cpp
+++ b/Gui/DataView/MshLayerMapper.cpp
@@ -29,7 +29,6 @@
 #include "Elements/Hex.h"
 #include "Elements/Pyramid.h"
 #include "Elements/Prism.h"
-#include "MeshEditing/removeMeshNodes.h"
 #include "MeshSurfaceExtraction.h"
 #include "MathTools.h"
 
diff --git a/Gui/mainwindow.cpp b/Gui/mainwindow.cpp
index 57c1a2502e5..26e223cf2f4 100644
--- a/Gui/mainwindow.cpp
+++ b/Gui/mainwindow.cpp
@@ -11,6 +11,7 @@
  *              http://www.opengeosys.org/project/license
  *
  */
+
 #include "Configure.h"
 #include "mainwindow.h"
 
@@ -88,6 +89,7 @@
 #include "MeshSurfaceExtraction.h"
 #include "readMeshFromFile.h"
 #include "convertMeshToGeo.h"
+#include "MeshQuality/MeshQualityController.h"
 
 // Qt includes
 #include <QDesktopWidget>
@@ -1276,6 +1278,9 @@ void MainWindow::showDataExplorerSettingsDialog()
 
 void MainWindow::FEMTestStart()
 {
+	
+	MeshLib::MeshQualityController mqc(*(const_cast<MeshLib::Mesh*>(this->_meshModels->getMesh("mshtest"))));
+
 }
 
 
diff --git a/MeshLib/Mesh.cpp b/MeshLib/Mesh.cpp
index 62dca49178d..ee6f0f9bad9 100644
--- a/MeshLib/Mesh.cpp
+++ b/MeshLib/Mesh.cpp
@@ -41,7 +41,6 @@ Mesh::Mesh(const std::string &name,
 	//this->setNodesConnectedByEdges();
 	//this->setNodesConnectedByElements();
 	this->setElementsConnectedToElements();
-	this->removeUnusedMeshNodes();
 
 	_edge_length[0] =  std::numeric_limits<double>::max();
 	_edge_length[1] = -std::numeric_limits<double>::max();
@@ -245,29 +244,5 @@ void Mesh::setNodesConnectedByElements()
 	}
 }
 
-void Mesh::removeUnusedMeshNodes()
-{
-	unsigned count(0);
-	std::vector<MeshLib::Node*>::iterator it (this->_nodes.begin());
-	while(it != this->_nodes.end())
-	{
-		if ((*it)->getNElements() == 0)
-		{
-			delete *it;
-			*it = nullptr;
-			++it;
-			++count;
-		}
-		else ++it;
-	}
-	auto node_vec_end = std::remove(_nodes.begin(), _nodes.end(), nullptr);
-	_nodes.erase(node_vec_end, _nodes.end());
-
-	if (count)
-	{
-		INFO("Removed %d unused mesh nodes.", count );
-		this->resetNodeIDs();
-	}
-}
 
 }
diff --git a/MeshLib/Mesh.h b/MeshLib/Mesh.h
index 5f3626c3596..ecb597dbd11 100644
--- a/MeshLib/Mesh.h
+++ b/MeshLib/Mesh.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "MeshEnums.h"
+#include "MeshQuality/MeshQualityController.h"
 
 #include "BaseLib/Counter.h"
 
@@ -33,6 +34,9 @@ namespace MeshLib
  */
 class Mesh : BaseLib::Counter<Mesh>
 {
+	/* friend functions: */
+	friend void removeMeshNodes(MeshLib::Mesh &mesh, const std::vector<std::size_t> &nodes);
+
 public:
 	/// Constructor using a mesh name and an array of nodes and elements
 	Mesh(const std::string &name,
@@ -91,11 +95,11 @@ public:
 	std::size_t getID() const {return _id; }
 
 protected:
-	// Set the minimum and maximum length over the edges of the mesh.
+	/// Set the minimum and maximum length over the edges of the mesh.
 	void calcEdgeLengthRange();
 
-	/// Removes nodes that are not part of any element.
-	void removeUnusedMeshNodes();
+	/// Returns an editable reference of the node vector
+	std::vector<Node*>& getNodesVector() { return _nodes; }
 
 	/// Sets the dimension of the mesh.
 	void setDimension();
diff --git a/MeshLib/MeshEditing/removeMeshNodes.cpp b/MeshLib/MeshEditing/removeMeshNodes.cpp
index 98b494015fd..9ed1460b4c6 100644
--- a/MeshLib/MeshEditing/removeMeshNodes.cpp
+++ b/MeshLib/MeshEditing/removeMeshNodes.cpp
@@ -19,16 +19,14 @@
 
 namespace MeshLib {
 
-MeshLib::Mesh* removeMeshNodes(const MeshLib::Mesh &mesh, const std::vector<size_t> &nodes)
+void removeMeshNodes(MeshLib::Mesh &mesh, const std::vector<std::size_t> &nodes)
 {
-	MeshLib::Mesh* new_mesh (new MeshLib::Mesh(mesh));
-
 	// delete nodes and their connected elements and replace them with null pointers
 	const size_t delNodes = nodes.size();
-	std::vector<MeshLib::Node*> mesh_nodes = new_mesh->getNodes();
+	std::vector<MeshLib::Node*>& mesh_nodes = mesh.getNodesVector();
 	for (size_t i = 0; i < delNodes; ++i)
 	{
-		const MeshLib::Node* node = new_mesh->getNode(i);
+		const MeshLib::Node* node = mesh.getNode(nodes[i]);
 		std::vector<MeshLib::Element*> conn_elems = node->getElements();
 
 		for (size_t j = 0; j < conn_elems.size(); ++j)
@@ -41,16 +39,14 @@ MeshLib::Mesh* removeMeshNodes(const MeshLib::Mesh &mesh, const std::vector<size
 	}
 
 	// erase null pointers from node- and element vectors
-	std::vector<MeshLib::Element*> elements = new_mesh->getElements();
+	std::vector<MeshLib::Element*> elements = mesh.getElements();
 	auto elem_vec_end = std::remove(elements.begin(), elements.end(), nullptr);
 	elements.erase(elem_vec_end, elements.end());
 
 	auto node_vec_end = std::remove(mesh_nodes.begin(), mesh_nodes.end(), nullptr);
 	mesh_nodes.erase(node_vec_end, mesh_nodes.end());
 
-	new_mesh->resetNodeIDs(); // after removing nodes set new node-IDs
-
-	return new_mesh;
+	mesh.resetNodeIDs(); // after removing nodes set new node-IDs
 }
 
 
diff --git a/MeshLib/MeshEditing/removeMeshNodes.h b/MeshLib/MeshEditing/removeMeshNodes.h
index d1ecde3c986..b1769121699 100644
--- a/MeshLib/MeshEditing/removeMeshNodes.h
+++ b/MeshLib/MeshEditing/removeMeshNodes.h
@@ -23,7 +23,8 @@ namespace MeshLib {
 class Mesh;
 
 	/// Removes the mesh nodes (and connected elements) given in the nodes-list from the mesh.
-	MeshLib::Mesh* removeMeshNodes(const MeshLib::Mesh &mesh, const std::vector<std::size_t> &nodes);
+	/// 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
 
diff --git a/MeshLib/MeshQuality/MeshQualityController.cpp b/MeshLib/MeshQuality/MeshQualityController.cpp
new file mode 100644
index 00000000000..77ec47128a8
--- /dev/null
+++ b/MeshLib/MeshQuality/MeshQualityController.cpp
@@ -0,0 +1,57 @@
+/**
+ * \file   MeshQualityController.cpp
+ * \author Karsten Rink
+ * \date   2013-04-04
+ * \brief  Implementation of the MeshQualityController class.
+ *
+ * \copyright
+ * Copyright (c) 2013, 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 "MeshQualityController.h"
+#include "Mesh.h"
+#include "Node.h"
+#include "MeshEditing/removeMeshNodes.h"
+
+
+#include "logog/include/logog.hpp"
+
+namespace MeshLib {
+
+MeshQualityController::MeshQualityController(MeshLib::Mesh &mesh)
+{
+	this->removeUnusedMeshNodes(mesh);
+}
+
+void MeshQualityController::removeUnusedMeshNodes(MeshLib::Mesh &mesh)
+{
+	std::vector<MeshLib::Node*> nodes (mesh.getNodes());
+	std::vector<std::size_t> del_node_idx;
+	std::size_t nNodes (mesh.getNNodes());
+	for (std::size_t i=0; i<nNodes; ++i)
+	{
+		if (nodes[i]->getNElements() == 0)
+			del_node_idx.push_back(i);
+	}
+	MeshLib::removeMeshNodes(mesh, del_node_idx);
+
+	if (!del_node_idx.empty())
+		INFO("Removed %d unused mesh nodes.", del_node_idx.size());
+}
+
+void MeshQualityController::testElementGeometry(MeshLib::Mesh &mesh)
+{
+	unsigned count(0);
+	const std::size_t nElements (mesh.getNElements());
+	for (std::size_t i=0; i<nElements; ++i)
+	{
+
+	}
+}
+
+} // end namespace MeshLib
diff --git a/MeshLib/MeshQuality/MeshQualityController.h b/MeshLib/MeshQuality/MeshQualityController.h
new file mode 100644
index 00000000000..2a3d486e6bd
--- /dev/null
+++ b/MeshLib/MeshQuality/MeshQualityController.h
@@ -0,0 +1,44 @@
+/**
+ * \file   MeshQualityController.h
+ * \author Karsten Rink
+ * \date   2013-04-04
+ * \brief  Definition of the MeshQualityController class
+ *
+ * \copyright
+ * Copyright (c) 2013, 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 MESHQUALITYCONTROLLER_H
+#define MESHQUALITYCONTROLLER_H
+
+#include <vector>
+
+namespace MeshLib {
+	class Mesh;
+
+/**
+ * \brief A set of methods for manipulating mesh element values
+ */
+class MeshQualityController
+{
+public:
+	MeshQualityController(MeshLib::Mesh &mesh);
+	~MeshQualityController() {}
+
+	/// Removes nodes from the mesh that are not part of any element.
+	static void removeUnusedMeshNodes(MeshLib::Mesh &mesh);
+
+	/// Tests if elements are geometrically correct
+	static void testElementGeometry(MeshLib::Mesh &mesh);
+
+private:
+
+};
+
+} // end namespace MeshLib
+
+#endif //MESHQUALITYCONTROLLER_H
diff --git a/MeshLib/Node.h b/MeshLib/Node.h
index 0ac6e2d93dd..d91a14c194f 100644
--- a/MeshLib/Node.h
+++ b/MeshLib/Node.h
@@ -38,7 +38,6 @@ class Element;
 class Node : public GeoLib::PointWithID
 {
 	/* friend functions: */
-	friend MeshLib::Mesh* removeMeshNodes(MeshLib::Mesh const*const mesh, const std::vector<std::size_t> &nodes);
 #ifdef OGS_BUILD_GUI
 	friend int MshLayerMapper::LayerMapping(MeshLib::Mesh* msh, const std::string &rasterfile, const unsigned nLayers,
 		                                    const unsigned layer_id, double noDataReplacementValue);
diff --git a/Utils/MeshEdit/moveMeshNodes.cpp b/Utils/MeshEdit/moveMeshNodes.cpp
index e8dede492e3..d45ef8e0663 100644
--- a/Utils/MeshEdit/moveMeshNodes.cpp
+++ b/Utils/MeshEdit/moveMeshNodes.cpp
@@ -1,5 +1,5 @@
 /**
- * \file removeMeshNodes.cpp
+ * \file moveMeshNodes.cpp
  * 2012/03/07 KR Initial implementation
  */
 
@@ -11,7 +11,6 @@
 #include "AABB.h"
 #include "Mesh.h"
 #include "Node.h"
-#include "MeshEditing/removeMeshNodes.h"
 #include "MathTools.h"
 
 int find_closest_point(MeshLib::Node const*const point, std::vector<MeshLib::Node*> const& nodes, double const& max_dist)
diff --git a/Utils/MeshEdit/removeMeshNodes.cpp b/Utils/MeshEdit/removeMeshNodes.cpp
index 54d2b680d24..a1043678bc8 100644
--- a/Utils/MeshEdit/removeMeshNodes.cpp
+++ b/Utils/MeshEdit/removeMeshNodes.cpp
@@ -82,16 +82,14 @@ int main (int argc, char* argv[])
 	/**** add other keywords here ****/
 
 	// remove nodes and write new file
-	MeshLib::Mesh* new_mesh = MeshLib::removeMeshNodes(*mesh, del_nodes);
+	MeshLib::removeMeshNodes(*mesh, del_nodes);
 	
 	FileIO::Legacy::MeshIO meshIO;
 	meshIO.setMesh(mesh);
 	meshIO.setPrecision(9);
 	meshIO.writeToFile(msh_name.substr(0, msh_name.length()-4) + "_new.msh");
 	delete mesh;
-	delete new_mesh;
 	return 1;
-
 }
 
 
-- 
GitLab