diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 02dfc8b8539eb4180c0deaf974c06919518ae330..8a382e238377c184c8c3ccc21037d76e5ecab75e 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -322,6 +322,8 @@ static int _save_view_med(const char *name){ return genericViewFileDialog (name, "MED Options", 6); } static int _save_view_txt(const char *name){ return genericViewFileDialog (name, "TXT Options", 4); } +static int _save_view_wrl(const char *name){ return genericViewFileDialog + (name, "X3D Options", 7); } static int _save_auto(const char *name) { @@ -405,6 +407,7 @@ static void file_save_as_cb(Fl_Widget *w, void *data) {"Mesh - PLY2 Surface" TT "*.ply2", _save_ply2}, {"Mesh - SU2" TT "*.su2", _save_su2}, {"Post-processing - Gmsh POS" TT "*.pos", _save_view_pos}, + {"Post-processing - X3D (X3D)" TT "*.x3d", _save_view_wrl}, #if defined(HAVE_MED) {"Post-processing - MED" TT "*.rmed", _save_view_med}, #endif diff --git a/Graphics/drawPost.cpp b/Graphics/drawPost.cpp index 9240dc65cb72c9eb332ca99d4e708be415824955..7c11ec29c50fd23c7f19b0088a9bb4edf1303c22 100644 --- a/Graphics/drawPost.cpp +++ b/Graphics/drawPost.cpp @@ -408,10 +408,11 @@ class drawPView { // use adaptive data if available PViewData *data = p->getData(true); PViewOptions *opt = p->getOptions(); - + p->setDrawContext(_ctx); + if(data->getDirty() || !data->getNumTimeSteps()) return; if(!opt->visible || opt->type != PViewOptions::Plot3D) return; - if(!_ctx->isVisible(p)) return; + if(!_ctx->isVisible(p)) return; if(_ctx->render_mode == drawContext::GMSH_SELECT){ glPushName(5); @@ -578,5 +579,5 @@ void drawContext::drawPost() for(unsigned int i = 0; i < PView::list.size(); i++) PView::list[i]->fillVertexArrays(); - std::for_each(PView::list.begin(), PView::list.end(), drawPView(this)); + std::for_each(PView::list.begin(), PView::list.end(), drawPView(this)); } diff --git a/Post/CMakeLists.txt b/Post/CMakeLists.txt index ca2a6d7a73bc0372aa1c1249c43d20f19c57831c..4e2fb73971d27907e95776bcde3d339e5fac3018 100644 --- a/Post/CMakeLists.txt +++ b/Post/CMakeLists.txt @@ -5,7 +5,7 @@ set(SRC PView.cpp PViewIO.cpp PViewVertexArrays.cpp - PViewData.cpp PViewDataIO.cpp + PViewData.cpp PViewDataIO.cpp PViewX3D.cpp PViewDataList.cpp PViewDataListIO.cpp PViewDataGModel.cpp PViewDataGModelIO.cpp PViewOptions.cpp diff --git a/Post/PView.cpp b/Post/PView.cpp index cf9958441af61379d17fcc9cabf82b6f9f19c5b0..62c7a425e2aea05508a9353293574870e1a3ec7d 100644 --- a/Post/PView.cpp +++ b/Post/PView.cpp @@ -354,3 +354,4 @@ double PView::getMemoryInMb() mem += getData()->getMemoryInMb(); return mem; } + diff --git a/Post/PView.h b/Post/PView.h index 46a173dbff45946598cf99df43faf2ae8ee13f6a..51804454b2a8ec44393fbcdb32498a172c0fcd22 100644 --- a/Post/PView.h +++ b/Post/PView.h @@ -10,6 +10,8 @@ #include <map> #include <string> #include "SPoint3.h" +#include "drawContext.h" + class PViewData; class PViewOptions; @@ -39,7 +41,7 @@ class PView{ PViewData *_data; // initialize private stuff void _init(int tag=-1); - + public: // create a new view with list-based data PView(int tag=-1); @@ -75,6 +77,8 @@ class PView{ // get/set the view data PViewData *getData(bool useAdaptiveIfAvailable=false); void setData(PViewData *val){ _data = val; } + // current drawContext + drawContext *_ctx; // get the view tag (unique and immutable) int getTag(){ return _tag; } @@ -93,6 +97,7 @@ class PView{ // get/set the eye position (for transparency calculations) SPoint3 &getEye(){ return _eye; } void setEye(SPoint3 &p){ _eye = p; } + void setDrawContext(drawContext *ctx){_ctx=ctx;} // get (approx.) memory used by the view, in Mb double getMemoryInMb(); @@ -121,7 +126,7 @@ class PView{ static bool readPOS(const std::string &fileName, int fileIndex=-1); static bool readMSH(const std::string &fileName, int fileIndex=-1); static bool readMED(const std::string &fileName, int fileIndex=-1); - + static bool writeX3D(const std::string &fileName ); // IO write routine bool write(const std::string &fileName, int format, bool append=false); @@ -137,6 +142,9 @@ class PView{ // smoothed normals smooth_normals *normals; + + + }; // this is the maximum number of nodes of elements we actually *draw* @@ -147,4 +155,8 @@ void changeCoordinates(PView *p, int ient, int iele, double **xyz, double **val); bool isElementVisible(PViewOptions *opt, int dim, int numNodes, double **xyz); + + #endif + + diff --git a/Post/PViewDataIO.cpp b/Post/PViewDataIO.cpp index b0ee584571967aaacb8f89a29174fc6e0376518b..95224640a3903546e015d15c70f6aeac39ddaf02 100644 --- a/Post/PViewDataIO.cpp +++ b/Post/PViewDataIO.cpp @@ -104,6 +104,8 @@ bool PViewData::writeTXT(const std::string &fileName) return true; } + + bool PViewData::writePOS(const std::string &fileName, bool binary, bool parsed, bool append) { @@ -193,6 +195,9 @@ bool PViewData::writeMED(const std::string &fileName) return false; } + + + bool PViewData::toVector(std::vector<std::vector<double> > &vec) { vec.resize(getNumTimeSteps()); diff --git a/Post/PViewIO.cpp b/Post/PViewIO.cpp index 96194fbf78b5d8c43ab43a548b8f14f1d0062192..f441b89398bab7398d5ff4791631b4dcedda7db6 100644 --- a/Post/PViewIO.cpp +++ b/Post/PViewIO.cpp @@ -6,8 +6,11 @@ #include "GmshConfig.h" #include "GmshMessage.h" #include "PView.h" +#include "PViewData.h" +#include "PViewOptions.h" #include "PViewDataList.h" #include "PViewDataGModel.h" +#include "VertexArray.h" #include "StringUtils.h" #include "Context.h" #include "OS.h" @@ -302,6 +305,7 @@ bool PView::write(const std::string &fileName, int format, bool append) 0, true, CTX::instance()->post.forceNodeData, CTX::instance()->post.forceElementData); break; case 6: ret = _data->writeMED(fileName); break; + case 7: ret = writeX3D(fileName); break; case 10: { std::string ext = SplitFileName(fileName)[2]; @@ -326,3 +330,6 @@ bool PView::write(const std::string &fileName, int format, bool append) if(ret) Msg::StatusBar(true, "Done writing '%s'", fileName.c_str()); return ret; } + + + diff --git a/Post/PViewX3D.cpp b/Post/PViewX3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..deaa0074b105f7b7f5e1bb54ca237c83d5383f00 --- /dev/null +++ b/Post/PViewX3D.cpp @@ -0,0 +1,597 @@ +// Gmsh - Copyright (C) 1997-2015 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to the public mailing list <gmsh@geuz.org>. +// +// PViewX3D is a extension for Post-processing outputs : +// creates a file in X3D format with the same features as +// what is visible in post-processing screen. +// contact : gilles.marckmann@ec-nantes.fr + +#include "GmshConfig.h" +#include "GmshMessage.h" +#include "PView.h" +#include "PViewData.h" +#include "PViewOptions.h" +#include "PViewDataList.h" +#include "PViewDataGModel.h" +#include "VertexArray.h" +#include "StringUtils.h" +#include "Context.h" +#include "OS.h" +#include <ctime> +#include "SBoundingBox3d.h" +#include <math.h> +#include "PViewX3D.h" + +bool PView::writeX3D(const std::string &fileName ) +{ + time_t rawtime; + struct tm * timeinfo; + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); + + FILE *fp = Fopen(fileName.c_str(), "w"); + if(!fp){ + Msg::Error("Unable to open file '%s'", fileName.c_str()); + return false; + } + + // x3 Header --------------------------------------------------------------------------- + fprintf(fp,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + fprintf(fp,"<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.3//EN\" \"http://www.web3d.org/specifications/x3d-3.3.dtd\">\n"); + fprintf(fp,"<X3D profile='Interchange' version='3.3' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' >\n"); + fprintf(fp,"<head>\n"); + fprintf(fp," <meta name='title' content='PView'/> \n"); + fprintf(fp," <meta name='description' content='%s'/>\n", fileName.c_str()); + fprintf(fp," <meta name='creator' content='gmsh'/> \n"); + fprintf(fp," <meta name='created' content='%s'/>\n", asctime(timeinfo) ); + fprintf(fp,"</head>\n"); + // Viewport --------------------------------------------------------------------------- + SBoundingBox3d bb(0.,0.,0.,0.,0.,0.); + for(std::vector<PView*>::iterator pvit=PView::list.begin() ; pvit < PView::list.end(); pvit++){ + PViewData *data = (*pvit)->getData(true); + PViewOptions *opt = (*pvit)->getOptions(); + if( !data->getDirty() && opt->visible ) { + bb+= data->getBoundingBox(opt->timeStep); + } + } + SPoint3 _center = bb.center(); + double _diagonal = bb.diag(); + fprintf(fp,"<Scene>\n"); + fprintf(fp,"<Viewpoint description='Book View' orientation='0 0. 1. 0.' position='%g %g %g'/> \n", + _center.x(), _center.y() , _center.z()+_diagonal*1.2 ); + fprintf(fp,"<Background skyColor='.7 .7 1'/> \n"); + //**************** + // HUD : Head Up Display + fprintf(fp,"<ProtoDeclare appinfo='Heads-up display (HUD)' name='HeadsUpDisplay'> \n"); + fprintf(fp," <ProtoInterface> \n"); + fprintf(fp," <field accessType='inputOutput' appinfo='offset position for HUD' name='screenOffset' type='SFVec3f' value='%g %g %g'/> \n", _center.x(), _center.y() , 5*_center.z()+_diagonal*1.2 ); + fprintf(fp," <field accessType='inputOutput' appinfo='X3D content positioned at HUD offset' name='children' type='MFNode'> \n"); + fprintf(fp," </field> \n"); + fprintf(fp," <field accessType='outputOnly' appinfo='HUD position update (in world coordinates) relative to original location' name='position_changed' type='SFVec3f'/> \n"); + fprintf(fp," <field accessType='outputOnly' appinfo='HUD orientation update relative to original location' name='orientation_changed' type='SFRotation'/> \n"); + fprintf(fp," </ProtoInterface> \n"); + fprintf(fp," <ProtoBody> \n"); + fprintf(fp," <Group bboxCenter=\"%g %g %g\"> \n", _center.x(), _center.y() , _center.z() ); + fprintf(fp," <Transform DEF='HudContainer'> \n"); + fprintf(fp," <Transform> \n"); + fprintf(fp," <IS> \n"); + fprintf(fp," <connect nodeField='translation' protoField='screenOffset'/> \n"); + fprintf(fp," </IS> \n"); + fprintf(fp," <Group> \n"); + fprintf(fp," <IS> \n"); + fprintf(fp," <connect nodeField='children' protoField='children'/> \n"); + fprintf(fp," </IS> \n"); + fprintf(fp," </Group> \n"); + fprintf(fp," </Transform> \n"); + fprintf(fp," </Transform> \n"); + fprintf(fp," <ProximitySensor DEF='HereIAm' size='10000000 10000000 10000000'> \n"); + fprintf(fp," <IS> \n"); + fprintf(fp," <connect nodeField='position_changed' protoField='position_changed'/> \n"); + fprintf(fp," <connect nodeField='orientation_changed' protoField='orientation_changed'/> \n"); + fprintf(fp," </IS> \n"); + fprintf(fp," </ProximitySensor> \n"); + fprintf(fp," <ROUTE fromField='orientation_changed' fromNode='HereIAm' toField='rotation' toNode='HudContainer'/> \n"); + fprintf(fp," <ROUTE fromField='position_changed' fromNode='HereIAm' toField='translation' toNode='HudContainer'/> \n"); + fprintf(fp," </Group> \n"); + fprintf(fp," </ProtoBody> \n"); + fprintf(fp," </ProtoDeclare> \n"); + fprintf(fp," <Background skyColor='.7 .7 1'/> \n"); + fprintf(fp," <Viewpoint description='Book View' orientation='0 0. 1. 0.' position='%g %g %g'/> \n", _center.x(), _center.y() , _center.z()+_diagonal*1.2 ); + fprintf(fp," <!-- ProtoDeclare is the \"cookie cutter\" template, ProtoInstance creates an actual occurrence --> \n"); + fprintf(fp," <ProtoInstance DEF='HeadsUpDisplay' name='HeadsUpDisplay'> \n"); + fprintf(fp," <!-- example: upper left-hand corner of screen (x=-2, y=1) and set back z=-5 from user view --> \n"); + fprintf(fp," <fieldValue name='screenOffset' value='%g %g %g'/> \n", _center.x(), _center.y() , _center.z()-.2*_diagonal ); + fprintf(fp," <fieldValue name='children'> \n"); + /*--------------------------------------------------------- + fprintf(fp," <Shape> \n"); + fprintf(fp," <Text string='\"HUD : place for legend\" \"stay fixed while user navigates\"'> \n"); + fprintf(fp," <FontStyle justify='\"MIDDLE\" \"MIDDLE\"' size='0.02'/> \n"); + fprintf(fp," </Text> \n"); + fprintf(fp," <Appearance> \n"); + fprintf(fp," <Material diffuseColor='0. 0. 0.'/> \n"); + fprintf(fp," </Appearance> \n"); + fprintf(fp," </Shape> \n"); + ------------------------------------------------------------*/ + + // here contour legends in frame (-.45,-.28, 0.) and (.45, .28,0.) : viewport .9 x .56 + + std::vector<PView*> scales; + for(unsigned int i = 0; i < PView::list.size(); i++){ + PViewData *data = PView::list[i]->getData(); + PViewOptions *opt = PView::list[i]->getOptions(); + if(!data->getDirty() + && opt->visible && opt->showScale + && opt->type == PViewOptions::Plot3D && data->getNumElements() + && PView::list[i]->_ctx->isVisible(PView::list[i]) + ) + scales.push_back(PView::list[i]); + } + if(!scales.empty()) { + char label[1024]; + double maxw = 0.; + for(unsigned int i = 0; i < scales.size(); i++) { + PViewOptions *opt = scales[i]->getOptions(); + sprintf(label, opt->format.c_str(), -M_PI * 1.e-4); + maxw = std::max(maxw, drawContext::global()->getStringWidth(label)); + } + + const double tic = 10., bar_size = 16.; double width = 0., width_prev = 0., width_total = 0.; + + for(unsigned int i = 0; i < scales.size(); i++) { + PView *p = scales[i]; + PViewData *data = p->getData(); + PViewOptions *opt = p->getOptions(); + double vph = p->_ctx->viewport[3] - p->_ctx->viewport[1]; + double vpw = p->_ctx->viewport[2] - p->_ctx->viewport[0]; + double xfactor = .9 /vpw; + double yfactor = .56/vph; + double ratio =2.*min(xfactor,yfactor); + + if(!opt->autoPosition) { + double w = opt->size[0], h = opt->size[1]; + double x = opt->position[0], y = opt->position[1] - h; + int c = p->_ctx->fix2dCoordinates(&x, &y); + if(c & 1) x -= w ; + if(c & 2) y += h / 2.; + + x -=vpw/2.; y -=vph/2.; + writeX3DScale(fp, p, x*xfactor, y*yfactor, w*xfactor, h*yfactor, tic*yfactor/2, CTX::instance()->post.horizontalScales,ratio); + } + else if(CTX::instance()->post.horizontalScales){ + double ysep = 20.; + double xc = ( p->_ctx->viewport[2] - p->_ctx->viewport[0]) / 2.; + if(scales.size() == 1){ + double w = ( p->_ctx->viewport[2] - p->_ctx->viewport[0]) / 2., h = bar_size; + double x = xc - w / 2., y = p->_ctx->viewport[1] + ysep; + + x -=vpw/2.; y -=vph/2.; + writeX3DScale(fp, p, x*xfactor, y*yfactor, w*xfactor, h*yfactor, tic*yfactor/2, 1,ratio); + } + else{ + double xsep = maxw / 4. + ( p->_ctx->viewport[2] - p->_ctx->viewport[0]) / 10.; + double w = ( p->_ctx->viewport[2] - p->_ctx->viewport[0] - 4 * xsep) / 2.; + if(w < 20.) w = 20.; + double h = bar_size; + double x = xc - (i % 2 ? -xsep / 1.5 : w + xsep / 1.5); + double y = p->_ctx->viewport[1] + ysep + + (i / 2) * (bar_size + tic +2 * drawContext::global()->getStringHeight() + ysep); + + x -=vpw/2.; y -=vph/2.; + writeX3DScale(fp, p, x*xfactor, y*yfactor, w*xfactor, h*yfactor, tic*yfactor/2, 1,ratio); + } + } + else{ + double xsep = 20.; + double dy = 2. * drawContext::global()->getStringHeight(); + if(scales.size() == 1){ + double ysep = ( p->_ctx->viewport[3] - p->_ctx->viewport[1]) / 6.; + double w = bar_size, h = p->_ctx->viewport[3] - p->_ctx->viewport[1] - 2 * ysep - dy; + double x = p->_ctx->viewport[0] + xsep, y = p->_ctx->viewport[1] + ysep + dy; + + x -=vpw/2.; y -=vph/2.; + writeX3DScale(fp, p, x*xfactor, y*yfactor, w*xfactor, h*yfactor, tic*yfactor/2, 1,ratio); + + } + else{ + double ysep = ( p->_ctx->viewport[3] - p->_ctx->viewport[1]) / 15.; + double w = bar_size; + double h = ( p->_ctx->viewport[3] - p->_ctx->viewport[1] - 3 * ysep - 2.5 * dy) / 2.; + double x = p->_ctx->viewport[0] + xsep + width_total + (i / 2) * xsep; + double y = p->_ctx->viewport[1] + ysep + dy + (1 - i % 2) * (h + 1.5 * dy + ysep); + + x -=vpw/2.; y -=vph/2.; + writeX3DScale(fp, p, x*xfactor, y*yfactor, w*xfactor, h*yfactor, tic*yfactor/2, 1,ratio); + + } + // compute width + width_prev = width; + sprintf(label, opt->format.c_str(), -M_PI * 1.e-4); + width = bar_size + tic + drawContext::global()->getStringWidth(label); + if(opt->showTime){ + char tmp[256]; + sprintf(tmp, opt->format.c_str(), data->getTime(opt->timeStep)); + sprintf(label, "%s (%s)", data->getName().c_str(), tmp); + } + else + sprintf(label, "%s", data->getName().c_str()); + width = std::max(width, drawContext::global()->getStringWidth(label)); + if(i % 2) width_total += std::max(bar_size + width, bar_size + width_prev); + } + } + } + + // end of contour legend + // frame to visualize HUD if necessary---------------------------------------- + /* + fprintf(fp," <Shape>\n"); + fprintf(fp," <IndexedFaceSet solid=\"false\" colorPerVertex=\"true\" coordIndex=\"0 1 2 3 -1\">\n"); + fprintf(fp," <Coordinate point= \" -.45 -.28 0. .45 -.28 0. .45 .28 0. -.45 .28 0. \" />\n"); + fprintf(fp," <Color color= \"0 0 0, 0 0 0, 1 1 1, 1 1 1\" /> \n"); + fprintf(fp," </IndexedFaceSet>\n"); + fprintf(fp," <Appearance> \n"); + fprintf(fp," <Material transparency='0.75' /> \n"); + fprintf(fp," </Appearance> \n"); + fprintf(fp," </Shape>"); + */ + //----------------------------------------------------------------------------- + fprintf(fp," </fieldValue> \n"); + fprintf(fp," </ProtoInstance> \n"); + + + // geometrical objects + for(std::vector<PView*>::iterator pvit=PView::list.begin() ; pvit < PView::list.end(); pvit++){ + PViewData *data = (*pvit)->getData(true); + PViewOptions *opt = (*pvit)->getOptions(); + if( !data->getDirty() && opt->visible ) { + VertexArray *va; + // points ------------------------NOT TREATED YET------------------------------- + va=(*pvit)->va_points; + for(int ipt = 0; ipt < va->getNumVertices(); ipt++){ + float *p = va->getVertexArray(3 * ipt); + // glColor4ubv((GLubyte *)va_points->getColorArray(4 * ipt)); + double f = 1.; + if(opt->pointType > 1){ + char *n = va->getNormalArray(3 * ipt); + f = char2float(*n); + } + if(opt->pointType == 2){ + int s = (int)(opt->pointSize * f); + if(s){ + fprintf(fp,"points : %g %g %g\n", p[0], p[1], p[2]); + } + } + else + fprintf(fp,"sphere : %g %g %g \n", p[0], p[1], p[2] ); + } + + + // lines ----------------------------------------------------------------------- + va=(*pvit)->va_lines; + fprintf(fp,"<Shape> \n"); + fprintf(fp," <IndexedLineSet coordIndex=' "); + for(int ipt = 0; ipt < va->getNumVertices(); ipt += 2){ + if(opt->lineType != 2 && opt->lineType != 1) { + fprintf(fp,"%i %i %i ",ipt,ipt+1,-1); + } + } + fprintf(fp,"'> \n"); + fprintf(fp," <Coordinate DEF='TurnPoints' point=' "); + for(int ipt = 0; ipt < va->getNumVertices(); ipt += 2){ + if(opt->lineType != 2 && opt->lineType != 1) { + float *p0 = va->getVertexArray(3 * ipt); + float *p1 = va->getVertexArray(3 * (ipt + 1)); + fprintf(fp,"%g %g %g %g %g %g ", p0[0], p0[1], p0[2], p1[0], p1[1], p1[2]); + } + } + fprintf(fp,"'/>\n"); + fprintf(fp," </IndexedLineSet> \n"); + fprintf(fp," <Appearance> \n"); + fprintf(fp," <Material emissiveColor='0 0 0'/>\n"); + fprintf(fp," <LineProperties containerField='lineProperties'> \n"); + fprintf(fp," </LineProperties> \n"); + fprintf(fp," </Appearance> \n"); + fprintf(fp,"</Shape>\n"); + + + //vectors --------------------colored arrow replaced by colored cones------------------- + va=(*pvit)->va_vectors; + + for(int i = 0; i < va->getNumVertices(); i += 2){ + float *s = va->getVertexArray(3 * i); + float *v = va->getVertexArray(3 * (i + 1)); + unsigned char *c = va->getColorArray(4 * i); + double rgba[4]; + UnsignedChar2rgba(c,rgba) ; + double l = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + double lmax = opt->tmpMax; + if((l || opt->vectorType == 6) && lmax){ + double scale=.5/_diagonal; + double theta=acos(v[1]/l); + fprintf(fp,"<Transform rotation='%g %g %g %g' translation='%e %e %e' >\n" + ,v[2],0.,-v[0],theta + ,s[0]+.5*scale*v[0],s[1]+.5*scale*v[1],s[2]+.5*scale*v[2]); + fprintf(fp,"<Shape>\n"); + fprintf(fp," <Cone bottomRadius='%g' height='%g'/>\n", + .05*l*scale, + l*scale); + fprintf(fp," <Appearance>\n"); + fprintf(fp," <Material diffuseColor='%g %g %g'/>\n",rgba[0], rgba[1], rgba[2]); + fprintf(fp," </Appearance>\n"); + fprintf(fp,"</Shape>\n"); + fprintf(fp,"</Transform>\n"); + } + } + + //triangles --------------------------colored triangles ------------------------------- + va=(*pvit)->va_triangles; + + fprintf(fp,"<Transform> \n"); + fprintf(fp,"<Shape> \n"); + fprintf(fp," <IndexedTriangleSet index=' "); + for(int ipt = 0; ipt < va->getNumVertices(); ipt += 3){ + fprintf(fp,"%i %i %i ",ipt,ipt+1,ipt+2); + } + fprintf(fp," ' solid='false' ccw='true' colorPerVertex='true' normalPerVertex='true' containerField='geometry'> \n"); + fprintf(fp," <Coordinate point='"); + for(int ipt = 0; ipt < va->getNumVertices(); ipt += 3){ + float *p0 = va->getVertexArray(3 * ipt); + float *p1 = va->getVertexArray(3 * (ipt + 1)); + float *p2 = va->getVertexArray(3 * (ipt + 2)); + fprintf(fp,"%e %e %e %e %e %e %e %e %e " + , p0[0], p0[1], p0[2] + , p1[0], p1[1], p1[2] + , p2[0], p2[1], p2[2]); + } + fprintf(fp," '/> \n"); + fprintf(fp," <Color color='"); + for(int ipt = 0; ipt < va->getNumVertices(); ipt += 3){ + unsigned char *c0 = va->getColorArray(4 * ipt); + unsigned char *c1 = va->getColorArray(4 * (ipt+1)); + unsigned char *c2 = va->getColorArray(4 * (ipt+2)); + double rgba0[4] , rgba1[4] ,rgba2[4]; + UnsignedChar2rgba(c0,rgba0) ; + UnsignedChar2rgba(c1,rgba1) ; + UnsignedChar2rgba(c2,rgba2) ; + fprintf(fp,"%g %g %g %g %g %g %g %g %g " + , rgba0[0],rgba0[1],rgba0[2] + , rgba1[0],rgba1[1],rgba1[2] + , rgba2[0],rgba2[1],rgba2[2]); + } + fprintf(fp," '/>\n"); + fprintf(fp," </IndexedTriangleSet> \n"); + fprintf(fp,"</Shape> \n"); + fprintf(fp,"</Transform> \n"); + + + } + }// end loop of pvit + + fprintf(fp,"</Scene>\n"); + fprintf(fp,"</X3D>\n"); + fclose(fp); + return true; + +} + + + +static void writeX3DScale(FILE *fp, PView *p, double xmin, double ymin, + double width, double height, double tic, int horizontal,double ratio) +{ + // use adaptive data if available + PViewData *data = p->getData(true); + PViewOptions *opt = p->getOptions(); + + if(opt->externalViewIndex >= 0){ + opt->tmpMin = opt->externalMin; + opt->tmpMax = opt->externalMax; + } + else if(opt->rangeType == PViewOptions::Custom){ + opt->tmpMin = opt->customMin; + opt->tmpMax = opt->customMax; + } + else if(opt->rangeType == PViewOptions::PerTimeStep){ + opt->tmpMin = data->getMin(opt->timeStep); + opt->tmpMax = data->getMax(opt->timeStep); + } + else{ + opt->tmpMin = data->getMin(); + opt->tmpMax = data->getMax(); + } + + writeX3DScaleBar(fp, p, xmin, ymin, width, height, tic, horizontal); + writeX3DScaleValues(fp, p, xmin, ymin, width, height, tic, horizontal,ratio); + writeX3DScaleLabel (fp, p, xmin, ymin, width, height, tic, horizontal,ratio); +} + + +static void writeX3DScaleBar(FILE *fp, PView *p, double xmin, double ymin, double width, + double height, double tic, int horizontal) +{ + PViewOptions *opt = p->getOptions(); + double box = (horizontal ? width : height) / (opt->nbIso ? opt->nbIso : 1); + + for(int i = 0; i < opt->nbIso; i++) { + if(opt->intervalsType == PViewOptions::Continuous + || opt->intervalsType == PViewOptions::Discrete + || opt->intervalsType == PViewOptions::Numeric){ + fprintf(fp," <Shape> \n"); + fprintf(fp," <IndexedFaceSet colorPerVertex='true' normalPerVertex='true' coordIndex='0 1 2 3 -1' solid='false' ccw='true' > \n"); + fprintf(fp," <Coordinate point='"); + if(horizontal){ + fprintf(fp,"%e %e %e %e %e %e %e %e %e %e %e %e " + ,xmin + i * box , ymin, 0. + ,xmin + (i + 1) * box, ymin, 0. + ,xmin + (i + 1) * box, ymin + height, 0. + ,xmin + i * box , ymin + height, 0.); + } + else{ + fprintf(fp,"%e %e %e %e %e %e %e %e %e %e %e %e " + ,xmin, ymin + i * box, 0. + ,xmin + width, ymin + i * box, 0. + ,xmin + width, ymin + (i + 1) * box, 0. + ,xmin, ymin + (i + 1) * box, 0.); + } + fprintf(fp," '/> \n"); + + if(opt->intervalsType == PViewOptions::Discrete + || opt->intervalsType == PViewOptions::Numeric){ + double rgba[4]= { .5,.5,.5,1. }; + unsigned int col = opt->getColor(i, opt->nbIso); + unsignedInt2RGBA(col,rgba[0],rgba[1],rgba[2],rgba[3]); + fprintf(fp," <Color color=' %g %g %g %g %g %g %g %g %g %g %g %g '/>\n" + , rgba[0],rgba[1],rgba[2], rgba[0],rgba[1],rgba[2], rgba[0],rgba[1],rgba[2], rgba[0],rgba[1],rgba[2] ); + } + else if(opt->intervalsType == PViewOptions::Continuous){ + double dv = (opt->tmpMax - opt->tmpMin) / (opt->nbIso ? opt->nbIso : 1); + double v1 = opt->tmpMin + i * dv; + double v2 = opt->tmpMin + (i + 1) * dv; + unsigned int col1 = opt->getColor(v1, opt->tmpMin, opt->tmpMax, true); + unsigned int col2 = opt->getColor(v2, opt->tmpMin, opt->tmpMax, true); + double rgba1[4]= { .5,.5,.5,1. }; + double rgba2[4]= { .5,.5,.5,1. }; + unsignedInt2RGBA(col1,rgba1[0],rgba1[1],rgba1[2],rgba1[3]); + unsignedInt2RGBA(col2,rgba2[0],rgba2[1],rgba2[2],rgba2[3]); + fprintf(fp," <Color color=' %g %g %g %g %g %g %g %g %g %g %g %g '/>\n" + , rgba1[0],rgba1[1],rgba1[2], rgba2[0],rgba2[1],rgba2[2], rgba2[0],rgba2[1],rgba2[2], rgba1[0],rgba1[1],rgba1[2] ); + } + fprintf(fp," </IndexedFaceSet> \n"); + } + else{ + fprintf(fp," <Shape> \n"); + fprintf(fp," <IndexedLineSet colorPerVertex='true' coordIndex='0 1 -1' > \n"); + fprintf(fp," <Coordinate point='"); + if(horizontal){ + fprintf(fp,"%e %e %e %e %e %e ",xmin+box/2.+i*box , ymin , 0.,xmin+box/2.+i*box , ymin+height , 0.); + } + else{ + fprintf(fp,"%e %e %e %e %e %e ",xmin , ymin + box / 2. + i * box, 0.,xmin + width , ymin + box / 2. + i * box , 0.); + } + fprintf(fp," '/> \n"); + double rgba[4]= { .5,.5,.5,1. }; + unsigned int col = opt->getColor(i, opt->nbIso); + unsignedInt2RGBA(col,rgba[0],rgba[1],rgba[2],rgba[3]); + fprintf(fp," <Color color=' %g %g %g %g %g %g '/>\n", rgba[0],rgba[1],rgba[2], rgba[0],rgba[1],rgba[2] ); + fprintf(fp," </IndexedLineSet> \n"); + } + fprintf(fp," </Shape> \n"); + } +} + + + + +static void writeX3DScaleValues(FILE *fp, PView *p, double xmin, double ymin, + double width, double height, double tic, int horizontal,double ratio) +{ + PViewOptions *opt = p->getOptions(); + if(!opt->nbIso) return; + double font_h = drawContext::global()->getStringHeight(); // total font height + double font_a = drawContext::global()->getStringHeight() - drawContext::global()->getStringDescent(); // height above ref pt + char label[1024]; + sprintf(label, opt->format.c_str(), -M_PI * 1.e-4); + double maxw = drawContext::global()->getStringWidth(label); + font_h *=ratio;font_a *=ratio; + maxw *=ratio; + int nbv = opt->nbIso; + double f = (opt->intervalsType == PViewOptions::Discrete || + opt->intervalsType == PViewOptions::Numeric || + opt->intervalsType == PViewOptions::Continuous) ? 2 : 2.5; + + if(horizontal && width < nbv * maxw){ + if(width < f * maxw) nbv = 1; + else nbv = 2; + } + else if(!horizontal && height < nbv * font_h ){ + if(height < f * font_h) nbv = 1; + else nbv = 2; + } + double box = (horizontal ? width : height) / opt->nbIso; + double vbox = (horizontal ? width : height) / nbv; + + glColor4ubv((GLubyte *) & CTX::instance()->color.text); + + if(opt->intervalsType == PViewOptions::Discrete || + opt->intervalsType == PViewOptions::Numeric || + opt->intervalsType == PViewOptions::Continuous){ + for(int i = 0; i < nbv + 1; i++) { + double v = opt->getScaleValue(i, nbv + 1, opt->tmpMin, opt->tmpMax); + sprintf(label, opt->format.c_str(), v); + if(horizontal){ + writeX3DStringCenter( fp,label, xmin + i * vbox, ymin + height + tic, 0.,font_h ); + } + else{ + writeX3DStringCenter( fp,label, xmin + width + tic,ymin + i * vbox - font_a*ratio / 3., 0.,font_h ); + } + } + } + else{ + if(opt->nbIso > 2 && (nbv == 1 || nbv == 2)){ + vbox = (vbox * nbv - box) / nbv; + nbv++; + } + for(int i = 0; i < nbv; i++) { + double v = opt->getScaleValue(i, nbv, opt->tmpMin, opt->tmpMax); + sprintf(label, opt->format.c_str(), v); + if(horizontal){ + writeX3DStringCenter( fp,label, xmin + box / 2. + i * vbox,ymin + height + tic, 0.,font_h ); + } + else{ + writeX3DStringCenter( fp,label, xmin + width + tic,ymin + box / 2. + i * vbox - font_a / 3., 0.,font_h ); + } + } + } +} + +static void writeX3DScaleLabel(FILE *fp , PView *p, double xmin, double ymin, + double width, double height, double tic, int horizontal,double ratio) +{ + PViewOptions *opt = p->getOptions(); + PViewData *data; + + // requested by Laurent: but is this really what we should be doing? + if(opt->externalViewIndex >= 0 && opt->externalViewIndex < (int)PView::list.size()) + data = PView::list[opt->externalViewIndex]->getData(); + else + data = p->getData(); + double font_h = drawContext::global()->getStringHeight(); + font_h *=ratio*1.2; + char label[1024]; + int nt = data->getNumTimeSteps(); + if((opt->showTime == 1 && nt > 1) || opt->showTime == 2){ + char tmp[256]; + sprintf(tmp, opt->format.c_str(), data->getTime(opt->timeStep)); + sprintf(label, "%s (%s)", data->getName().c_str(), tmp); + } + else if((opt->showTime == 3 && nt > 1) || opt->showTime == 4){ + sprintf(label, "%s (%d/%d)", data->getName().c_str(), opt->timeStep,data->getNumTimeSteps() - 1); + } + else + sprintf(label, "%s", data->getName().c_str()); + + if(horizontal){ + writeX3DStringCenter( fp,label, xmin + width / 2., ymin + height + tic + .9 * font_h, 0.,font_h ); + } + else{ + writeX3DStringCenter( fp,label, xmin, ymin - 2 * font_h, 0.,font_h ); + } +} + + + + +static void writeX3DStringCenter( FILE *fp,char *label,double x, double y, double z,double font_size){ + fprintf(fp," <Transform translation='%g %g %g'> \n",x,y,0.); + fprintf(fp," <Shape> \n"); + fprintf(fp," <Text string='\"%s\"'>\n",label); + fprintf(fp," <FontStyle justify='\"MIDDLE\" \"MIDDLE\"' size=' %g '/> \n",font_size); + fprintf(fp," </Text>\n"); + fprintf(fp," <Appearance>\n"); + fprintf(fp," <Material diffuseColor='0. 0. 0. '/>\n"); + fprintf(fp," </Appearance>\n"); + fprintf(fp," </Shape>\n"); + fprintf(fp," </Transform> \n"); + +} diff --git a/Post/PViewX3D.h b/Post/PViewX3D.h new file mode 100644 index 0000000000000000000000000000000000000000..ef7c5889519e79932809fce4ac9119cfe010ce39 --- /dev/null +++ b/Post/PViewX3D.h @@ -0,0 +1,47 @@ +// Gmsh - Copyright (C) 1997-2015 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to the public mailing list <gmsh@geuz.org>. +// +// PViewX3D is a extension for Post-processing outputs : +// creates a file in X3D format with the same features as +// what is visible in post-processing screen. +// contact : gilles.marckmann@ec-nantes.fr + +#ifndef _PVIEWX3D_H_ +#define _PVIEWX3D_H_ + +#include <iostream> + +using namespace std; + +static inline void UnsignedChar2rgba(unsigned char *glc,double*rgba){ + rgba[0]=glc[0]/255.; + rgba[1]=glc[1]/255.; + rgba[2]=glc[2]/255.; + rgba[3]=glc[3]/255.; +} + +static inline void unsignedInt2RGBA(unsigned int &color,double &r,double &g, double &b,double &a) +{ + r = color & 255; + g = (color >> 8) & 255; + b = (color >> 16) & 255; + a = (color >> 24) & 255; + r =r /255.; + g =g /255.; + b =b /255.; + a =a /255.; + // cout<< "couleur="<<color<<" / decomposition: "<<" r="<<r<<", g="<<g<<", b="<<b<<", a="<<a<<endl; + return; +} + +static void writeX3DScale(FILE *fp, PView *p, double xmin, double ymin, double width, double height, double tic, int horizontal,double ratio); +static void writeX3DScaleBar(FILE *fp, PView *p, double xmin, double ymin, double width, double height, double tic, int horizontal); +static void writeX3DScaleValues(FILE *fp, PView *p, double xmin, double ymin, double width, double height, double tic, int horizontal,double ratio); +static void writeX3DScaleLabel (FILE *fp, PView *p, double xmin, double ymin, double width, double height, double tic, int horizontal,double ratio); +static void writeX3DStringCenter( FILE *fp,char *label,double x, double y, double z,double font_size); + + +#endif +