diff --git a/libsrc/interface/CMakeLists.txt b/libsrc/interface/CMakeLists.txt index caf93017..ceb87a01 100644 --- a/libsrc/interface/CMakeLists.txt +++ b/libsrc/interface/CMakeLists.txt @@ -1,8 +1,8 @@ -target_sources(nglib PRIVATE +target_sources(nglib PRIVATE writeuser.cpp nginterface.cpp nginterface_v2.cpp read_fnf_mesh.cpp readtetmesh.cpp readuser.cpp writeabaqus.cpp writediffpack.cpp writedolfin.cpp writeelmer.cpp writefeap.cpp writefluent.cpp writegmsh.cpp writejcm.cpp - writepermas.cpp writetecplot.cpp writetet.cpp writetochnog.cpp writeuser.cpp + writepermas.cpp writetecplot.cpp writetet.cpp writetochnog.cpp wuchemnitz.cpp writegmsh2.cpp writeOpenFOAM15x.cpp rw_cgns.cpp ) diff --git a/libsrc/interface/read_fnf_mesh.cpp b/libsrc/interface/read_fnf_mesh.cpp index 39ad99ea..92c3978d 100644 --- a/libsrc/interface/read_fnf_mesh.cpp +++ b/libsrc/interface/read_fnf_mesh.cpp @@ -11,10 +11,10 @@ #include #include +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" bool ReadLine (istream & in, string & buf) { @@ -471,4 +471,5 @@ namespace netgen } mesh.ComputeNVertices(); } +static RegisterUserFormat reg_fnf ("Pro/ENGINEER Format", {".fnf"}, ReadFNFFormat, nullopt); } diff --git a/libsrc/interface/readuser.cpp b/libsrc/interface/readuser.cpp index c3aac4ae..3ad4a33d 100644 --- a/libsrc/interface/readuser.cpp +++ b/libsrc/interface/readuser.cpp @@ -15,6 +15,12 @@ namespace netgen { + extern void ReadTETFormat (Mesh & mesh, const filesystem::path & filename); + extern void ReadFNFFormat (Mesh & mesh, const filesystem::path & filename); +#ifdef NG_CGNS + extern void ReadCGNSMesh (Mesh & mesh, const filesystem::path & filename); +#endif // NG_CGNS + void ReadFile (Mesh & mesh, const filesystem::path & filename) { @@ -665,9 +671,11 @@ namespace netgen if ( ext == ".fnf" ) ReadFNFFormat (mesh, filename); +#ifdef NG_CGNS // .cgns file - CFD General Notation System if ( ext == ".cgns" ) ReadCGNSMesh (mesh, filename); +#endif // NG_CGNS if ( ext == ".stl" || ext == ".stlb" ) { @@ -695,6 +703,24 @@ namespace netgen } } } + + void ReadUserFormat(Mesh & mesh, const filesystem::path & filename, const string & format) + { + if(format == "") + return ReadFile(mesh, filename); + + if(!UserFormatRegister::HaveFormat(format)) + throw Exception("Unknown format: " + format); + + const auto & entry = UserFormatRegister::Get(format); + if(!entry.read) + throw Exception("Reading format " + format + " is not implemented"); + + (*entry.read)(mesh, filename); + } + +static RegisterUserFormat reg_uni ("Universial Format", {".unv"}, ReadFile, nullopt); +static RegisterUserFormat reg_olaf ("Olaf Format", {".emt"}, ReadFile, nullopt); } diff --git a/libsrc/interface/rw_cgns.cpp b/libsrc/interface/rw_cgns.cpp index ad0869a7..096fbfdc 100644 --- a/libsrc/interface/rw_cgns.cpp +++ b/libsrc/interface/rw_cgns.cpp @@ -808,32 +808,9 @@ namespace netgen cg_close(fn); } -} - -#else // NG_CGNS - -namespace netgen -{ - void ReadCGNSMesh (Mesh & mesh, const filesystem::path & filename) - { - PrintMessage(1, "Could not import CGNS mesh: Netgen was built without CGNS support"); - } - - tuple, vector, vector>, vector> ReadCGNSFile(const filesystem::path & filename, int base) - { - throw Exception("Netgen was built without CGNS support"); - } - - void WriteCGNSMesh (const Mesh & mesh, const filesystem::path & filename) - { - PrintMessage(1, "Could not write CGNS mesh: Netgen was built without CGNS support"); - } - - void WriteCGNSFile(shared_ptr mesh, const filesystem::path & filename, vector fields, vector> values, vector locations) - { - throw Exception("Netgen was built without CGNS support"); - } - + static RegisterUserFormat reg_cgns ("CGNS Format", {".cgns"}, + static_cast(&ReadCGNSMesh), + static_cast(&WriteCGNSMesh)); } #endif // NG_CGNS diff --git a/libsrc/interface/writeOpenFOAM15x.cpp b/libsrc/interface/writeOpenFOAM15x.cpp index d484e8d9..56b5780e 100644 --- a/libsrc/interface/writeOpenFOAM15x.cpp +++ b/libsrc/interface/writeOpenFOAM15x.cpp @@ -31,10 +31,10 @@ #include #include "../general/gzstream.h" +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" extern MeshingParameters mparam; @@ -757,5 +757,11 @@ namespace netgen cout << "Error in OpenFOAM 1.5+ Export.... Aborted!\n"; } } + +void WriteOpenFOAM15xFormatCompressed (const Mesh & mesh, const filesystem::path & dirname) { WriteOpenFOAM15xFormat(mesh, dirname, true); } +void WriteOpenFOAM15xFormatUncompressed (const Mesh & mesh, const filesystem::path & dirname) { WriteOpenFOAM15xFormat(mesh, dirname, false); } + +static RegisterUserFormat reg_openfoam ("OpenFOAM 1.5+ Format", {"*"}, nullopt, WriteOpenFOAM15xFormatUncompressed); +static RegisterUserFormat reg_openfoam_compressed ("OpenFOAM 1.5+ Compressed", {"*"}, nullopt, WriteOpenFOAM15xFormatCompressed); } diff --git a/libsrc/interface/writeabaqus.cpp b/libsrc/interface/writeabaqus.cpp index 8d698b0b..8a0557c9 100644 --- a/libsrc/interface/writeabaqus.cpp +++ b/libsrc/interface/writeabaqus.cpp @@ -10,9 +10,10 @@ #include #include +#include "writeuser.hpp" + namespace netgen { -#include "writeuser.hpp" @@ -229,4 +230,5 @@ void WriteAbaqusFormat (const Mesh & mesh, cout << "done" << endl; } +static RegisterUserFormat reg_abaqus ("Abaqus Format", {".mesh"}, nullopt, WriteAbaqusFormat); } diff --git a/libsrc/interface/writediffpack.cpp b/libsrc/interface/writediffpack.cpp index 1c6ba159..9797dbed 100644 --- a/libsrc/interface/writediffpack.cpp +++ b/libsrc/interface/writediffpack.cpp @@ -13,14 +13,13 @@ #include #include +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" void WriteDiffPackFormat (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { // double scale = globflags.GetNumFlag ("scale", 1); @@ -322,4 +321,5 @@ void WriteDiffPackFormat (const Mesh & mesh, } } } +static RegisterUserFormat reg_surface("DIFFPACK Format", {".mesh"}, nullopt, WriteDiffPackFormat); } diff --git a/libsrc/interface/writeelmer.cpp b/libsrc/interface/writeelmer.cpp index 2b0be044..75cec877 100644 --- a/libsrc/interface/writeelmer.cpp +++ b/libsrc/interface/writeelmer.cpp @@ -197,4 +197,6 @@ void WriteElmerFormat (const Mesh &mesh, outfile_h << tmap[eltype] << " " << count << "\n"; } +static RegisterUserFormat reg_elmer ("Elmer Format", {"*"}, nullopt, WriteElmerFormat); + } diff --git a/libsrc/interface/writefeap.cpp b/libsrc/interface/writefeap.cpp index 0b5aad61..bdacdd7e 100644 --- a/libsrc/interface/writefeap.cpp +++ b/libsrc/interface/writefeap.cpp @@ -13,12 +13,13 @@ #include #include +#include "writeuser.hpp" + namespace netgen { extern MeshingParameters mparam; -#include "writeuser.hpp" void WriteFEAPFormat (const Mesh & mesh, @@ -219,4 +220,5 @@ void WriteFEAPFormat (const Mesh & mesh, cout << "done" << endl; } +static RegisterUserFormat reg_feap ("FEAP Format", {".mesh"}, nullopt, WriteFEAPFormat); } diff --git a/libsrc/interface/writefluent.cpp b/libsrc/interface/writefluent.cpp index 43cb5fe3..eee7abbf 100644 --- a/libsrc/interface/writefluent.cpp +++ b/libsrc/interface/writefluent.cpp @@ -10,11 +10,10 @@ #include #include -namespace netgen -{ - #include "writeuser.hpp" +namespace netgen +{ void WriteFluentFormat (const Mesh & mesh, @@ -190,4 +189,5 @@ void WriteFluentFormat (const Mesh & mesh, cout << "done" << endl; } +static RegisterUserFormat reg_fluent ("Fluent Format", {".mesh"}, nullopt, WriteFluentFormat); } diff --git a/libsrc/interface/writegmsh.cpp b/libsrc/interface/writegmsh.cpp index 1048f582..58e7f8e6 100644 --- a/libsrc/interface/writegmsh.cpp +++ b/libsrc/interface/writegmsh.cpp @@ -17,10 +17,10 @@ #include #include #include +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" extern MeshingParameters mparam; @@ -31,7 +31,6 @@ namespace netgen */ void WriteGmshFormat (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { ofstream outfile (filename); @@ -196,6 +195,7 @@ void WriteGmshFormat (const Mesh & mesh, } +static RegisterUserFormat reg_gmsh ("Gmsh Format", {".gmsh"}, nullopt, WriteGmshFormat); } diff --git a/libsrc/interface/writegmsh2.cpp b/libsrc/interface/writegmsh2.cpp index c80208c4..845556bd 100644 --- a/libsrc/interface/writegmsh2.cpp +++ b/libsrc/interface/writegmsh2.cpp @@ -20,10 +20,10 @@ #include #include #include +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" extern MeshingParameters mparam; @@ -48,7 +48,6 @@ namespace netgen * */ void WriteGmsh2Format (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { ofstream outfile (filename); @@ -258,6 +257,7 @@ namespace netgen cout << " Invalid element type for Gmsh v2.xx Export Format !\n"; } } // End: WriteGmsh2Format +static RegisterUserFormat reg_gmsh2 ("Gmsh2 Format", {".gmsh2"}, nullopt, WriteGmsh2Format); } // End: namespace netgen diff --git a/libsrc/interface/writejcm.cpp b/libsrc/interface/writejcm.cpp index 7732b413..0c33263b 100644 --- a/libsrc/interface/writejcm.cpp +++ b/libsrc/interface/writejcm.cpp @@ -11,12 +11,12 @@ #include #include -namespace netgen -{ #include "writeuser.hpp" +namespace netgen +{ + void WriteJCMFormat (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { if (mesh.GetDimension() != 3) @@ -426,5 +426,6 @@ void WriteJCMFormat (const Mesh & mesh, cout << " JCMwave grid file written." << endl; } +static RegisterUserFormat reg_jcmwave ("JCMwave Format", {".jcm"}, nullopt, WriteJCMFormat); } diff --git a/libsrc/interface/writepermas.cpp b/libsrc/interface/writepermas.cpp index 3fbd5845..28885e67 100644 --- a/libsrc/interface/writepermas.cpp +++ b/libsrc/interface/writepermas.cpp @@ -12,14 +12,15 @@ #include -using namespace std; #include "writeuser.hpp" +using namespace std; namespace netgen { // Forward declarations (don't know, where to define them, sorry) int addComponent(string &strComp, string &strSitu, ofstream &out); + void WritePermasFormat (const Mesh &mesh, const filesystem::path &filename); // This should be the new function to export a PERMAS file void WritePermasFormat (const Mesh &mesh, const filesystem::path &filename, @@ -205,4 +206,5 @@ namespace netgen return 0; } +static RegisterUserFormat reg_permas ("Permas Format", {".mesh"}, nullopt, static_cast(&WritePermasFormat)); } diff --git a/libsrc/interface/writetecplot.cpp b/libsrc/interface/writetecplot.cpp index 2c130efb..53203503 100644 --- a/libsrc/interface/writetecplot.cpp +++ b/libsrc/interface/writetecplot.cpp @@ -9,16 +9,19 @@ #include #include +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" void WriteTecPlotFormat (const Mesh & mesh, - const CSGeometry & geom, - const string & filename) + const filesystem::path & filename) { + auto geom = dynamic_pointer_cast(mesh.GetGeometry()); + if(geom == nullptr) + throw Exception("TecPlot format requires a CSGeometry"); + INDEX i; int j, k, e, z; Vec<3> n; @@ -30,7 +33,7 @@ void WriteTecPlotFormat (const Mesh & mesh, NgArray sn(np); ofstream outfile(filename); - outfile << "TITLE=\" " << filename << "\"" << endl; + outfile << "TITLE=\" " << filename.string() << "\"" << endl; // fill hashtable @@ -56,7 +59,7 @@ void WriteTecPlotFormat (const Mesh & mesh, } - for (j = 1; j <= geom.GetNSurf(); j++) /* Flaeche Nummer j */ + for (j = 1; j <= geom->GetNSurf(); j++) /* Flaeche Nummer j */ { for (i = 1; i <= np; i++) sn.Elem(i) = 0; @@ -85,7 +88,7 @@ void WriteTecPlotFormat (const Mesh & mesh, for (i = 1; i <= np; i++) if (sn.Elem(i) != 0) { - n = geom.GetSurface(j) -> GetNormalVector ( mesh.Point(i) ); + n = geom->GetSurface(j) -> GetNormalVector ( mesh.Point(i) ); outfile << mesh.Point(i)(0) << " " /* Knoten Koordinaten */ << mesh.Point(i)(1) << " " @@ -123,5 +126,6 @@ void WriteTecPlotFormat (const Mesh & mesh, } } +static RegisterUserFormat reg_tecplot ("TecPlot Format", {".mesh"}, nullopt, WriteTecPlotFormat); } diff --git a/libsrc/interface/writetet.cpp b/libsrc/interface/writetet.cpp index 8e952ae9..89e9f278 100644 --- a/libsrc/interface/writetet.cpp +++ b/libsrc/interface/writetet.cpp @@ -6,21 +6,20 @@ #include #include #include +#include "writeuser.hpp" namespace netgen { - -#include "writeuser.hpp" - + extern void ReadTETFormat (Mesh & mesh, const filesystem::path & filename); void WriteTETFormat (const Mesh & mesh, - const string & filename)//, const string& problemType ) + const filesystem::path & filename)//, const string& problemType ) { string problemType = ""; if(!mesh.PureTetMesh()) throw NgException("Can only export pure tet mesh in this format"); - cout << "starting .tet export to file " << filename << endl; + cout << "starting .tet export to file " << filename.string() << endl; NgArray point_ids,edge_ids,face_ids; @@ -1095,4 +1094,5 @@ namespace netgen cout << ".tet export done" << endl; } +static RegisterUserFormat reg_tet ("TET Format", {".tet"}, ReadTETFormat, WriteTETFormat); } diff --git a/libsrc/interface/writetochnog.cpp b/libsrc/interface/writetochnog.cpp index 3068a385..168f6b6a 100644 --- a/libsrc/interface/writetochnog.cpp +++ b/libsrc/interface/writetochnog.cpp @@ -13,10 +13,10 @@ #include #include +#include "writeuser.hpp" namespace netgen { -#include "writeuser.hpp" void WriteTochnogFormat (const Mesh & mesh, @@ -105,4 +105,5 @@ void WriteTochnogFormat (const Mesh & mesh, cout << "done" << endl; } +static RegisterUserFormat reg_tochnog ("Tochnog Format", {".mesh"}, nullopt, WriteTochnogFormat); } diff --git a/libsrc/interface/writeuser.cpp b/libsrc/interface/writeuser.cpp index 24aeb57b..04f3780f 100644 --- a/libsrc/interface/writeuser.cpp +++ b/libsrc/interface/writeuser.cpp @@ -18,155 +18,43 @@ namespace netgen { extern MeshingParameters mparam; + Array UserFormatRegister::entries; + std::map UserFormatRegister::format_to_entry_index; void RegisterUserFormats (NgArray & names, NgArray & extensions) { - const char *types[] = + for (const auto & entry : UserFormatRegister::entries) { - "Neutral Format", ".mesh", - "Surface Mesh Format", ".mesh" , - "DIFFPACK Format", ".mesh", - "TecPlot Format", ".mesh", - "Tochnog Format", ".mesh", - "Abaqus Format", ".mesh", - "Fluent Format", ".mesh", - "Permas Format", ".mesh", - "FEAP Format", ".mesh", - "Elmer Format", "*", - "STL Format", ".stl", - "STL Extended Format", ".stl", - "VRML Format", ".*", - "Gmsh Format", ".gmsh", - "Gmsh2 Format", ".gmsh2", - "OpenFOAM 1.5+ Format", "*", - "OpenFOAM 1.5+ Compressed", "*", - "JCMwave Format", ".jcm", - "TET Format", ".tet", - "CGNS Format", ".cgns", - // { "Chemnitz Format" }, - 0 - }; - - for (int i = 0; types[2*i]; i++) - { - names.Append (types[2*i]); - extensions.Append (types[2*i+1]); + names.Append (entry.format.c_str()); + extensions.Append (entry.extensions[0].c_str()); } } - - -bool WriteUserFormat (const filesystem::path & format, +bool WriteUserFormat (const string & format, const Mesh & mesh, const filesystem::path & filename) { - // cout << "write user &hgeom = " << &hgeom << endl; - // const CSGeometry & geom = *dynamic_cast (&hgeom); - const CSGeometry & geom = *dynamic_pointer_cast (mesh.GetGeometry()); + if(!UserFormatRegister::HaveFormat(format)) + return true; - PrintMessage (1, "Export mesh to file ", filename, - ", format is ", format); + const auto & entry = UserFormatRegister::Get(format); + if(!entry.write) + return true; - if (format == "Neutral Format") - WriteNeutralFormat (mesh, geom, filename); - - else if (format == "Surface Mesh Format") - WriteSurfaceFormat (mesh, filename); - - else if (format == "DIFFPACK Format") - WriteDiffPackFormat (mesh, geom, filename); - - else if (format == "Tochnog Format") - WriteTochnogFormat (mesh, filename); - - else if (format == "TecPlot Format") - cerr << "ERROR: TecPlot format currently out of order" << endl; - // WriteTecPlotFormat (mesh, geom, filename); - - else if (format == "Abaqus Format") - WriteAbaqusFormat (mesh, filename); - - else if (format == "Fluent Format") - WriteFluentFormat (mesh, filename); - - else if (format == "Permas Format") - WritePermasFormat (mesh, filename); - - else if (format == "FEAP Format") - WriteFEAPFormat (mesh, filename); - - else if (format == "Elmer Format") - WriteElmerFormat (mesh, filename); - - else if (format == "STL Format") - WriteSTLFormat (mesh, filename); - - // Philippose - 16 August 2010 - // Added additional STL Export in which - // each face of the geometry is treated - // as a separate "solid" entity - else if (format == "STL Extended Format") - WriteSTLExtFormat (mesh, filename); - - else if (format == "VRML Format") - WriteVRMLFormat (mesh, 1, filename); - - else if (format == "Fepp Format") - WriteFEPPFormat (mesh, geom, filename); - - else if (format == "EdgeElement Format") - WriteEdgeElementFormat (mesh, geom, filename); - - else if (format == "Chemnitz Format") - WriteUserChemnitz (mesh, filename); - - else if (format == "Gmsh Format") - WriteGmshFormat (mesh, geom, filename); - - // Philippose - 29/01/2009 - // Added Gmsh v2.xx Mesh export capability - else if (format == "Gmsh2 Format") - WriteGmsh2Format (mesh, geom, filename); - - // Philippose - 25/10/2009 - // Added OpenFOAM 1.5+ Mesh export capability - else if (format == "OpenFOAM 1.5+ Format") - WriteOpenFOAM15xFormat (mesh, filename, false); - - else if (format == "OpenFOAM 1.5+ Compressed") - WriteOpenFOAM15xFormat (mesh, filename, true); - - else if (format == "JCMwave Format") - WriteJCMFormat (mesh, geom, filename); - -#ifdef OLIVER - else if (format == "TET Format") - WriteTETFormat( mesh, filename);//, "High Frequency" ); -#endif - - else if (format == "CGNS Format") - WriteCGNSMesh( mesh, filename); - - else - { - return 1; - } - - return 0; + (*entry.write)(mesh, filename); + return false; } - /* * Neutral mesh format * points, elements, surface elements */ void WriteNeutralFormat (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { cout << "write neutral, new" << endl; @@ -631,6 +519,16 @@ void WriteVRMLFormat (const Mesh & mesh, } +void WriteVRMLFormatLineset (const Mesh & mesh, const filesystem::path & filename) +{ + WriteVRMLFormat(mesh, false, filename); +} + +void WriteVRMLFormatFaceset (const Mesh & mesh, const filesystem::path & filename) +{ + WriteVRMLFormat(mesh, true, filename); +} + @@ -640,7 +538,6 @@ void WriteVRMLFormat (const Mesh & mesh, * FEPP .. a finite element package developed at University Linz, Austria */ void WriteFEPPFormat (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { @@ -771,7 +668,6 @@ void WriteFEPPFormat (const Mesh & mesh, */ void WriteEdgeElementFormat (const Mesh & mesh, - const NetgenGeometry & geom, const filesystem::path & filename) { cout << "write edge element format" << endl; @@ -898,169 +794,14 @@ void WriteEdgeElementFormat (const Mesh & mesh, } } - - - - - - - - -#ifdef OLDSTYLE_WRITE - - -void WriteFile (int typ, - const Mesh & mesh, - const CSGeometry & geom, - const filesystem::path & filename, - const filesystem::path & geomfile, - double h) -{ - - - int inverttets = mparam.inverttets; - int invertsurf = mparam.inverttrigs; - - - - - - - - - if (typ == WRITE_EDGEELEMENT) - { - // write edge element file - // Peter Harscher, ETHZ - - cout << "Write Edge-Element Format" << endl; - - ofstream outfile (filename); - - int i, j; - int ned; - - // hash table representing edges; - INDEX_2_HASHTABLE edgeht(mesh.GetNP()); - - // list of edges - NgArray edgelist; - - // edge (point) on boundary ? - NgBitArray bedge, bpoint(mesh.GetNP()); - - static int eledges[6][2] = { { 1, 2 } , { 1, 3 } , { 1, 4 }, - { 2, 3 } , { 2, 4 } , { 3, 4 } }; - - // fill hashtable (point1, point2) ----> edgenr - for (i = 1; i <= mesh.GetNE(); i++) - { - const Element & el = mesh.VolumeElement (i); - INDEX_2 edge; - for (j = 1; j <= 6; j++) - { - edge.I1() = el.PNum (eledges[j-1][0]); - edge.I2() = el.PNum (eledges[j-1][1]); - edge.Sort(); - - if (!edgeht.Used (edge)) - { - edgelist.Append (edge); - edgeht.Set (edge, edgelist.Size()); - } - } - } - - - // set bedges, bpoints - bedge.SetSize (edgelist.Size()); - bedge.Clear(); - bpoint.Clear(); - - for (i = 1; i <= mesh.GetNSE(); i++) - { - const Element2d & sel = mesh.SurfaceElement(i); - for (j = 1; j <= 3; j++) - { - bpoint.Set (sel.PNum(j)); - - INDEX_2 edge; - edge.I1() = sel.PNum(j); - edge.I2() = sel.PNum(j%3+1); - edge.Sort(); - - bedge.Set (edgeht.Get (edge)); - } - } - - - - outfile << mesh.GetNE() << endl; - // write element ---> point - for (i = 1; i <= mesh.GetNE(); i++) - { - const Element & el = mesh.VolumeElement(i); - - outfile.width(8); - outfile << i; - for (j = 1; j <= 4; j++) - { - outfile.width(8); - outfile << el.PNum(j); - } - outfile << endl; - } - - // write element ---> edge - for (i = 1; i <= mesh.GetNE(); i++) - { - const Element & el = mesh.VolumeElement (i); - INDEX_2 edge; - for (j = 1; j <= 6; j++) - { - edge.I1() = el.PNum (eledges[j-1][0]); - edge.I2() = el.PNum (eledges[j-1][1]); - edge.Sort(); - - outfile.width(8); - outfile << edgeht.Get (edge); - } - outfile << endl; - } - - // write points - outfile << mesh.GetNP() << endl; - outfile.precision (6); - for (i = 1; i <= mesh.GetNP(); i++) - { - const Point3d & p = mesh.Point(i); - - for (j = 1; j <= 3; j++) - { - outfile.width(8); - outfile << p.X(j); - } - outfile << " " - << (bpoint.Test(i) ? "1" : 0) << endl; - } - - // write edges - outfile << edgelist.Size() << endl; - for (i = 1; i <= edgelist.Size(); i++) - { - outfile.width(8); - outfile << edgelist.Get(i).I1(); - outfile.width(8); - outfile << edgelist.Get(i).I2(); - outfile << " " - << (bedge.Test(i) ? "1" : "0") << endl; - } - } - - - +static RegisterUserFormat reg_neutral("Neutral Format", {".mesh"}, ReadFile, WriteNeutralFormat); +static RegisterUserFormat reg_surface("Surface Mesh Format", {".mesh", ".surf"} ,ReadFile, WriteSurfaceFormat); +static RegisterUserFormat reg_stl ("STL Format", {".stl", ".stlb"}, ReadFile, WriteSTLFormat); +static RegisterUserFormat reg_stlx ("STL Extended Format", {".stl", ".stlb"}, nullopt, WriteSTLExtFormat); +static RegisterUserFormat reg_vrml ("VRML Format", {".*"}, nullopt, WriteVRMLFormatLineset); +static RegisterUserFormat reg_vrml_faces ("VRML Format Faces", {".*"}, nullopt, WriteVRMLFormatFaceset); +static RegisterUserFormat reg_fepp ("Fepp Format", {"*"}, nullopt, WriteFEPPFormat); +static RegisterUserFormat reg_edgeelement ("EdgeElement Format", {"*"}, nullopt, WriteEdgeElementFormat); -} -#endif } diff --git a/libsrc/interface/writeuser.hpp b/libsrc/interface/writeuser.hpp index 2c604e9d..99dc21e0 100644 --- a/libsrc/interface/writeuser.hpp +++ b/libsrc/interface/writeuser.hpp @@ -7,176 +7,73 @@ /* Date: 10. Dec. 97 */ /**************************************************************************/ +#include +#include +#include + +#include + namespace netgen { -DLL_HEADER extern -void WriteFile (int typ, - const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename, - const filesystem::path & geomfile = "", - double h = 0); +using namespace std::filesystem; + +typedef std::function FWrite; +typedef std::function FRead; +typedef std::function FTest; + +struct UserFormatRegister { + struct UserFormatEntry { + string format; + Array extensions; + optional read; + optional write; + }; + DLL_HEADER static Array entries; + DLL_HEADER static std::map format_to_entry_index; + + static void Register(UserFormatEntry && entry) { + format_to_entry_index[entry.format] = entries.Size(); + entries.Append( std::move(entry) ); + } + + static const bool HaveFormat(string format) { + return format_to_entry_index.count(format) > 0; + } + static const UserFormatEntry & Get(string format) { + return entries[format_to_entry_index[format]]; + } + + template + static void IterateFormats(TFunc func, bool need_read=false, bool need_write=false) { + Array import_formats; + for(const auto & e: entries) + if((!need_read || e.read) && (!need_write || e.write)) + import_formats.Append(e.format); + QuickSort(import_formats); + for(auto format : import_formats) + func(entries[format_to_entry_index[format]]); + } + +}; + +struct RegisterUserFormat { + RegisterUserFormat(string format, Array extensions, optional read, optional write, FTest ftest = [](const filesystem::path & ){return true;}) + { + UserFormatRegister::Register({format, std::move(extensions), std::move(read), std::move(write)}); + } +}; + +DLL_HEADER void ReadFile(Mesh & mesh, const filesystem::path & filename); +DLL_HEADER void ReadUserFormat(Mesh & mesh, const filesystem::path & filename, const string & format = ""); - -DLL_HEADER extern -void ReadFile (Mesh & mesh, - const filesystem::path & filename); - - - - - - -extern -void WriteNeutralFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - -extern -void WriteSurfaceFormat (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WriteSTLFormat (const Mesh & mesh, - const filesystem::path & filename); - - -// Philippose - 16 August 2010 -// Added the STL Extended format in which -// each face of the geometry is treated as -// a separate "solid" entity in the STL file -extern -void WriteSTLExtFormat (const Mesh & mesh, - const filesystem::path & filename); - - -extern -void WriteVRMLFormat (const Mesh & mesh, - bool faces, - const filesystem::path & filename); - -extern -void WriteFEPPFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - -extern -void WriteGmshFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - - -// Philippose - 29/01/2009 -// Added GMSH v2.xx Mesh Export support -void WriteGmsh2Format (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - - -// Philippose - 25/10/2009 -// Added OpenFOAM 1.5+ Mesh Export support -extern -void WriteOpenFOAM15xFormat (const Mesh & mesh, - const filesystem::path & casename, - const bool compressed); - - -extern -void WriteUserChemnitz (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WriteJCMFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - - -extern -void WriteDiffPackFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - -extern -void WriteTochnogFormat (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WriteTecPlotFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - -extern -void WriteAbaqusFormat (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WriteFluentFormat (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WritePermasFormat (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WriteFEAPFormat (const Mesh & mesh, - const filesystem::path & filename); - -extern -void WriteElmerFormat (const Mesh & mesh, - const filesystem::path & filename); - - -extern -void WriteEdgeElementFormat (const Mesh & mesh, - const NetgenGeometry & geom, - const filesystem::path & filename); - - - -#ifdef OLIVER -extern -void WriteTETFormat (const Mesh & mesh, - const filesystem::path & filename); - -#endif - -extern void ReadTETFormat (Mesh & mesh, - const filesystem::path & filename); - - -extern void ReadFNFFormat (Mesh & mesh, - const filesystem::path & filename); - - - -extern void DLL_HEADER ReadCGNSMesh (Mesh & mesh, - const filesystem::path & filename); - -extern void DLL_HEADER WriteCGNSMesh (const Mesh & mesh, - const filesystem::path & filename); - -// read/write mesh and solutions from CGNS file -extern tuple, vector, vector>, vector> -DLL_HEADER ReadCGNSFile(const filesystem::path & filename, int base); - -extern void DLL_HEADER WriteCGNSFile(shared_ptr mesh, const filesystem::path & filename, vector fields, - vector> values, vector locations); - - -void WriteDolfinFormat (const Mesh & mesh, - const filesystem::path & filename); - +extern bool DLL_HEADER WriteUserFormat (const string & format, + const Mesh & mesh, + const filesystem::path & filename); extern void DLL_HEADER RegisterUserFormats (NgArray & names, NgArray & extensions); - -extern bool DLL_HEADER WriteUserFormat (const filesystem::path & format, - const Mesh & mesh, - // const NetgenGeometry & geom, - const filesystem::path & filename); - } #endif diff --git a/libsrc/interface/wuchemnitz.cpp b/libsrc/interface/wuchemnitz.cpp index 6798993f..ffc0b864 100644 --- a/libsrc/interface/wuchemnitz.cpp +++ b/libsrc/interface/wuchemnitz.cpp @@ -9,6 +9,8 @@ #include #include +#include "writeuser.hpp" + namespace netgen { @@ -316,4 +318,5 @@ namespace netgen WriteFile (outfile); cout << "Wrote Chemnitz standard file" << endl; } +static RegisterUserFormat reg_chemnitz ("Chemnitz Format", {"*"}, nullopt, WriteUserChemnitz ); } diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 8eace9e8..c8fdd6bc 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -79,6 +79,10 @@ namespace netgen extern bool netgen_executable_started; extern shared_ptr ng_geometry; extern void Optimize2d (Mesh & mesh, MeshingParameters & mp, int faceindex=0); +#ifdef NG_CGNS + extern tuple, vector, vector>, vector> ReadCGNSFile(const filesystem::path & filename, int base); + extern void WriteCGNSFile(shared_ptr mesh, const filesystem::path & filename, vector fields, vector> values, vector locations); +#endif // NG_CGNS } @@ -725,6 +729,20 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) ExportArray(m); ExportArray(m); + string export_docu = "Export mesh to other file format. Supported formats are:\n"; + Array export_formats; + for(auto & e : UserFormatRegister::entries) + if(e.write) { + string s = '\t'+e.format+"\t("+e.extensions[0]; + for(auto & ext : e.extensions.Range(1, e.extensions.Size())) + s += ", "+ext; + s += ")\n"; + export_formats.Append(s); + } + QuickSort(export_formats); + for(const auto & s : export_formats) + export_docu += s; + py::implicitly_convertible< int, PointIndex>(); py::class_> (m, "NetgenGeometry", py::dynamic_attr()) @@ -932,18 +950,11 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def("Export", [] (Mesh & self, string filename, string format) { - if (WriteUserFormat (format, self, /* *self.GetGeometry(), */ filename)) - { - string err = string ("nothing known about format")+format; - NgArray names, extensions; - RegisterUserFormats (names, extensions); - err += "\navailable formats are:\n"; - for (auto name : names) - err += string("'") + name + "'\n"; - throw NgException (err); - } + if (WriteUserFormat (format, self, filename)) + throw Exception ("Nothing known about format"+format); }, - py::arg("filename"), py::arg("format"),py::call_guard()) + py::arg("filename"), py::arg("format"), export_docu.c_str(), + py::call_guard()) .def_property("dim", &Mesh::GetDimension, &Mesh::SetDimension) @@ -1672,20 +1683,21 @@ project_boundaries : Optional[str] = None }) ; - m.def("ImportMesh", [](const string& filename) + string import_docu = "Import mesh from other file format. Leaving format parameter empty guesses based on file extension.\nSupported formats are:\n"; + UserFormatRegister::IterateFormats([&](auto & e) { + string s = '\t'+e.format+"\t("+e.extensions[0]; + for(auto & ext : e.extensions.Range(1, e.extensions.Size())) + s += ", "+ext; + s += ")\n"; + import_docu += s; + }, true); + + m.def("ImportMesh", [](const string& filename, const string & format) { auto mesh = make_shared(); - ReadFile(*mesh, filename); + ReadUserFormat(*mesh, filename, format); return mesh; - }, py::arg("filename"), - R"delimiter(Import mesh from other file format, supported file formats are: - Neutral format (*.mesh, *.emt) - Surface file (*.surf) - Universal format (*.unv) - Olaf format (*.emt) - Tet format (*.tet) - Pro/ENGINEER format (*.fnf) -)delimiter"); + }, py::arg("filename"), py::arg("format")="", import_docu.c_str()); py::enum_(m,"MeshingStep") .value("ANALYSE", MESHCONST_ANALYSE) .value("MESHEDGES", MESHCONST_MESHEDGES) @@ -1757,6 +1769,7 @@ project_boundaries : Optional[str] = None m.attr("debugparam") = py::cast(&debugparam); +#ifdef NG_CGNS m.def("ReadCGNSFile", &ReadCGNSFile, py::arg("filename"), py::arg("base")=1, "Read mesh and solution vectors from CGNS file"); m.def("WriteCGNSFile", &WriteCGNSFile, py::arg("mesh"), py::arg("filename"), py::arg("names"), py::arg("values"), py::arg("locations"), R"(Write mesh and solution vectors to CGNS file, possible values for locations: @@ -1765,6 +1778,7 @@ project_boundaries : Optional[str] = None FaceCenter = 2 CellCenter = 3 )"); +#endif // NG_CGNS py::class_> (m, "SurfaceGeometry") .def(py::init<>()) diff --git a/ng/menustat.tcl b/ng/menustat.tcl index 5be804c2..cd5d3a02 100644 --- a/ng/menustat.tcl +++ b/ng/menustat.tcl @@ -222,9 +222,15 @@ loadmeshinifile; +set meshimportformats [Ng_GetImportFormats] .ngmenu.file add command -label "Import Mesh..." \ -command { + foreach importformat $meshimportformats { + if { [lindex $importformat 0] == $importfiletype } { + set extension [lindex $importformat 1] + } + } set types { {"Neutral format" {.mesh .emt} } {"Surface mesh format" {.surf} } @@ -235,9 +241,9 @@ loadmeshinifile; {"Pro/ENGINEER neutral format" {.fnf} } {"CFD General Notation System" {.cgns} } } - set file [tk_getOpenFile -filetypes $types ] + set file [tk_getOpenFile -filetypes $meshimportformats -typevariable importfiletype] if {$file != ""} { - Ng_ImportMesh $file + Ng_ImportMesh $file $importfiletype set selectvisual mesh Ng_SetVisParameters redraw diff --git a/ng/ngpkg.cpp b/ng/ngpkg.cpp index e3778cf4..e8113567 100644 --- a/ng/ngpkg.cpp +++ b/ng/ngpkg.cpp @@ -282,17 +282,33 @@ namespace netgen } + int Ng_GetImportFormats (ClientData clientData, + Tcl_Interp * interp, + int argc, tcl_const char *argv[]) + { + ostringstream fstr; + UserFormatRegister::IterateFormats([&](auto & entry) { + fstr << "{ {" << entry.format << "} {" << entry.extensions[0]; + for(auto ext : entry.extensions.Range(1, entry.extensions.Size())) + fstr << ' ' << ext; + fstr << "} }\n"; + }, true, false); + + Tcl_SetResult (interp, const_cast(fstr.str().c_str()), TCL_VOLATILE); + return TCL_OK; + } + int Ng_GetExportFormats (ClientData clientData, Tcl_Interp * interp, int argc, tcl_const char *argv[]) { - NgArray userformats; - NgArray extensions; - RegisterUserFormats (userformats, extensions); - ostringstream fstr; - for (int i = 1; i <= userformats.Size(); i++) - fstr << "{ {" << userformats.Get(i) << "} {" << extensions.Get(i) << "} }\n"; + UserFormatRegister::IterateFormats([&](auto & entry) { + fstr << "{ {" << entry.format << "} {" << entry.extensions[0]; + for(auto ext : entry.extensions.Range(1, entry.extensions.Size())) + fstr << ' ' << ext; + fstr << "} }\n"; + }, false, true); Tcl_SetResult (interp, const_cast(fstr.str().c_str()), TCL_VOLATILE); return TCL_OK; @@ -333,11 +349,12 @@ namespace netgen int argc, tcl_const char *argv[]) { const string filename (argv[1]); + const string format (argv[2]); PrintMessage (1, "import mesh from ", filename); mesh = make_shared(); - ReadFile (*mesh, filename); + ReadUserFormat (*mesh, filename, format); PrintMessage (2, mesh->GetNP(), " Points, ", mesh->GetNE(), " Elements."); @@ -2877,6 +2894,10 @@ void PlayAnimFile(const char* name, int speed, int maxcnt) (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); + Tcl_CreateCommand (interp, "Ng_GetImportFormats", Ng_GetImportFormats, + (ClientData)NULL, + (Tcl_CmdDeleteProc*) NULL); + Tcl_CreateCommand (interp, "Ng_GetExportFormats", Ng_GetExportFormats, (ClientData)NULL, (Tcl_CmdDeleteProc*) NULL); diff --git a/ng/onetcl.cpp b/ng/onetcl.cpp index 63d7f085..7e5254c6 100644 --- a/ng/onetcl.cpp +++ b/ng/onetcl.cpp @@ -250,6 +250,7 @@ DLL_HEADER const char * ngscript[] = {"" ,"set status_filename 0\n" ,"set status_tetqualclasses \"10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40\"\n" ,"set exportfiletype \"Neutral Format\"\n" +,"set importfiletype \"Neutral Format\"\n" ,"set preproc.facenr 0\n" ,"set preproc.selectmode query\n" ,"set preproc.numtrig 0\n" @@ -860,8 +861,14 @@ DLL_HEADER const char * ngscript[] = {"" ,"Ng_ReadStatus;\n" ,"}\n" ,"}\n" +,"set meshimportformats [Ng_GetImportFormats]\n" ,".ngmenu.file add command -label \"Import Mesh...\" \\\n" ,"-command {\n" +,"foreach importformat $meshimportformats {\n" +,"if { [lindex $importformat 0] == $importfiletype } {\n" +,"set extension [lindex $importformat 1]\n" +,"}\n" +,"}\n" ,"set types {\n" ,"{\"Neutral format\" {.mesh .emt} }\n" ,"{\"Surface mesh format\" {.surf} }\n" @@ -872,9 +879,9 @@ DLL_HEADER const char * ngscript[] = {"" ,"{\"Pro/ENGINEER neutral format\" {.fnf} }\n" ,"{\"CFD General Notation System\" {.cgns} }\n" ,"}\n" -,"set file [tk_getOpenFile -filetypes $types ]\n" +,"set file [tk_getOpenFile -filetypes $meshimportformats -typevariable importfiletype]\n" ,"if {$file != \"\"} {\n" -,"Ng_ImportMesh $file\n" +,"Ng_ImportMesh $file $importfiletype\n" ,"set selectvisual mesh\n" ,"Ng_SetVisParameters\n" ,"redraw\n" diff --git a/ng/variables.tcl b/ng/variables.tcl index e2748ecc..0ef9bdb2 100644 --- a/ng/variables.tcl +++ b/ng/variables.tcl @@ -232,6 +232,7 @@ set status_filename 0 set status_tetqualclasses "10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40 10 20 30 40" set exportfiletype "Neutral Format" +set importfiletype "Neutral Format" set preproc.facenr 0 set preproc.selectmode query