MeshLib::Mesh* MeshSurfaceExtraction::getMeshSurface( const MeshLib::Mesh& mesh, const MathLib::Vector3& dir, double angle, std::string const& subsfc_node_id_backup_prop_name) { if (angle < 0 || angle > 90) { ERR ("Supported angle between 0 and 90 degrees only."); return nullptr; } INFO ("Extracting mesh surface..."); std::vector<MeshLib::Element*> sfc_elements; get2DSurfaceElements(mesh.getElements(), sfc_elements, dir, angle, mesh.getDimension()); if (sfc_elements.empty()) return nullptr; std::vector<MeshLib::Node*> sfc_nodes; std::vector<std::size_t> node_id_map(mesh.getNNodes()); get2DSurfaceNodes(sfc_nodes, mesh.getNNodes(), sfc_elements, node_id_map); // create new elements vector with newly created nodes std::vector<MeshLib::Element*> new_elements; new_elements.reserve(sfc_elements.size()); for (auto elem = sfc_elements.cbegin(); elem != sfc_elements.cend(); ++elem) { unsigned const n_elem_nodes ((*elem)->getNBaseNodes()); MeshLib::Node** new_nodes = new MeshLib::Node*[n_elem_nodes]; for (unsigned k(0); k<n_elem_nodes; k++) new_nodes[k] = sfc_nodes[node_id_map[(*elem)->getNode(k)->getID()]]; if ((*elem)->getGeomType() == MeshElemType::TRIANGLE) new_elements.push_back(new MeshLib::Tri(new_nodes)); else { assert((*elem)->getGeomType() == MeshElemType::QUAD); new_elements.push_back(new MeshLib::Quad(new_nodes)); } delete *elem; } std::vector<std::size_t> id_map; if (!subsfc_node_id_backup_prop_name.empty()) { id_map.reserve(sfc_nodes.size()); for (auto node = sfc_nodes.cbegin(); node != sfc_nodes.cend(); ++node) id_map.push_back((*node)->getID()); } MeshLib::Mesh* result (new Mesh(mesh.getName()+"-Surface", sfc_nodes, new_elements)); // transmit the original node ids of the subsurface mesh as a property if (!subsfc_node_id_backup_prop_name.empty()) { boost::optional<MeshLib::PropertyVector<std::size_t>&> orig_node_ids( result->getProperties().createNewPropertyVector<std::size_t>( subsfc_node_id_backup_prop_name , MeshLib::MeshItemType::Node, 1)); if (orig_node_ids) { orig_node_ids->resize(id_map.size()); std::copy(id_map.cbegin(), id_map.cend(), orig_node_ids->begin()); } } return result; }
int main (int argc, char* argv[]) { ApplicationsLib::LogogSetup logog_setup; TCLAP::CmdLine cmd("The tool computes the area per node of the surface mesh" " and writes the information as txt and csv data.", ' ', "0.1"); TCLAP::ValueArg<std::string> mesh_in("i", "mesh-input-file", "the name of the file containing the input mesh", true, "", "file name of input mesh"); cmd.add(mesh_in); TCLAP::ValueArg<std::string> id_prop_name("", "id-prop-name", "the name of the property containing the id information", false, "OriginalSubsurfaceNodeIDs", "property name"); cmd.add(id_prop_name); TCLAP::ValueArg<std::string> out_base_fname("p", "output-base-name", "the path and base file name the output will be written to", false, "", "output path and base name as one string"); cmd.add(out_base_fname); cmd.parse(argc, argv); std::unique_ptr<MeshLib::Mesh> surface_mesh( MeshLib::IO::readMeshFromFile(mesh_in.getValue())); INFO("Mesh read: %u nodes, %u elements.", surface_mesh->getNNodes(), surface_mesh->getNElements()); // ToDo check if mesh is read correct and if the mesh is a surface mesh // check if a node property containing the subsurface ids is available boost::optional<MeshLib::PropertyVector<std::size_t> const&> orig_node_ids( surface_mesh->getProperties().getPropertyVector<std::size_t>( id_prop_name.getValue())); // if the node property is not available generate it if (!orig_node_ids) { boost::optional<MeshLib::PropertyVector<std::size_t>&> node_ids( surface_mesh->getProperties().createNewPropertyVector<std::size_t>( id_prop_name.getValue(), MeshLib::MeshItemType::Node, 1)); if (!node_ids) { ERR("Fatal error: could not create property."); return EXIT_FAILURE; } node_ids->resize(surface_mesh->getNNodes()); std::iota(node_ids->begin(), node_ids->end(), 0); orig_node_ids = node_ids; } std::vector<double> areas( MeshLib::MeshSurfaceExtraction::getSurfaceAreaForNodes(*surface_mesh)); // pack area and node id together std::vector<std::pair<std::size_t, double>> ids_and_areas; std::transform(orig_node_ids->cbegin(), orig_node_ids->cend(), areas.cbegin(), std::back_inserter(ids_and_areas), std::make_pair<std::size_t const&, double const&>); // generate file names for output std::string path(out_base_fname.getValue()); if (path.empty()) path = BaseLib::dropFileExtension(mesh_in.getValue()); std::string const id_and_area_fname(path+".txt"); std::string const csv_fname(path+".csv"); writeToFile(id_and_area_fname, csv_fname, ids_and_areas, surface_mesh->getNodes()); return EXIT_SUCCESS; }