From 22f451a6de370451d972200e6f701d67e25eda16 Mon Sep 17 00:00:00 2001
From: Gilles Marckmann <gilles.marckmann@ec-nantes.fr>
Date: Mon, 5 Oct 2015 16:28:27 +0000
Subject: [PATCH] improve export in x3d with deleting of inner border in case
 of partitionned mesh

---
 Common/CreateFile.cpp  |   2 +
 Common/GmshDefines.h   |   1 +
 Fltk/extraDialogs.cpp  |   1 +
 Fltk/fileDialogs.cpp   |  88 ++++++++++++++-
 Fltk/fileDialogs.h     |   1 +
 Fltk/graphicWindow.cpp |   9 +-
 Post/PView.cpp         |   5 +-
 Post/PView.h           |  16 ++-
 Post/PViewX3D.cpp      | 235 ++++++++++++++++++++++++++++++++++-------
 Post/PViewX3D.h        |  18 ++++
 10 files changed, 332 insertions(+), 44 deletions(-)

diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index 9eab419c66..8dffc51634 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -33,6 +33,7 @@ int GetFileFormatFromExtension(const std::string &ext)
 {
   if     (ext == ".geo")  return FORMAT_GEO;
   else if(ext == ".msh")  return FORMAT_MSH;
+  else if(ext == ".x3d")  return FORMAT_X3D;
   else if(ext == ".pos")  return FORMAT_POS;
   else if(ext == ".pvtu") return FORMAT_PVTU;
   else if(ext == ".opt")  return FORMAT_OPT;
@@ -92,6 +93,7 @@ std::string GetDefaultFileName(int format)
   case FORMAT_GEO:  name += ".geo_unrolled"; break;
   case FORMAT_MSH:  name += ".msh"; break;
   case FORMAT_POS:  name += ".pos"; break;
+  case FORMAT_X3D:  name += ".x3d"; break;
   case FORMAT_PVTU:  name += ".pvtu"; break;
   case FORMAT_OPT:  name += ".opt"; break;
   case FORMAT_UNV:  name += ".unv"; break;
diff --git a/Common/GmshDefines.h b/Common/GmshDefines.h
index 31c0e3780c..a36ee96905 100644
--- a/Common/GmshDefines.h
+++ b/Common/GmshDefines.h
@@ -52,6 +52,7 @@
 #define FORMAT_MPEG_PREVIEW 43
 #define FORMAT_PGF   44
 #define FORMAT_PVTU  45
+#define FORMAT_X3D  46
 
 // Element types
 #define TYPE_PNT     1
diff --git a/Fltk/extraDialogs.cpp b/Fltk/extraDialogs.cpp
index d10b3afef8..72df705bda 100644
--- a/Fltk/extraDialogs.cpp
+++ b/Fltk/extraDialogs.cpp
@@ -32,6 +32,7 @@
 #include "drawContext.h"
 #include "GModel.h"
 #include "Context.h"
+#include "PView.h"
 
 // Arrow editor
 
diff --git a/Fltk/fileDialogs.cpp b/Fltk/fileDialogs.cpp
index e0d4bad096..8f4371052a 100644
--- a/Fltk/fileDialogs.cpp
+++ b/Fltk/fileDialogs.cpp
@@ -34,7 +34,7 @@
 #include "GModel.h"
 #include "PView.h"
 #include "PViewOptions.h"
-
+#include <iostream>
 // File chooser
 
 #if defined(HAVE_NATIVE_FILE_CHOOSER)
@@ -1576,6 +1576,92 @@ int pvtuAdaptFileDialog(const char *name)
   return 0;
 }
 
