bool convertMeshToGeo(const MeshLib::Mesh &mesh, GeoLib::GEOObjects &geo_objects, double eps) { if (mesh.getDimension() != 2) { ERR ("Mesh to geometry conversion is only working for 2D meshes."); return false; } // nodes to points conversion std::string mesh_name(mesh.getName()); { auto points = std::make_unique<std::vector<GeoLib::Point*>>(); points->reserve(mesh.getNumberOfNodes()); for (auto node_ptr : mesh.getNodes()) points->push_back(new GeoLib::Point(*node_ptr, node_ptr->getID())); geo_objects.addPointVec(std::move(points), mesh_name, nullptr, eps); } const std::vector<std::size_t> id_map (geo_objects.getPointVecObj(mesh_name)->getIDMap()); // elements to surface triangles conversion std::string const mat_name ("MaterialIDs"); auto bounds (MeshInformation::getValueBounds<int>(mesh, mat_name)); const unsigned nMatGroups(bounds.second-bounds.first+1); auto sfcs = std::make_unique<std::vector<GeoLib::Surface*>>(); sfcs->reserve(nMatGroups); auto const& points = *geo_objects.getPointVec(mesh_name); for (unsigned i=0; i<nMatGroups; ++i) sfcs->push_back(new GeoLib::Surface(points)); const std::vector<MeshLib::Element*> &elements = mesh.getElements(); const std::size_t nElems (mesh.getNumberOfElements()); MeshLib::PropertyVector<int> const*const materialIds = mesh.getProperties().existsPropertyVector<int>("MaterialIDs") ? mesh.getProperties().getPropertyVector<int>("MaterialIDs") : nullptr; for (unsigned i=0; i<nElems; ++i) { auto surfaceId = !materialIds ? 0 : ((*materialIds)[i] - bounds.first); MeshLib::Element* e (elements[i]); if (e->getGeomType() == MeshElemType::TRIANGLE) (*sfcs)[surfaceId]->addTriangle(id_map[e->getNodeIndex(0)], id_map[e->getNodeIndex(1)], id_map[e->getNodeIndex(2)]); if (e->getGeomType() == MeshElemType::QUAD) { (*sfcs)[surfaceId]->addTriangle(id_map[e->getNodeIndex(0)], id_map[e->getNodeIndex(1)], id_map[e->getNodeIndex(2)]); (*sfcs)[surfaceId]->addTriangle(id_map[e->getNodeIndex(0)], id_map[e->getNodeIndex(2)], id_map[e->getNodeIndex(3)]); } // all other element types are ignored (i.e. lines) } std::for_each(sfcs->begin(), sfcs->end(), [](GeoLib::Surface* sfc){ if (sfc->getNumberOfTriangles()==0) delete sfc; sfc = nullptr;}); auto sfcs_end = std::remove(sfcs->begin(), sfcs->end(), nullptr); sfcs->erase(sfcs_end, sfcs->end()); geo_objects.addSurfaceVec(std::move(sfcs), mesh_name); return true; }
MeshLib::Mesh* MeshSurfaceExtraction::getMeshBoundary(const MeshLib::Mesh &mesh) { if (mesh.getDimension()==1) return nullptr; // For 3D meshes return the 2D surface if (mesh.getDimension()==3) { MathLib::Vector3 dir(0,0,0); return getMeshSurface(mesh, dir, 90); } // For 2D meshes return the boundary lines std::vector<MeshLib::Node*> nodes = MeshLib::copyNodeVector(mesh.getNodes()); std::vector<MeshLib::Element*> boundary_elements; std::vector<MeshLib::Element*> const& org_elems (mesh.getElements()); for (auto it=org_elems.begin(); it!=org_elems.end(); ++it) { MeshLib::Element* elem (*it); std::size_t const n_edges (elem->getNEdges()); for (std::size_t i=0; i<n_edges; ++i) if (elem->getNeighbor(i) == nullptr) { MeshLib::Element const*const edge (elem->getEdge(i)); boundary_elements.push_back(MeshLib::copyElement(edge, nodes)); delete edge; } } MeshLib::Mesh* result = new MeshLib::Mesh("Boundary Mesh", nodes, boundary_elements); MeshLib::NodeSearch ns(*result); if (ns.searchUnused() == 0) { return result; } else { auto removed = MeshLib::removeNodes(*result, ns.getSearchedNodeIDs(), result->getName()); delete result; return removed; } }
std::unique_ptr<MeshLib::Mesh> appendLinesAlongPolylines( const MeshLib::Mesh& mesh, const GeoLib::PolylineVec& ply_vec) { // copy existing nodes and elements std::vector<MeshLib::Node*> vec_new_nodes = MeshLib::copyNodeVector(mesh.getNodes()); std::vector<MeshLib::Element*> vec_new_eles = MeshLib::copyElementVector(mesh.getElements(), vec_new_nodes); auto const material_ids = materialIDs(mesh); int const max_matID = material_ids ? *(std::max_element(begin(*material_ids), end(*material_ids))) : 0; std::vector<int> new_mat_ids; const std::size_t n_ply (ply_vec.size()); // for each polyline for (std::size_t k(0); k < n_ply; k++) { const GeoLib::Polyline* ply = (*ply_vec.getVector())[k]; // search nodes on the polyline MeshGeoToolsLib::MeshNodesAlongPolyline mshNodesAlongPoly( mesh, *ply, mesh.getMinEdgeLength() * 0.5, MeshGeoToolsLib::SearchAllNodes::Yes); auto &vec_nodes_on_ply = mshNodesAlongPoly.getNodeIDs(); if (vec_nodes_on_ply.empty()) { std::string ply_name; ply_vec.getNameOfElementByID(k, ply_name); INFO("No nodes found on polyline %s", ply_name.c_str()); continue; } // add line elements for (std::size_t i=0; i<vec_nodes_on_ply.size()-1; i++) { std::array<MeshLib::Node*, 2> element_nodes; element_nodes[0] = vec_new_nodes[vec_nodes_on_ply[i]]; element_nodes[1] = vec_new_nodes[vec_nodes_on_ply[i+1]]; vec_new_eles.push_back( new MeshLib::Line(element_nodes, vec_new_eles.size())); new_mat_ids.push_back(max_matID+k+1); } } // generate a mesh const std::string name = mesh.getName() + "_with_lines"; auto new_mesh = std::make_unique<MeshLib::Mesh>(name, vec_new_nodes, vec_new_eles); auto new_material_ids = new_mesh->getProperties().createNewPropertyVector<int>( "MaterialIDs", MeshLib::MeshItemType::Cell); if (!new_material_ids) { OGS_FATAL("Could not create MaterialIDs cell vector in new mesh."); } new_material_ids->reserve(new_mesh->getNumberOfElements()); if (material_ids != nullptr) { std::copy(begin(*material_ids), end(*material_ids), std::back_inserter(*new_material_ids)); } else { new_material_ids->resize(mesh.getNumberOfElements()); } std::copy(begin(new_mat_ids), end(new_mat_ids), std::back_inserter(*new_material_ids)); return new_mesh; }
PostProcessTool::PostProcessTool( MeshLib::Mesh const& org_mesh, std::vector<MeshLib::Node*> const& vec_fracture_nodes, std::vector<MeshLib::Element*> const& vec_fracutre_matrix_elements) :_org_mesh(org_mesh) { if (!org_mesh.getProperties().hasPropertyVector("displacement") || !org_mesh.getProperties().hasPropertyVector("displacement_jump1") || !org_mesh.getProperties().hasPropertyVector("levelset1") ) { OGS_FATAL("The given mesh does not have relevant properties"); } // clone nodes and elements std::vector<MeshLib::Node*> new_nodes(MeshLib::copyNodeVector(org_mesh.getNodes())); std::vector<MeshLib::Element*> new_eles( MeshLib::copyElementVector(org_mesh.getElements(), new_nodes)); // duplicate fracture nodes for (auto const* org_node : vec_fracture_nodes) { auto duplicated_node = new MeshLib::Node(org_node->getCoords(), new_nodes.size()); new_nodes.push_back(duplicated_node); _map_dup_newNodeIDs[org_node->getID()] = duplicated_node->getID(); } // split elements using the new duplicated nodes auto prop_levelset = org_mesh.getProperties().getPropertyVector<double>("levelset1"); for (auto const* org_e : vec_fracutre_matrix_elements) { // only matrix elements if (org_e->getDimension() != org_mesh.getDimension()) continue; auto const eid = org_e->getID(); // keep original if the element has levelset=0 if ((*prop_levelset)[eid] == 0) continue; // replace fracture nodes with duplicated ones MeshLib::Element* e = new_eles[eid]; for (unsigned i=0; i<e->getNumberOfNodes(); i++) { // only fracture nodes auto itr = _map_dup_newNodeIDs.find(e->getNodeIndex(i)); if (itr == _map_dup_newNodeIDs.end()) continue; // check if a node belongs to the particular fracture group auto itr2 = std::find_if(vec_fracture_nodes.begin(), vec_fracture_nodes.end(), [&](MeshLib::Node const*node) { return node->getID()==e->getNodeIndex(i);}); if (itr2 == vec_fracture_nodes.end()) continue; e->setNode(i, new_nodes[itr->second]); } } // new mesh _output_mesh.reset(new MeshLib::Mesh(org_mesh.getName(), new_nodes, new_eles)); createProperties<int>(); createProperties<double>(); copyProperties<int>(); copyProperties<double>(); calculateTotalDisplacement(); }
void ElementTreeModel::setMesh(MeshLib::Mesh const& mesh) { this->clearView(); QList<QVariant> mesh_name; mesh_name << "Name:" << QString::fromStdString(mesh.getName()) << "" << "" << ""; TreeItem* name_item = new TreeItem(mesh_name, _rootItem); _rootItem->appendChild(name_item); QList<QVariant> nodes_number; nodes_number << "#Nodes: " << QString::number(mesh.getNumberOfNodes()) << "" << ""; TreeItem* nodes_item = new TreeItem(nodes_number, _rootItem); _rootItem->appendChild(nodes_item); QList<QVariant> elements_number; elements_number << "#Elements: " << QString::number(mesh.getNumberOfElements()) << "" << ""; TreeItem* elements_item = new TreeItem(elements_number, _rootItem); _rootItem->appendChild(elements_item); const std::array<QString, 7> n_element_names = {{ "Lines:", "Triangles:", "Quads:", "Tetrahedra:", "Hexahedra:", "Pyramids:", "Prisms:" }}; const std::array<unsigned, 7>& n_element_types (MeshLib::MeshInformation::getNumberOfElementTypes(mesh)); for (std::size_t i=0; i<n_element_types.size(); ++i) { if (n_element_types[i]) { QList<QVariant> elements_number; elements_number << n_element_names[i] << QString::number(n_element_types[i]) << "" << ""; TreeItem* type_item = new TreeItem(elements_number, elements_item); elements_item->appendChild(type_item); } } QList<QVariant> bounding_box; bounding_box << "Bounding Box" << "" << "" << ""; TreeItem* aabb_item = new TreeItem(bounding_box, _rootItem); _rootItem->appendChild(aabb_item); const GeoLib::AABB aabb (MeshLib::MeshInformation::getBoundingBox(mesh)); auto const& min = aabb.getMinPoint(); auto const& max = aabb.getMaxPoint(); QList<QVariant> min_aabb; min_aabb << "Min:" << QString::number(min[0], 'f') << QString::number(min[1], 'f') << QString::number(min[2], 'f'); TreeItem* min_item = new TreeItem(min_aabb, aabb_item); aabb_item->appendChild(min_item); QList<QVariant> max_aabb; max_aabb << "Max:" << QString::number(max[0], 'f') << QString::number(max[1], 'f') << QString::number(max[2], 'f'); TreeItem* max_item = new TreeItem(max_aabb, aabb_item); aabb_item->appendChild(max_item); QList<QVariant> edges; edges << "Edge Length: " << "[" + QString::number(mesh.getMinEdgeLength(), 'f') + "," << QString::number(mesh.getMaxEdgeLength(), 'f') + "]" << ""; TreeItem* edge_item = new TreeItem(edges, _rootItem); _rootItem->appendChild(edge_item); std::vector<std::string> const& vec_names (mesh.getProperties().getPropertyVectorNames()); for (std::size_t i=0; i<vec_names.size(); ++i) { QList<QVariant> array_info; array_info << QString::fromStdString(vec_names[i]) + ": "; auto vec_bounds (MeshLib::MeshInformation::getValueBounds<int>(mesh, vec_names[i])); if (vec_bounds.second != std::numeric_limits<int>::max()) array_info << "[" + QString::number(vec_bounds.first) + "," << QString::number(vec_bounds.second) + "]" << ""; else { auto vec_bounds (MeshLib::MeshInformation::getValueBounds<double>(mesh, vec_names[i])); if (vec_bounds.second != std::numeric_limits<double>::max()) array_info << "[" + QString::number(vec_bounds.first) + "," << QString::number(vec_bounds.second) + "]" << ""; } if (array_info.size() == 1) array_info << "[ ?" << "? ]" << ""; TreeItem* vec_item = new TreeItem(array_info, _rootItem); _rootItem->appendChild(vec_item); } reset(); }
std::unique_ptr<MeshLib::Mesh> appendLinesAlongPolylines( const MeshLib::Mesh& mesh, const GeoLib::PolylineVec& ply_vec) { // copy existing nodes and elements std::vector<MeshLib::Node*> vec_new_nodes = MeshLib::copyNodeVector(mesh.getNodes()); std::vector<MeshLib::Element*> vec_new_eles = MeshLib::copyElementVector(mesh.getElements(), vec_new_nodes); std::vector<int> new_mat_ids; { if (mesh.getProperties().existsPropertyVector<int>("MaterialIDs")) { auto ids = mesh.getProperties().getPropertyVector<int>("MaterialIDs"); new_mat_ids.reserve(ids->size()); std::copy(ids->cbegin(), ids->cend(), std::back_inserter(new_mat_ids)); } } int max_matID(0); if (!new_mat_ids.empty()) max_matID = *(std::max_element(new_mat_ids.cbegin(), new_mat_ids.cend())); const std::size_t n_ply (ply_vec.size()); // for each polyline for (std::size_t k(0); k < n_ply; k++) { const GeoLib::Polyline* ply = (*ply_vec.getVector())[k]; // search nodes on the polyline MeshGeoToolsLib::MeshNodesAlongPolyline mshNodesAlongPoly( mesh, *ply, mesh.getMinEdgeLength() * 0.5, MeshGeoToolsLib::SearchAllNodes::Yes); auto &vec_nodes_on_ply = mshNodesAlongPoly.getNodeIDs(); if (vec_nodes_on_ply.empty()) { std::string ply_name; ply_vec.getNameOfElementByID(k, ply_name); INFO("No nodes found on polyline %s", ply_name.c_str()); continue; } // add line elements for (std::size_t i=0; i<vec_nodes_on_ply.size()-1; i++) { std::array<MeshLib::Node*, 2> element_nodes; element_nodes[0] = vec_new_nodes[vec_nodes_on_ply[i]]; element_nodes[1] = vec_new_nodes[vec_nodes_on_ply[i+1]]; vec_new_eles.push_back( new MeshLib::Line(element_nodes, vec_new_eles.size())); new_mat_ids.push_back(max_matID+k+1); } } // generate a mesh const std::string name = mesh.getName() + "_with_lines"; auto new_mesh = std::make_unique<MeshLib::Mesh>(name, vec_new_nodes, vec_new_eles); auto opt_mat_pv = new_mesh->getProperties().createNewPropertyVector<int>( "MaterialIDs", MeshLib::MeshItemType::Cell); if (opt_mat_pv) { auto & mat_pv = *opt_mat_pv; mat_pv.reserve(new_mat_ids.size()); std::copy(new_mat_ids.cbegin(), new_mat_ids.cend(), std::back_inserter(mat_pv)); } return new_mesh; }
int main (int argc, char* argv[]) { LOGOG_INITIALIZE(); logog::Cout* logog_cout (new logog::Cout); BaseLib::LogogSimpleFormatter *custom_format (new BaseLib::LogogSimpleFormatter); logog_cout->SetFormatter(*custom_format); TCLAP::CmdLine cmd("Remove mesh elements.", ' ', "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> mesh_out("o", "mesh-output-file", "the name of the file the mesh will be written to", true, "", "file name of output mesh"); cmd.add(mesh_out); TCLAP::SwitchArg zveArg("z", "zero-volume", "remove zero volume elements", false); cmd.add(zveArg); TCLAP::MultiArg<std::string> eleTypeArg("t", "element-type", "element type to be removed", false, "element type"); cmd.add(eleTypeArg); TCLAP::MultiArg<unsigned> matIDArg("m", "material-id", "material id", false, "material id"); cmd.add(matIDArg); cmd.parse(argc, argv); MeshLib::Mesh* mesh (FileIO::readMeshFromFile(mesh_in.getValue())); INFO("Mesh read: %d nodes, %d elements.", mesh->getNNodes(), mesh->getNElements()); // search elements IDs to be removed std::vector<std::size_t> vec_elementIDs_removed; if (zveArg.isSet()) { std::vector<std::size_t> vec_matched = searchByZeroContent(mesh->getElements()); updateUnion(vec_matched, vec_elementIDs_removed); INFO("%d zero volume elements found.", vec_matched.size()); } if (eleTypeArg.isSet()) { std::vector<std::string> eleTypeNames = eleTypeArg.getValue(); for (auto typeName : eleTypeNames) { MeshElemType type = String2MeshElemType(typeName); if (type == MeshElemType::INVALID) continue; std::vector<std::size_t> vec_matched = searchByElementType(mesh->getElements(), type); updateUnion(vec_matched, vec_elementIDs_removed); INFO("%d %s elements found.", vec_matched.size(), typeName.c_str()); } } if (matIDArg.isSet()) { std::vector<unsigned> vec_matID = matIDArg.getValue(); for (auto matID : vec_matID) { std::vector<std::size_t> vec_matched = searchByMaterialID(mesh->getElements(), matID); updateUnion(vec_matched, vec_elementIDs_removed); INFO("%d elements with material ID %d found.", vec_matched.size(), matID); } } // remove the elements INFO("Removing total %d elements...", vec_elementIDs_removed.size()); std::vector<MeshLib::Element*> tmp_eles = excludeElements(mesh->getElements(), vec_elementIDs_removed); INFO("%d elements remained.", tmp_eles.size()); std::vector<MeshLib::Node*> new_nodes; std::vector<MeshLib::Element*> new_eles; copyNodesElements(mesh->getNodes(), tmp_eles, new_nodes, new_eles); // create a new mesh object. Unsued nodes are removed while construction MeshLib::Mesh* new_mesh(new MeshLib::Mesh(mesh->getName(), new_nodes, new_eles)); // write into a file FileIO::Legacy::MeshIO meshIO; meshIO.setMesh(new_mesh); meshIO.writeToFile(mesh_out.getValue()); delete custom_format; delete logog_cout; LOGOG_SHUTDOWN(); return 0; }