#include #include #include "rw_medit.hpp" namespace netgen { void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map, int> & index_map) { static Timer tall("ReadMeditMesh"); RegionTimer rtall(tall); if(!filesystem::exists(filename)) throw Exception("File does not exist: " + filename.string()); auto fin = ifstream(filename); string token; int version, dim; mesh.ClearFaceDescriptors(); int index_cnt[4] = {0,0,0,0}; auto getIndex = [&](int eldim, int index) { if(index_map.count({eldim,index})==0) { auto n = ++index_cnt[eldim]; index_map[{eldim, index}] = n; if(eldim==2) { auto fd = FaceDescriptor(n-1,1,0,0); fd.SetBCProperty(n); mesh.AddFaceDescriptor (fd); } } return index_map[{eldim, index}]; }; while(true) { fin >> token; int index; // cout << "token: " << token << endl; if(token == "End") { break; } else if(token == "" || std::regex_match(token, std::regex("^[\\s]*$"))) { continue; } else if(token == "MeshVersionFormatted") { fin >> version; } else if(token == "Dimension") { fin >> dim; mesh.SetDimension(dim); } else if(token == "Vertices") { int nvert; fin >> nvert; Point<3> p{0.,0.,0.}; for([[maybe_unused]] auto k : Range(nvert)) { for(auto i : Range(dim)) fin >> p[i]; fin >> index; mesh.AddPoint(p); } } else if(token == "Edges") { int nedge; fin >> nedge; Segment seg; for([[maybe_unused]] auto k : Range(nedge)) { for(auto i : Range(2)) fin >> seg[i]; fin >> seg.edgenr; seg.edgenr = getIndex(1, seg.edgenr); seg.si = seg.edgenr; mesh.AddSegment(seg); } } else if(token == "Triangles") { int ntrig, index; fin >> ntrig; Element2d sel; for([[maybe_unused]] auto k : Range(ntrig)) { for(auto i : Range(3)) fin >> sel[i]; fin >> index; sel.SetIndex(getIndex(2, index)); mesh.AddSurfaceElement(sel); } } else if(token == "Tetrahedra") { int ntet; fin >> ntet; Element el(4); for([[maybe_unused]] auto k : Range(ntet)) { for(auto i : Range(4)) fin >> el[i]; fin >> index; el.SetIndex(getIndex(3, index)); el.Invert(); mesh.AddVolumeElement(el); } } else if(token == "Corners") { int ncorners; fin >> ncorners; Element0d el; for([[maybe_unused]] auto k : Range(ncorners)) { fin >> el.pnum; } } else if(token == "RequiredVertices") { int nverts; fin >> nverts; int vert; for([[maybe_unused]] auto k : Range(nverts)) { fin >> vert; } } else if(token == "Normals") { int nnormals; fin >> nnormals; Vec<3> normal; for([[maybe_unused]] auto k : Range(nnormals)) { fin >> normal[0]; fin >> normal[1]; fin >> normal[2]; } } else if(token == "NormalAtVertices") { int nnormals; fin >> nnormals; int vert; int normal; for([[maybe_unused]] auto k : Range(nnormals)) { fin >> normal; fin >> vert; } } else if(token == "Tangents") { int ntangents; fin >> ntangents; Vec<3> tangent; for([[maybe_unused]] auto k : Range(ntangents)) { fin >> tangent[0]; fin >> tangent[1]; fin >> tangent[2]; } } else if(token == "TangentAtVertices") { int ntangents; fin >> ntangents; int vert; int tangent; for([[maybe_unused]] auto k : Range(ntangents)) { fin >> tangent; fin >> vert; } } else if(token == "Ridges") { int nridges; fin >> nridges; int ridge; for([[maybe_unused]] auto k : Range(nridges)) { fin >> ridge; } } else { cout << "unknown token " << token << endl; int nitems; fin >> nitems; string s; for([[maybe_unused]] auto i : Range(nitems)) fin >> s; // read one line } } } void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename) { map, int> index_map; ReadMeditFormat(mesh, filename, index_map); } void WriteMeditFormat (const Mesh & mesh, const filesystem::path & filename, map, int> & index_map) { static Timer tall("WriteMeditFormat"); RegionTimer rtall(tall); auto fout = ofstream(filename); fout << "MeshVersionFormatted 2\n"; fout << "Dimension\n" << mesh.GetDimension() << endl; fout << "Vertices\n" << mesh.GetNP() << endl; int base_index = 0; int max_index = 0; auto getIndex = [&](int i, int dim) { max_index = max(max_index, i+base_index); auto index = base_index+i; index_map[{dim,i}] = index; return index; }; fout << setprecision(16); for(const auto & p : mesh.Points()) { for(auto i : Range(mesh.GetDimension())) fout << p[i] << ' '; fout << getIndex(1, 0) << endl; } base_index = max_index; fout << "Edges\n" << mesh.GetNSeg() << endl; for(const auto & seg : mesh.LineSegments()) fout << seg[0] << ' ' << seg[1] << ' ' << getIndex(seg.edgenr, 1) << endl; base_index = max_index; fout << "Triangles\n" << mesh.GetNSE() << endl; for(const auto & sel : mesh.SurfaceElements()) fout << sel[0] << ' ' << sel[1] << ' ' << sel[2] << ' ' << getIndex(sel.GetIndex(), 2) << endl; base_index = max_index; fout << "Tetrahedra\n" << mesh.GetNE() << endl; for(const auto & el : mesh.VolumeElements()) fout << el[0] << ' ' << el[1] << ' ' << el[2] << ' ' << el[3] << '\t' << getIndex(el.GetIndex(), 3) << endl; fout << "End" << endl; } void WriteMeditFormat (const Mesh & mesh, const filesystem::path & filename) { map, int> index_map; WriteMeditFormat(mesh, filename, index_map); } static RegisterUserFormat reg_medit ("Medit Format", {".mesh"}, static_cast(ReadMeditFormat), static_cast(WriteMeditFormat)); } // namespace netgen