Skip to content
Snippets Groups Projects
Commit d5f09aae authored by Tom Fischer's avatar Tom Fischer
Browse files

Tool CollapseMeshNode and associated class did not work in a correct way.

parent bceeb227
No related branches found
No related tags found
No related merge requests found
/**
* \file
* \author Thomas Fischer
* \date Aug 3, 2012
* \brief Implementation of the MeshCoarsener 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
*
*/
// ThirdParty/logog
#include "logog/include/logog.hpp"
#include "MeshCoarsener.h"
// GeoLib
#include "Grid.h"
// MeshLib
#include "Mesh.h"
#include "Node.h"
#include "Elements/Element.h"
namespace MeshLib {
MeshCoarsener::MeshCoarsener(Mesh const*const mesh) :
_orig_mesh (mesh)
{}
MeshCoarsener::~MeshCoarsener()
{}
Mesh* MeshCoarsener::operator()(double min_distance)
{
// copy mesh nodes, reset mesh node ids and
// store original mesh node ids in a vector
std::vector<Node*> const& orig_nodes(_orig_mesh->getNodes());
const size_t n_nodes(orig_nodes.size());
std::vector<Node*> nodes(n_nodes);
std::map<size_t,size_t> orig_ids_map;
for (size_t k(0); k < n_nodes; k++) {
nodes[k] = new Node(orig_nodes[k]->getCoords(), k);
orig_ids_map.insert(std::pair<size_t, size_t>(orig_nodes[k]->getID(), k));
}
// init grid
GeoLib::Grid<Node>* grid(new GeoLib::Grid<Node>(nodes.begin(), nodes.end(), 64));
// init id map
std::vector<size_t> id_map(n_nodes);
for (size_t k(0); k < n_nodes; k++) {
id_map[k] = nodes[k]->getID();
}
const double sqr_min_distance (min_distance * min_distance);
// do the work - search nearest nodes
for (size_t k(0); k < n_nodes; k++) {
std::vector<std::vector<Node*> const*> node_vecs_intersecting_cube;
Node const*const node(nodes[k]);
const size_t node_id_k(node->getID());
grid->getPntVecsOfGridCellsIntersectingCube(node->getCoords(), min_distance, node_vecs_intersecting_cube);
const size_t n_vecs (node_vecs_intersecting_cube.size());
for (size_t i(0); i<n_vecs; i++) {
std::vector<Node*> const* node_vec (node_vecs_intersecting_cube[i]);
const size_t n_loc_nodes (node_vec->size());
for (size_t j(0); j<n_loc_nodes; j++) {
Node const*const test_node((*node_vec)[j]);
const size_t test_node_id (test_node->getID());
if (node_id_k < test_node_id) {
if (MathLib::sqrDist(node->getCoords(), test_node->getCoords()) < sqr_min_distance) {
// two nodes are very close to each other
id_map[test_node_id] = node_id_k;
#ifndef NDEBUG
INFO("distance of nodes with ids %d and %d is %f", node_id_k, test_node_id, sqrt(MathLib::sqrDist(node->getCoords(), test_node->getCoords())));
#endif
}
}
}
}
}
// apply changes to id_map
for (size_t k(0), cnt(0); k < n_nodes; k++) {
if (id_map[k] != k) {
if (id_map[k] != id_map[id_map[k]]) {
id_map[k] = id_map[id_map[k]];
}
} else {
id_map[k] = cnt++;
}
}
// delete unused nodes
for (size_t k(0), cnt(0); k < n_nodes; k++) {
if (id_map[k] != cnt) {
delete nodes[k];
nodes[k] = NULL;
} else {
cnt++;
}
}
// remove NULL-ptr from node vector
for (std::vector<Node*>::iterator it(nodes.begin()); it != nodes.end(); ) {
if (*it == NULL) {
it = nodes.erase (it);
} else {
it++;
}
}
// reset mesh node ids
const size_t new_n_nodes(nodes.size());
for (size_t k(0); k < new_n_nodes; k++) {
nodes[k]->setID(k);
}
// copy mesh elements, reset the node pointers
std::vector<Element*> const& orig_elements(_orig_mesh->getElements());
const size_t n_elements(orig_elements.size());
std::vector<Element*> elements(n_elements);
std::vector<size_t> mapped_node_ids_of_element;
for (size_t k(0), cnt(0); k < n_elements; k++) {
Element const*const kth_orig_elem(orig_elements[k]);
const size_t n_nodes_element (kth_orig_elem->getNNodes());
mapped_node_ids_of_element.clear();
for (size_t i(0); i<n_nodes_element; i++) {
const size_t orig_node_id (kth_orig_elem->getNode(i)->getID());
std::map<size_t, size_t>::const_iterator it(orig_ids_map.find(orig_node_id));
if (it == orig_ids_map.end()) {
ERR("[MeshCoarsener::operator()] could not found mesh node id.");
} else {
mapped_node_ids_of_element.push_back(id_map[it->second]);
}
}
// check if nodes of the element are collapsed
bool not_collapsed (true);
for (size_t i(0); i<n_nodes_element-1 && not_collapsed; i++) {
const size_t id_i(mapped_node_ids_of_element[i]);
for (size_t j(i+1); j<n_nodes_element && not_collapsed; j++) {
if (id_i == mapped_node_ids_of_element[j]) {
not_collapsed = false;
}
}
}
if (! not_collapsed) {
Element* elem (kth_orig_elem->clone());
if (elem != NULL) {
for (size_t i(0); i<n_nodes_element; i++) {
elem->setNode(i, nodes[mapped_node_ids_of_element[i]]);
}
Element* revised_elem(elem->reviseElement());
elements[cnt] = revised_elem;
delete elem;
cnt++;
}
} else {
elements[cnt] = kth_orig_elem->clone();
for (size_t i(0); i<n_nodes_element; i++) {
elements[cnt]->setNode(i, nodes[mapped_node_ids_of_element[i]]);
}
cnt++;
}
}
for (std::vector<Element*>::iterator it(elements.begin()); it != elements.end(); ) {
if (*it == NULL) {
it = elements.erase(it);
} else {
it++;
}
}
return new Mesh (_orig_mesh->getName() + "Collapsed", nodes, elements);
}
} // end namespace MeshLib
/**
* \file
* \author Thomas Fischer
* \date Aug 3, 2012
* \brief Definition of the MeshCoarsener 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 MESHCOARSENER_H_
#define MESHCOARSENER_H_
#include <vector>
#include <cstddef>
// forward declaration
namespace MeshLib {
class Mesh;
}
namespace MeshLib {
/**
* The class MeshCoarsener merges mesh nodes that have a smaller
* distance than a (user) given minimal distance.
*/
class MeshCoarsener {
public:
/**
* Constructor of class MeshCoarsener that takes the mesh object that should be coarsened.
* @param mesh the mesh object
*/
MeshCoarsener(Mesh const*const mesh);
/**
* destructor.
*/
virtual ~MeshCoarsener();
/**
* create new mesh and apply the coarsening process to the mesh
* @param min_distance
*/
Mesh* operator() (double min_distance);
private:
Mesh const*const _orig_mesh;
};
}
#endif /* MESHCOARSENER_H_ */
...@@ -45,7 +45,6 @@ class Node : public GeoLib::PointWithID ...@@ -45,7 +45,6 @@ class Node : public GeoLib::PointWithID
#endif #endif
/* friend classes: */ /* friend classes: */
friend class Mesh; friend class Mesh;
friend class MeshCoarsener;
friend class MeshRevision; friend class MeshRevision;
......
...@@ -30,23 +30,6 @@ TARGET_LINK_LIBRARIES ( MeshRead ...@@ -30,23 +30,6 @@ TARGET_LINK_LIBRARIES ( MeshRead
${BOOST_LIBRARIES} ${BOOST_LIBRARIES}
) )
# Create CollapseMeshNodes executable
ADD_EXECUTABLE( CollapseMeshNodes
CollapseMeshNodes.cpp
${SOURCES}
${HEADERS}
)
TARGET_LINK_LIBRARIES ( CollapseMeshNodes
MeshLib
FileIO
MathLib
BaseLib
GeoLib
logog
${BOOST_LIBRARIES}
)
# Create MeshSearchTest executable # Create MeshSearchTest executable
ADD_EXECUTABLE( MeshSearchTest ADD_EXECUTABLE( MeshSearchTest
MeshSearchTest.cpp MeshSearchTest.cpp
......
/**
* 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/LICENSE.txt
*
* \file CollapseMeshNodes.cpp
*
* Created on Jul 31, 2012 by Thomas Fischer
*/
// BaseLib
#include "MemWatch.h"
#include "RunTime.h"
#include "tclap/CmdLine.h"
#include "LogogSimpleFormatter.h"
// ThirdParty/logog
#include "logog/include/logog.hpp"
// MeshLib
#include "Node.h"
#include "Elements/Element.h"
#include "Mesh.h"
#include "Legacy/MeshIO.h"
#include "MeshEditing/MeshCoarsener.h"
int main(int argc, char *argv[])
{
LOGOG_INITIALIZE();
BaseLib::LogogSimpleFormatter *custom_format (new BaseLib::LogogSimpleFormatter);
logog::Cout *logogCout(new logog::Cout);
logogCout->SetFormatter(*custom_format);
TCLAP::CmdLine cmd("Collapse mesh nodes and, if necessary, remove elements", ' ', "0.1");
// Define a value argument and add it to the command line.
// A value arg defines a flag and a type of value that it expects,
// such as "-m meshfile".
TCLAP::ValueArg<std::string> input_mesh_arg("m","mesh","input mesh file name",true,"","string");
// Add the argument mesh_arg to the CmdLine object. The CmdLine object
// uses this Arg to parse the command line.
cmd.add( input_mesh_arg );
TCLAP::ValueArg<std::string> output_mesh_arg("","out-mesh","mesh file name for output",false,"","string");
cmd.add( output_mesh_arg );
TCLAP::ValueArg<double> distance_arg("d","collapse-distance","maximal distance two nodes are collapsed",false,0.01,"for example you can set this parameter to 10^{-6} times maximal area length");
cmd.add( distance_arg );
cmd.parse( argc, argv );
std::string fname (input_mesh_arg.getValue());
FileIO::Legacy::MeshIO mesh_io;
#ifndef WIN32
BaseLib::MemWatch mem_watch;
unsigned long mem_without_mesh (mem_watch.getVirtMemUsage());
BaseLib::RunTime run_time;
run_time.start();
#endif
MeshLib::Mesh* mesh = mesh_io.loadMeshFromFile(fname);
#ifndef WIN32
if (mesh) {
unsigned long mem_with_mesh (mem_watch.getVirtMemUsage());
INFO ("mem for mesh: %i MB", (mem_with_mesh - mem_without_mesh)/(1024*1024));
}
run_time.stop();
if (mesh) {
INFO ("time for reading: %f s", run_time.elapsed());
}
#endif
#ifndef WIN32
unsigned long mem_without_meshgrid (mem_watch.getVirtMemUsage());
run_time.start();
#endif
MeshLib::MeshCoarsener mesh_coarsener(mesh);
MeshLib::Mesh *collapsed_mesh(mesh_coarsener (distance_arg.getValue()));
#ifndef WIN32
run_time.stop();
unsigned long mem_with_meshgrid (mem_watch.getVirtMemUsage());
INFO ("mem for meshgrid: %i MB", (mem_with_meshgrid - mem_without_meshgrid)/(1024*1024));
INFO ("time for collapsing: %f s", run_time.elapsed());
#endif
mesh_io.setMesh(collapsed_mesh);
std::string out_fname (output_mesh_arg.getValue());
if (out_fname.empty()) {
out_fname = "/home/fischeth/workspace/OGS-6/Build/CollapsedMesh.msh";
}
INFO ("writing collapsed mesh to %s", out_fname.c_str());
mesh_io.writeToFile(out_fname);
INFO ("done");
delete mesh;
delete collapsed_mesh;
delete custom_format;
delete logogCout;
LOGOG_SHUTDOWN();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment