From 98b55c117efb07dd108c10a2d6794a7bb7c15fd6 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Sat, 19 Aug 2006 04:24:03 +0000 Subject: [PATCH] added binary stl export --- Common/Context.h | 2 +- Common/DefaultOptions.h | 2 + Common/Options.cpp | 13 ++++--- Common/Options.h | 1 + Fltk/Callbacks.cpp | 12 +++--- Fltk/GUI_Extras.cpp | 57 ++++++++++++++++++++++++++- Fltk/GUI_Extras.h | 1 + Geo/GModel.h | 2 +- Geo/GModelIO.cpp | 27 +++++++++---- Geo/MElement.cpp | 75 +++++++++++++++++++++--------------- Geo/MElement.h | 2 +- Parser/CreateFile.cpp | 4 +- doc/texinfo/opt_general.texi | 4 +- doc/texinfo/opt_mesh.texi | 5 +++ 14 files changed, 150 insertions(+), 57 deletions(-) diff --git a/Common/Context.h b/Common/Context.h index 957e52fca9..e3f9716bd6 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -182,7 +182,7 @@ public : return val; } int oldxtrude, oldxtrude_recombine; - int allow_degenerated_extrude, save_all; + int allow_degenerated_extrude, save_all, stl_binary; char *triangle_options; int smooth_normals, reverse_all_normals; double angle_smooth_normals; diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index c2c15e5050..4e0b623307 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -993,6 +993,8 @@ StringXNumber MeshOptions_Number[] = { "Disable dubious point insertion tests" }, { F|O, "StlDistanceTol" , opt_mesh_stl_distance_tol, 5.e-7 , "Distance tolerance between two distinct vertices in STL meshes" }, + { F|O, "StlBinary" , opt_mesh_stl_binary , 0. , + "Save STL files in binary format?" }, { F|O, "SurfaceEdges" , opt_mesh_surfaces_edges , 1. , "Display edges of surface mesh?" }, { F|O, "SurfaceFaces" , opt_mesh_surfaces_faces , 0. , diff --git a/Common/Options.cpp b/Common/Options.cpp index 047b9a06f7..d327fdc2cc 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -1,4 +1,4 @@ -// $Id: Options.cpp,v 1.299 2006-08-18 21:11:42 geuzaine Exp $ +// $Id: Options.cpp,v 1.300 2006-08-19 04:24:02 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -4626,6 +4626,13 @@ double opt_mesh_msh_file_version(OPT_ARGS_NUM) return CTX.mesh.msh_file_version; } +double opt_mesh_stl_binary(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX.mesh.stl_binary = (int)val; + return CTX.mesh.stl_binary; +} + double opt_mesh_nb_smoothing(OPT_ARGS_NUM) { if(action & GMSH_SET) @@ -4641,10 +4648,6 @@ double opt_mesh_nb_partitions(OPT_ARGS_NUM) { if(action & GMSH_SET) CTX.mesh.nbPartitions = (int)val; - //#if defined(HAVE_FLTK) - // if(WID && (action & GMSH_GUI)) - // WID->mesh_value[0]->value(CTX.mesh.nb_smoothing); - //#endif return CTX.mesh.nbPartitions; } diff --git a/Common/Options.h b/Common/Options.h index 0ed6ff7592..0cad7a6506 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -447,6 +447,7 @@ double opt_mesh_light_lines(OPT_ARGS_NUM); double opt_mesh_light_two_side(OPT_ARGS_NUM); double opt_mesh_format(OPT_ARGS_NUM); double opt_mesh_msh_file_version(OPT_ARGS_NUM); +double opt_mesh_stl_binary(OPT_ARGS_NUM); double opt_mesh_nb_smoothing(OPT_ARGS_NUM); double opt_mesh_stl_distance_tol(OPT_ARGS_NUM); double opt_mesh_nb_elem_per_rc(OPT_ARGS_NUM); diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index c586e98c15..61043149c6 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -1,4 +1,4 @@ -// $Id: Callbacks.cpp,v 1.442 2006-08-19 01:12:38 geuzaine Exp $ +// $Id: Callbacks.cpp,v 1.443 2006-08-19 04:24:03 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -650,26 +650,25 @@ int _save_pos(char *name) int _save_unv(char *name) { - CreateOutputFile(name, CTX.mesh.format = FORMAT_UNV); + CreateOutputFile(name, FORMAT_UNV); return 1; } int _save_mesh(char *name) { - CreateOutputFile(name, CTX.mesh.format = FORMAT_MESH); + CreateOutputFile(name, FORMAT_MESH); return 1; } int _save_vrml(char *name) { - CreateOutputFile(name, CTX.mesh.format = FORMAT_VRML); + CreateOutputFile(name, FORMAT_VRML); return 1; } int _save_stl(char *name) { - CreateOutputFile(name, CTX.mesh.format = FORMAT_STL); - return 1; + return stl_dialog(name); } int _save_ps(char *name) @@ -752,6 +751,7 @@ int _save_auto(char *name) switch(GuessFileFormatFromFileName(name)){ case FORMAT_OPT : return _save_options(name); case FORMAT_MSH : return _save_msh(name); + case FORMAT_STL : return _save_stl(name); case FORMAT_PS : return _save_ps(name); case FORMAT_EPS : return _save_eps(name); case FORMAT_EPSTEX : return _save_epstex(name); diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp index 3bda8024a3..ba4b10c38c 100644 --- a/Fltk/GUI_Extras.cpp +++ b/Fltk/GUI_Extras.cpp @@ -1,4 +1,4 @@ -// $Id: GUI_Extras.cpp,v 1.18 2006-08-08 04:42:43 geuzaine Exp $ +// $Id: GUI_Extras.cpp,v 1.19 2006-08-19 04:24:03 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -582,3 +582,58 @@ int msh_dialog(char *name) return 0; } +// save stl dialog + +int stl_dialog(char *name) +{ + struct _stl_dialog{ + Fl_Window *window; + Fl_Choice *c; + Fl_Button *ok, *cancel; + }; + static _stl_dialog *dialog = NULL; + + static Fl_Menu_Item formatmenu[] = { + {"ASCII", 0, 0, 0}, + {"Binary", 0, 0, 0}, + {0} + }; + + if(!dialog){ + dialog = new _stl_dialog; + int h = 3*10 + 25 + 1*25, y = 0; + // not a "Dialog_Window" since it is modal + dialog->window = new Fl_Double_Window(200, h, "STL Options"); y = 10; + dialog->window->box(GMSH_WINDOW_BOX); + dialog->c = new Fl_Choice(10, y, 130, 25, "Format"); y+= 25; + dialog->c->menu(formatmenu); + dialog->c->align(FL_ALIGN_RIGHT); + dialog->ok = new Fl_Return_Button(10, y+10, 85, 25, "OK"); + dialog->cancel = new Fl_Button(105, y+10, 85, 25, "Cancel"); + dialog->window->set_modal(); + dialog->window->end(); + dialog->window->hotspot(dialog->window); + } + + dialog->c->value(CTX.mesh.stl_binary ? 1 : 0); + dialog->window->show(); + + while(dialog->window->shown()){ + Fl::wait(); + for (;;) { + Fl_Widget* o = Fl::readqueue(); + if (!o) break; + if (o == dialog->ok) { + opt_mesh_stl_binary(0, GMSH_SET | GMSH_GUI, dialog->c->value()); + CreateOutputFile(name, FORMAT_STL); + dialog->window->hide(); + return 1; + } + if (o == dialog->window || o == dialog->cancel){ + dialog->window->hide(); + return 0; + } + } + } + return 0; +} diff --git a/Fltk/GUI_Extras.h b/Fltk/GUI_Extras.h index 798ba31cfb..22ec826fc5 100644 --- a/Fltk/GUI_Extras.h +++ b/Fltk/GUI_Extras.h @@ -34,6 +34,7 @@ int gif_dialog(char *filename); int gl2ps_dialog(char *filename, char *title, int format, int TeX); int options_dialog(char *filename); int msh_dialog(char *filename); +int stl_dialog(char *filename); #endif diff --git a/Geo/GModel.h b/Geo/GModel.h index 7af51784c1..1eabb8aefd 100644 --- a/Geo/GModel.h +++ b/Geo/GModel.h @@ -123,7 +123,7 @@ class GModel double scalingFactor=1.0); int writePOS(const std::string &name, double scalingFactor=1.0); int readSTL(const std::string &name, double tolerance=1.e-3); - int writeSTL(const std::string &name, double scalingFactor=1.0); + int writeSTL(const std::string &name, bool binary=false, double scalingFactor=1.0); int readVRML(const std::string &name); int writeVRML(const std::string &name, double scalingFactor=1.0); int writeUNV(const std::string &name, double scalingFactor=1.0); diff --git a/Geo/GModelIO.cpp b/Geo/GModelIO.cpp index 89e146b768..2854347247 100644 --- a/Geo/GModelIO.cpp +++ b/Geo/GModelIO.cpp @@ -1,4 +1,4 @@ -// $Id: GModelIO.cpp,v 1.25 2006-08-18 17:21:39 geuzaine Exp $ +// $Id: GModelIO.cpp,v 1.26 2006-08-19 04:24:03 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -728,23 +728,36 @@ int GModel::readSTL(const std::string &name, double tolerance) return 1; } -int GModel::writeSTL(const std::string &name, double scalingFactor) +int GModel::writeSTL(const std::string &name, bool binary, double scalingFactor) { - FILE *fp = fopen(name.c_str(), "w"); + FILE *fp = fopen(name.c_str(), binary ? "wb" : "w"); if(!fp){ Msg(GERROR, "Unable to open file '%s'", name.c_str()); return 0; } - fprintf(fp, "solid Created by Gmsh\n"); + if(!binary) + fprintf(fp, "solid Created by Gmsh\n"); + else{ + char header[80]; + strncpy(header, "Created by Gmsh", 80); + fwrite(header, sizeof(char), 80, fp); + unsigned int nfacets = 0; + for(fiter it = firstFace(); it != lastFace(); ++it) + nfacets += (*it)->triangles.size() + 2 * (*it)->quadrangles.size(); + fwrite(&nfacets, sizeof(unsigned int), 1, fp); + } + for(fiter it = firstFace(); it != lastFace(); ++it) { for(unsigned int i = 0; i < (*it)->triangles.size(); i++) - (*it)->triangles[i]->writeSTL(fp, scalingFactor); + (*it)->triangles[i]->writeSTL(fp, binary, scalingFactor); for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++) - (*it)->quadrangles[i]->writeSTL(fp, scalingFactor); + (*it)->quadrangles[i]->writeSTL(fp, binary, scalingFactor); } - fprintf(fp, "endsolid Created by Gmsh\n"); + if(!binary) + fprintf(fp, "endsolid Created by Gmsh\n"); + fclose(fp); return 1; } diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index a38fd89168..23e1130251 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -1,4 +1,4 @@ -// $Id: MElement.cpp,v 1.8 2006-08-15 06:26:52 geuzaine Exp $ +// $Id: MElement.cpp,v 1.9 2006-08-19 04:24:03 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -176,40 +176,53 @@ void MElement::writePOS(FILE *fp, double scalingFactor, int elementary) fprintf(fp, "};\n"); } -void MElement::writeSTL(FILE *fp, double scalingFactor) +void MElement::writeSTL(FILE *fp, bool binary, double scalingFactor) { - int n = getNumVertices(); - if(n < 3 || n > 4) return; - - MVertex *v0 = getVertex(0); - MVertex *v1 = getVertex(1); - MVertex *v2 = getVertex(2); - double N[3]; - normal3points(v0->x(), v0->y(), v0->z(), - v1->x(), v1->y(), v1->z(), - v2->x(), v2->y(), v2->z(), N); - fprintf(fp, "facet normal %g %g %g\n", N[0], N[1], N[2]); - fprintf(fp, " outer loop\n"); - fprintf(fp, " vertex %g %g %g\n", v0->x() * scalingFactor, - v0->y() * scalingFactor, v0->z() * scalingFactor); - fprintf(fp, " vertex %g %g %g\n", v1->x() * scalingFactor, - v1->y() * scalingFactor, v1->z() * scalingFactor); - fprintf(fp, " vertex %g %g %g\n", v2->x() * scalingFactor, - v2->y() * scalingFactor, v2->z() * scalingFactor); - fprintf(fp, " endloop\n"); - fprintf(fp, "endfacet\n"); - if(n == 4){ - MVertex *v3 = getVertex(3); - fprintf(fp, "facet normal %g %g %g\n", N[0], N[1], N[2]); + if(getNumEdges() != 3 && getNumEdges() != 4) return; + int qid[3] = {0, 2, 3}; + SVector3 n = getFace(0).normal(); + if(!binary){ + fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]); fprintf(fp, " outer loop\n"); - fprintf(fp, " vertex %g %g %g\n", v0->x() * scalingFactor, - v0->y() * scalingFactor, v0->z() * scalingFactor); - fprintf(fp, " vertex %g %g %g\n", v2->x() * scalingFactor, - v2->y() * scalingFactor, v2->z() * scalingFactor); - fprintf(fp, " vertex %g %g %g\n", v3->x() * scalingFactor, - v3->y() * scalingFactor, v3->z() * scalingFactor); + for(int j = 0; j < 3; j++) + fprintf(fp, " vertex %g %g %g\n", + getVertex(j)->x() * scalingFactor, + getVertex(j)->y() * scalingFactor, + getVertex(j)->z() * scalingFactor); fprintf(fp, " endloop\n"); fprintf(fp, "endfacet\n"); + if(getNumVertices() == 4){ + fprintf(fp, "facet normal %g %g %g\n", n[0], n[1], n[2]); + fprintf(fp, " outer loop\n"); + for(int j = 0; j < 3; j++) + fprintf(fp, " vertex %g %g %g\n", + getVertex(qid[j])->x() * scalingFactor, + getVertex(qid[j])->y() * scalingFactor, + getVertex(qid[j])->z() * scalingFactor); + fprintf(fp, " endloop\n"); + fprintf(fp, "endfacet\n"); + } + } + else{ + char data[50]; + float *coords = (float*)data; + coords[0] = n[0]; + coords[1] = n[1]; + coords[2] = n[2]; + for(int j = 0; j < 3; j++){ + coords[3 + 3 * j] = getVertex(j)->x() * scalingFactor; + coords[3 + 3 * j + 1] = getVertex(j)->y() * scalingFactor; + coords[3 + 3 * j + 2] = getVertex(j)->z() * scalingFactor; + } + fwrite(data, sizeof(char), 50, fp); + if(getNumVertices() == 4){ + for(int j = 0; j < 3; j++){ + coords[3 + 3 * j] = getVertex(qid[j])->x() * scalingFactor; + coords[3 + 3 * j + 1] = getVertex(qid[j])->y() * scalingFactor; + coords[3 + 3 * j + 2] = getVertex(qid[j])->z() * scalingFactor; + } + fwrite(data, sizeof(char), 50, fp); + } } } diff --git a/Geo/MElement.h b/Geo/MElement.h index c7d21f6278..004784d7ca 100644 --- a/Geo/MElement.h +++ b/Geo/MElement.h @@ -131,7 +131,7 @@ class MElement int elementary=1, int physical=1); virtual void writePOS(FILE *fp, double scalingFactor=1.0, int elementary=1); - virtual void writeSTL(FILE *fp, double scalingFactor=1.0); + virtual void writeSTL(FILE *fp, bool binary=false, double scalingFactor=1.0); virtual void writeVRML(FILE *fp); virtual void writeUNV(FILE *fp, int elementary); virtual void writeMESH(FILE *fp, int elementary); diff --git a/Parser/CreateFile.cpp b/Parser/CreateFile.cpp index d8462fc280..20e18f3b22 100644 --- a/Parser/CreateFile.cpp +++ b/Parser/CreateFile.cpp @@ -1,4 +1,4 @@ -// $Id: CreateFile.cpp,v 1.1 2006-08-12 19:34:16 geuzaine Exp $ +// $Id: CreateFile.cpp,v 1.2 2006-08-19 04:24:03 geuzaine Exp $ // // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle // @@ -150,7 +150,7 @@ void CreateOutputFile(char *filename, int format) break; case FORMAT_STL: - GMODEL->writeSTL(name, CTX.mesh.scaling_factor); + GMODEL->writeSTL(name, CTX.mesh.stl_binary, CTX.mesh.scaling_factor); break; case FORMAT_VRML: diff --git a/doc/texinfo/opt_general.texi b/doc/texinfo/opt_general.texi index 8ec47fe036..d9e39e8ce2 100644 --- a/doc/texinfo/opt_general.texi +++ b/doc/texinfo/opt_general.texi @@ -615,8 +615,8 @@ Default value: @code{450}@* Saved in: @code{General.SessionFileName} @item General.MouseSelection -Mouse selection mode (0=none, 1=no hover, 2=full)@* -Default value: @code{2}@* +Mouse hover and selection mode (0=none, 1=hover and select geometry but only select mesh, 2=hover and select geometry and mesh)@* +Default value: @code{1}@* Saved in: @code{General.OptionsFileName} @item General.NoPopup diff --git a/doc/texinfo/opt_mesh.texi b/doc/texinfo/opt_mesh.texi index c5345a6bd3..c67276ce96 100644 --- a/doc/texinfo/opt_mesh.texi +++ b/doc/texinfo/opt_mesh.texi @@ -359,6 +359,11 @@ Distance tolerance between two distinct vertices in STL meshes@* Default value: @code{5e-07}@* Saved in: @code{General.OptionsFileName} +@item Mesh.StlBinary +Save STL files in binary format?@* +Default value: @code{0}@* +Saved in: @code{General.OptionsFileName} + @item Mesh.SurfaceEdges Display edges of surface mesh?@* Default value: @code{1}@* -- GitLab