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