+
+int x3dViewFileDialog(const char *name, const char *title, int format)
+{
+  struct _viewFileDialog{
+    Fl_Window *window;
+    Fl_Choice *c[1];
+    Fl_Choice *d[1];
+    Fl_Value_Input *input[2];
+    Fl_Button *ok, *cancel;
+  };
+  static _viewFileDialog *dialog = NULL;
+
+  static Fl_Menu_Item viewmenu[] = {
+    {"Current", 0, 0, 0},
+    {"Visible", 0, 0, 0},
+    {"All", 0, 0, 0},
+    {0}
+  };
+  static Fl_Menu_Item viewmenu2[] = {
+    {"Keep", 0, 0, 0},
+    {"Remove", 0, 0, 0},
+    {0}
+  };
+
+  int BBB = BB + 9; // labels too long
+
+  if(!dialog){
+    dialog = new _viewFileDialog;
+    int h = 6 * WB + 5 * BH, w = 2 * BBB +  BBB  / 3  +  12 * WB , y = WB;
+    dialog->window = new Fl_Double_Window(w, h);
+    dialog->window->box(GMSH_WINDOW_BOX);
+    dialog->window->set_modal();
+    dialog->c[0] = new Fl_Choice(WB, y, BBB + BBB / 2, BH, "View(s)"); y += BH+WB;
+    dialog->c[0]->menu(viewmenu);
+    dialog->c[0]->align(FL_ALIGN_RIGHT);
+    dialog->d[0] = new Fl_Choice(WB, y, BBB + BBB / 2, BH, "Inner Borders"); y += BH+WB;
+    dialog->d[0]->menu(viewmenu2);
+    dialog->d[0]->align(FL_ALIGN_RIGHT);
+    dialog->input[0] = new Fl_Value_Input( WB, y, BBB + BBB / 2, BH, "Log10( Precision )");y += BH+WB;  
+    dialog->input[0]->minimum(-16);
+    dialog->input[0]->maximum(16);
+    dialog->input[0]->step(.25);
+    dialog->input[1] = new Fl_Value_Input( WB, y, BBB + BBB / 2, BH, "Transparency");y += BH+WB;  
+    dialog->input[1]->minimum(0.);
+    dialog->input[1]->maximum(1.);
+    dialog->input[1]->step(0.05);
+    dialog->ok     = new Fl_Return_Button( WB          , y , BBB, BH, "OK");
+    dialog->cancel = new Fl_Button       ( 2 * WB + BBB, y , BBB, BH, "Cancel");
+    dialog->window->end();
+    dialog->window->hotspot(dialog->window);
+  }
+
+  dialog->window->label(title);
+  dialog->window->show();
+  dialog->input[0]->value(	PView::getPrecisionValue() );
+  dialog->input[0]->align(FL_ALIGN_RIGHT);
+  dialog->input[1]->value(	PView::getTransparencyValue() );
+  dialog->input[1]->align(FL_ALIGN_RIGHT);
+
+  while(dialog->window->shown()){
+    Fl::wait();
+    for (;;) {
+      Fl_Widget* o = Fl::readqueue();
+      if (!o) break;
+      if (o == dialog->ok) {
+	dialog->d[0]->value()==1 ? PView::setInnerBorder(true) :   PView::setInnerBorder(false) ;
+	PView::setTransparencyValue( dialog->input[1]->value() );
+	PView::setPrecisionValue( dialog->input[0]->value() );
+
+        _saveViews(name, dialog->c[0]->value(),format, false);
+        dialog->window->hide();
+        return 1;
+      }
+      if (o == dialog->window || o == dialog->cancel){
+        dialog->window->hide();
+        return 0;
+      }
+    }
+  }
+  return 0;
+ 
+}
+
+
+
+
 int genericViewFileDialog(const char *name, const char *title, int format)
 {
   struct _viewFileDialog{
diff --git a/Fltk/fileDialogs.h b/Fltk/fileDialogs.h
index 393c71053e..f752fae753 100644
--- a/Fltk/fileDialogs.h
+++ b/Fltk/fileDialogs.h
@@ -29,6 +29,7 @@ int pgfBitmapFileDialog(const char *filename, const char *title, int format);
 int genericMeshFileDialog(const char *filename, const char *title, int format,
                           bool binary_support, bool element_tag_support);
 int posFileDialog(const char *name);
+int x3dViewFileDialog(const char *name, const char *title, int format);
 int pvtuAdaptFileDialog(const char *name);
 int genericViewFileDialog(const char *name, const char *title, int format);
 int gl2psFileDialog(const char *filename, const char *title, int format);
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index b7e1e8b733..c2f0c8ac6f 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -323,14 +323,17 @@ 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_view_wrl(const char *name){ return genericViewFileDialog    (name, "X3D Options", 7); } 
+static int _save_view_x3d(const char *name){ return x3dViewFileDialog    (name, "X3D Options", 7); } 
+
 
 static int _save_auto(const char *name)
 {
   switch(GuessFileFormatFromFileName(name)){
   case FORMAT_MSH  : return _save_msh(name);
   case FORMAT_POS  : return _save_view_pos(name);
+  case FORMAT_X3D  : return _save_view_x3d(name);
   case FORMAT_PVTU : return _save_view_adapt_pvtu(name);
   case FORMAT_TXT  : return _save_view_txt(name);
   case FORMAT_OPT  : return _save_options(name);
@@ -409,7 +412,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},
+    {"Post-processing - X3D (X3D)" TT "*.x3d", _save_view_x3d},
 #if defined(HAVE_MED)
     {"Post-processing - MED" TT "*.rmed", _save_view_med},
 #endif
diff --git a/Post/PView.cpp b/Post/PView.cpp
index 62c7a425e2..ba356f6884 100644
--- a/Post/PView.cpp
+++ b/Post/PView.cpp
@@ -15,10 +15,13 @@
 #include "GmshMessage.h"
 
 int PView::_globalTag = 0;
+bool PView::_removeInnerBorders = false;
+double PView::_transparency=0.;
+double PView::_precision=pow(10.,-9.);
 std::vector<PView*> PView::list;
-
 void PView::_init(int tag)
 {
+ _removeInnerBorders = false;
   if(tag >= 0){
     _tag = tag;
     _globalTag = std::max(_globalTag, _tag) + 1;
diff --git a/Post/PView.h b/Post/PView.h
index 9356c244f0..78f7f8f0b8 100644
--- a/Post/PView.h
+++ b/Post/PView.h
@@ -25,11 +25,15 @@ namespace onelab{ class localNetworkClient; }
 class PView{
  private:
   static int _globalTag;
+  //  transparency in x3d output
+  static double _transparency;
+  // merge partitionned model in delete duplicate as common border (for x3d export)
+  static bool _removeInnerBorders ;
   // unique tag of the view (>= 0)
   int _tag;
   // index of the view in the current view list
   int _index;
-  // flag to mark that the view has changed
+  // flag to mark that the view has changed1
   bool _changed;
   // tag of the source view if this view is an alias, -1 otherwise
   int _aliasOf;
@@ -63,8 +67,16 @@ class PView{
   // default destructor
   ~PView();
 
+  //  precision for inner border deletion in x3d output
+  static double _precision;
   // get/set global tag
-  static int getGlobalTag(){ return _globalTag; }
+  static double getTransparencyValue()          { return _transparency ;  }
+  static void   setTransparencyValue( double tr){        _transparency = tr; }
+  static double getPrecisionValue()              { return  log10( _precision ) ;  }
+      static void   setPrecisionValue( double pr){                _precision=pow( 10., pr) ; }
+  static bool getInnerBorder()        { return _removeInnerBorders; }
+  static void setInnerBorder(bool tag){        _removeInnerBorders = tag; }
+  static int  getGlobalTag(){ return _globalTag; }
   static void setGlobalTag(int tag){ _globalTag = tag; }
 
   // delete the vertex arrays, used to draw the view efficiently
diff --git a/Post/PViewX3D.cpp b/Post/PViewX3D.cpp
index 893937ab18..4e69ca8f44 100644
--- a/Post/PViewX3D.cpp
+++ b/Post/PViewX3D.cpp
@@ -27,13 +27,148 @@
 
 using namespace std;
 
+
+bool compare_xmin_triangle (const TriangleToSort* first, const TriangleToSort* second) {  return (first->xmin < second->xmin );  }
+bool compare_ymin_triangle (const TriangleToSort* first, const TriangleToSort* second) {  return (first->ymin < second->ymin );  }
+bool compare_zmin_triangle (const TriangleToSort* first, const TriangleToSort* second) {  return (first->zmin < second->zmin );  }
+bool compare_xmax_triangle (const TriangleToSort* first, const TriangleToSort* second) {  return (first->xmax < second->xmax );  }
+bool compare_ymax_triangle (const TriangleToSort* first, const TriangleToSort* second) {  return (first->ymax < second->ymax );  }
+bool compare_zmax_triangle (const TriangleToSort* first, const TriangleToSort* second) {  return (first->zmax < second->zmax );  }
+
+
 bool PView::writeX3D(const std::string &fileName )
 {
+  
+  // tags duplicated triangles ---------------------
+  int _size=0;
+  if (  PView::getInnerBorder() ) {   
+    for(unsigned int i = 0; i < PView::list.size(); i++){
+      VertexArray *va =PView::list[i]->va_triangles;
+      _size += va->getNumVertices()/3;
+    }
+  }
+  int _count=0;
+  bool visible[_size] ;
+  if (  PView::getInnerBorder() ) {   
+    // evaluate bbox of each triangle
+    std::list< TriangleToSort* > tlist ;
+    tlist.clear();
+    for(unsigned int ivp = 0; ivp < PView::list.size(); ivp++){
+      VertexArray *va =PView::list[ivp]->va_triangles;
+      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));
+	TriangleToSort *_current = new TriangleToSort ;
+	_current->_index = ipt;
+	_current->_globalIndex=_count; visible[_count]=true; _count++; 
+	_current->_ppv   = PView::list[ivp] ;
+	_current->xmin    = min(p0[0], min(p1[0],p2[0]) );
+	_current->ymin    = min(p0[1], min(p1[1],p2[1]) );
+	_current->zmin    = min(p0[2], min(p1[2],p2[2]) );
+	_current->xmax    = max(p0[0], max(p1[0],p2[0]) );
+	_current->ymax    = max(p0[1], max(p1[1],p2[1]) );
+	_current->zmax    = max(p0[2], max(p1[2],p2[2]) );
+
+	tlist.push_back(_current);
+      }
+    }
+    // sort triangles upon the position of bbbox
+    tlist.sort(compare_zmax_triangle);
+    tlist.sort(compare_ymax_triangle);
+    tlist.sort(compare_xmax_triangle);
+    tlist.sort(compare_zmin_triangle);
+    tlist.sort(compare_ymin_triangle);
+    tlist.sort(compare_xmin_triangle);
+
+    // estimate and tags triangles which are identical
+    std::list< TriangleToSort* >::iterator pt,nt;
+     for ( pt=tlist.begin() ; pt != tlist.end() ; pt++ ) {
+      nt=pt; 	nt++;
+      bool found=false;
+      VertexArray *vap = ( (*pt)->_ppv)->va_triangles;
+      int    ip = (*pt)->_index;
+      float *p0 = vap->getVertexArray( 3*  ip    );
+      float *p1 = vap->getVertexArray( 3* (ip+1) );
+      float *p2 = vap->getVertexArray( 3* (ip+2) );
+      int gip=(*pt)->_globalIndex;
+      while (  nt != tlist.end() && !found ) {
+	int gin=(*nt)->_globalIndex;
+	if    ( ( ( ( abs( (*pt)->xmin - (*nt)->xmin ) < 1.e-9 ) && ( abs( (*pt)->ymin - (*nt)->ymin ) < 1.e-9) ) && ( abs( (*pt)->zmin - (*nt)->zmin ) < 1.e-9 ) )  
+		&& ( ( ( abs( (*pt)->xmax - (*nt)->xmax ) < 1.e-9 ) && ( abs( (*pt)->ymax - (*nt)->ymax ) < 1.e-9) ) && ( abs( (*pt)->zmax - (*nt)->zmax ) < 1.e-9 ) ) )  {
+	  VertexArray *van = ( (*nt)->_ppv)->va_triangles;
+	  int in=(*nt)->_index;	
+	  float *n0 = van->getVertexArray( 3*  in    );
+	  float *n1 = van->getVertexArray( 3* (in+1) );
+	  float *n2 = van->getVertexArray( 3* (in+2) );
+	  //	  bool cas00 = (p0[0]==n0[0] &&  p0[1]==n0[1] &&  p0[2]==n0[2]);
+	  //	  bool cas01 = (p0[0]==n1[0] &&  p0[1]==n1[1] &&  p0[2]==n1[2]);
+	  //	  bool cas02 = (p0[0]==n2[0] &&  p0[1]==n2[1] &&  p0[2]==n2[2]);
+	  //	  bool cas10 = (p1[0]==n0[0] &&  p1[1]==n0[1] &&  p1[2]==n0[2]);
+	  //	  bool cas11 = (p1[0]==n1[0] &&  p1[1]==n1[1] &&  p1[2]==n1[2]);
+	  //	  bool cas12 = (p1[0]==n2[0] &&  p1[1]==n2[1] &&  p1[2]==n2[2]);
+	  //	  bool cas20 = (p2[0]==n0[0] &&  p2[1]==n0[1] &&  p2[2]==n0[2]);
+	  //	  bool cas21 = (p2[0]==n1[0] &&  p2[1]==n1[1] &&  p2[2]==n1[2]);
+	  //	  bool cas22 = (p2[0]==n2[0] &&  p2[1]==n2[1] &&  p2[2]==n2[2]);
+	  /*
+	  if ( p0[0]==n0[0] &&  p0[1]==n0[1] &&  p0[2]==n0[2] ){ 
+	    if ( p1[0]==n1[0] &&  p1[1]==n1[1] &&  p1[2]==n1[2] ){
+	      if ( p2[0]==n2[0] &&  p2[1]==n2[1] &&  p2[2]==n2[2] ) { found=true;  } }
+	    else if ( p1[0]==n2[0] &&  p1[1]==n2[1] &&  p1[2]==n2[2] ) {
+	      if ( p2[0]==n1[0] &&  p2[1]==n1[1] &&  p2[2]==n1[2] ) { found=true;  } } }
+	  else if ( p0[0]==n1[0] &&  p0[1]==n1[1] &&  p0[2]==n1[2] ) {
+	    if ( p1[0]==n0[0] &&  p1[1]==n0[1] &&  p1[2]==n0[2] ){
+	      if ( p2[0]==n2[0] &&  p2[1]==n2[1] &&  p2[2]==n2[2] ) { found=true; } }
+	    else if ( p1[0]==n2[0] &&  p1[1]==n2[1] &&  p1[2]==n2[2] ) {
+	      if ( p2[0]==n0[0] &&  p2[1]==n0[1] &&  p2[2]==n0[2] ) { found=true; } } }
+	  else if ( p0[0]==n2[0] &&  p0[1]==n2[1] &&  p0[2]==n2[2] ) { 
+	    if ( p1[0]==n0[0] &&  p1[1]==n0[1] &&  p1[2]==n0[2] ){
+	      if ( p2[0]==n1[0] &&  p2[1]==n1[1] &&  p2[2]==n1[2] ) { found=true;  } }
+	    else if ( p1[0]==n1[0] &&  p1[1]==n1[1] &&  p1[2]==n1[2] ) { 
+	      if ( p2[0]==n0[0] &&  p2[1]==n0[1] &&  p2[2]==n0[2] ) { found=true; } } }
+    */
+	  if ( almostEqual(p0[0],n0[0]) &&  almostEqual(p0[1],n0[1]) &&  almostEqual(p0[2],n0[2]) ){ 
+	    if ( almostEqual(p1[0],n1[0]) &&  almostEqual(p1[1],n1[1]) &&  almostEqual(p1[2],n1[2]) ){
+	      if ( almostEqual(p2[0],n2[0]) &&  almostEqual(p2[1],n2[1]) &&  almostEqual(p2[2],n2[2]) ) { found=true;  } }
+	    else if ( almostEqual(p1[0],n2[0]) &&  almostEqual(p1[1],n2[1]) &&  almostEqual(p1[2],n2[2]) ) {
+	      if ( almostEqual(p2[0],n1[0]) &&  almostEqual(p2[1],n1[1]) &&  almostEqual(p2[2],n1[2]) ) { found=true;  } } }
+	  else if ( almostEqual(p0[0],n1[0]) &&  almostEqual(p0[1],n1[1]) &&  almostEqual(p0[2],n1[2]) ) {
+	    if ( almostEqual(p1[0],n0[0]) &&  almostEqual(p1[1],n0[1]) &&  almostEqual(p1[2],n0[2]) ){
+	      if ( almostEqual(p2[0],n2[0]) &&  almostEqual(p2[1],n2[1]) &&  almostEqual(p2[2],n2[2]) ) { found=true; } }
+	    else if ( almostEqual(p1[0],n2[0]) &&  almostEqual(p1[1],n2[1]) &&  almostEqual(p1[2],n2[2]) ) {
+	      if ( almostEqual(p2[0],n0[0]) &&  almostEqual(p2[1],n0[1]) &&  almostEqual(p2[2],n0[2]) ) { found=true; } } }
+	  else if ( almostEqual(p0[0],n2[0]) &&  almostEqual(p0[1],n2[1]) &&  almostEqual(p0[2],n2[2]) ) { 
+	    if ( almostEqual(p1[0],n0[0]) &&  almostEqual(p1[1],n0[1]) &&  almostEqual(p1[2],n0[2]) ){
+	      if ( almostEqual(p2[0],n1[0]) &&  almostEqual(p2[1],n1[1]) &&  almostEqual(p2[2],n1[2]) ) { found=true;  } }
+	    else if ( almostEqual(p1[0],n1[0]) &&  almostEqual(p1[1],n1[1]) &&  almostEqual(p1[2],n1[2]) ) { 
+	      if ( almostEqual(p2[0],n0[0]) &&  almostEqual(p2[1],n0[1]) &&  almostEqual(p2[2],n0[2]) ) { found=true; } } }
+
+
+	  if (found){
+	    visible[gip]=false;
+	    visible[gin]=false;
+	    if ( pt != tlist.end() ) pt++;
+	  }
+	  else{
+	    nt++;
+	  }
+	} // if ( ( ( abs( (*pt)->xmin-(*nt)->xmin ) ...
+	else {
+	  nt = tlist.end();
+   	} // if ( ( ( abs( (*pt)->xmin-(*nt)->xmin ) ...
+      } //	while (  nt != tlist.end() && !found ) ...
+    } //     for ( pt=tlist.begin() ; pt != tlist.end() ; pt++ ) ...
+    for ( pt=tlist.begin() ;  pt  != tlist.end() ; pt++) {
+      //      delete (*pt);
+    }
+  }
+  // end tags duplicated triangles  ---------------------
+
+  // beginning writing x3d file     ---------------------
   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());
@@ -221,15 +356,16 @@ bool PView::writeX3D(const std::string &fileName )
   fprintf(fp,"      </fieldValue> \n");
   fprintf(fp,"    </ProtoInstance> \n");
  
-
+  //count all visible triangles of previous visited PView
+  _count=0;
   // 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();
+  for(unsigned int ipv = 0; ipv < PView::list.size(); ipv++){
+    PViewData *data = PView::list[ipv]->getData(true);
+    PViewOptions *opt = PView::list[ipv]->getOptions();
     if( !data->getDirty() && opt->visible ) {
       VertexArray *va;
       // points ------------------------NOT TREATED YET-------------------------------
-      va=(*pvit)->va_points;
+      va=PView::list[ipv]->va_points;
       for(int ipt = 0; ipt < va->getNumVertices(); ipt++){
 	float *p = va->getVertexArray(3 * ipt);
 	double f = 1.;
@@ -249,7 +385,7 @@ bool PView::writeX3D(const std::string &fileName )
 
 
       // lines -----------------------------------------------------------------------
-      va=(*pvit)->va_lines;
+      va=PView::list[ipv]->va_lines;
       fprintf(fp,"<Shape> \n");
       fprintf(fp,"   <IndexedLineSet coordIndex=' ");
       for(int ipt = 0; ipt < va->getNumVertices(); ipt += 2){
@@ -277,12 +413,12 @@ bool PView::writeX3D(const std::string &fileName )
 
 
       //vectors --------------------colored arrow replaced by colored cones-------------------
-      va=(*pvit)->va_vectors;
+      va=PView::list[ipv]->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);
+      for(int iv = 0; iv < va->getNumVertices(); iv += 2){
+	float *s = va->getVertexArray(3 * iv);
+	float *v = va->getVertexArray(3 * (iv + 1));
+	unsigned char *c = va->getColorArray(4 * iv);
 	double rgba[4];
 	UnsignedChar2rgba(c,rgba) ;    
 	double l = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
@@ -306,48 +442,72 @@ bool PView::writeX3D(const std::string &fileName )
       }
   
        //triangles --------------------------colored triangles -------------------------------
-      va=(*pvit)->va_triangles;
+      va=PView::list[ipv]->va_triangles;
 
       fprintf(fp,"<Transform> \n");
       fprintf(fp,"<Shape> \n");
       fprintf(fp,"   <IndexedTriangleSet index=' ");
+      // index of point of the visible tirangle
+      int ind=0;
       for(int ipt = 0; ipt < va->getNumVertices(); ipt += 3){  
-	fprintf(fp,"%i %i %i ",ipt,ipt+1,ipt+2);  
+	if ( (PView::getInnerBorder() &&  visible[_count+ipt/3] ) ||  !PView::getInnerBorder() ) {   
+	  fprintf(fp,"%i %i %i ",ind,ind+1,ind+2);  
+	  ind+=3;
+	}
       }
       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]);
+	if ( ( PView::getInnerBorder() &&  visible[_count+ipt/3] ) ||  !PView::getInnerBorder()) {   
+	    float *p0 = va->getVertexArray(3 * ipt);
+	    float *p1 = va->getVertexArray(3 * (ipt + 1));
+	    float *p2 = va->getVertexArray(3 * (ipt + 2));
+	    /*
+	    std::cout<<" PV" << ipv<<" ipt "<<ipt<<" coord "<<p0[0]<<","
+	    <<p0[1]<<","<<p0[2]<<"|"<<p1[0]<<","<<p1[1]<<","<<p1[2]
+	    <<"|"<<p2[0]<<","<<p2[1]<<","<<p2[2]<<std::endl;
+	    */
+	    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,"      <Color color='");
+       for(int ipt = 0; ipt < va->getNumVertices(); ipt += 3){
+	if ( ( PView::getInnerBorder() &&  visible[_count+ipt/3] ) ||  !PView::getInnerBorder() ) {   
+	    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,"            <Appearance> \n");
+      fprintf(fp,"              <Material  transparency='%g' /> \n",  PView::getTransparencyValue() );
+      fprintf(fp,"                         ambientIntensity=\"0.5\"");
+      fprintf(fp,"                         diffuseColor=\".5 .5 .5\"");
+      fprintf(fp,"                         emissiveColor=\"0.0 0.0 0.0\"");
+      fprintf(fp,"                         shininess=\"0.25\"");
+      fprintf(fp,"                         specularColor=\".1 .1 .1\"  /> ");
+      fprintf(fp,"            </Appearance> \n");
       fprintf(fp,"</Shape> \n");
       fprintf(fp,"</Transform> \n");
 
-
-    }
-  }// end loop of pvit
+      _count += va->getNumVertices()/3;
+    } // enf if dirty
+  }// end loop on PView::list
 
   fprintf(fp,"</Scene>\n");
   fprintf(fp,"</X3D>\n");
@@ -577,3 +737,4 @@ static void writeX3DStringCenter( FILE *fp,char *label,double x, double y, doubl
   fprintf(fp,"              </Transform> \n");
 
 }
+
diff --git a/Post/PViewX3D.h b/Post/PViewX3D.h
index 986d8960b4..532c973ae4 100644
--- a/Post/PViewX3D.h
+++ b/Post/PViewX3D.h
@@ -12,6 +12,7 @@
 #define _PVIEWX3D_H_
 
 #include <iostream>
+#include <limits>
 
 using namespace std;
 
@@ -43,5 +44,22 @@ static void writeX3DScaleLabel (FILE *fp, PView *p, double xmin, double ymin, do
 static void writeX3DStringCenter( FILE *fp,char *label,double x, double y, double z,double font_size); 
  
 
+class TriangleToSort{
+ public:
+  PView* _ppv;
+  int _index;
+  int _globalIndex;
+  float xmin,ymin,zmin;
+  float xmax,ymax,zmax;
+};
+
+
+static bool almostEqual(double x,double y){
+  return std::abs(x-y) <  PView::_precision  ;
+    
+}
+
+
+
 #endif
 
-- 
GitLab