Back to index

salome-smesh  6.5.0
DriverSTL_W_SMDS_Mesh.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include <stdio.h>
00024 #include <limits>
00025 
00026 #include "DriverSTL_W_SMDS_Mesh.h"
00027 
00028 #include "SMDS_FaceOfNodes.hxx"
00029 #include "SMDS_IteratorOnIterators.hxx"
00030 #include "SMDS_Mesh.hxx"
00031 #include "SMDS_MeshElement.hxx"
00032 #include "SMDS_MeshNode.hxx"
00033 #include "SMDS_SetIterator.hxx"
00034 #include "SMDS_VolumeTool.hxx"
00035 #include "SMESH_TypeDefs.hxx"
00036 
00037 #include <OSD_File.hxx>
00038 //#include <OSD_FromWhere.hxx>
00039 #include <OSD_Path.hxx>
00040 #include <OSD_Protection.hxx>
00041 //#include <OSD_SingleProtection.hxx>
00042 #include <TCollection_AsciiString.hxx>
00043 #include <gp_XYZ.hxx>
00044 
00045 #include "utilities.h"
00046 
00047 // definition des constantes 
00048 static const int LABEL_SIZE = 80;
00049 
00050 DriverSTL_W_SMDS_Mesh::DriverSTL_W_SMDS_Mesh()
00051 {
00052   myIsAscii = false;
00053 }
00054 
00055 void DriverSTL_W_SMDS_Mesh::SetIsAscii( const bool theIsAscii )
00056 {
00057   myIsAscii = theIsAscii;
00058 }
00059 
00060 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::Perform()
00061 {
00062   Status aResult = DRS_OK;
00063 
00064   if ( !myMesh ) {
00065     fprintf(stderr, ">> ERROR : Mesh is null \n");
00066     return DRS_FAIL;
00067   }
00068   findVolumeTriangles();
00069   if ( myIsAscii )
00070     aResult = writeAscii();
00071   else
00072     aResult = writeBinary();
00073 
00074   return aResult;
00075 }
00076 //================================================================================
00080 //================================================================================
00081 
00082 DriverSTL_W_SMDS_Mesh::~DriverSTL_W_SMDS_Mesh()
00083 {
00084   for ( unsigned i = 0; i < myVolumeTrias.size(); ++i )
00085     delete myVolumeTrias[i];
00086 }
00087 
00088 //================================================================================
00092 //================================================================================
00093 
00094 void DriverSTL_W_SMDS_Mesh::findVolumeTriangles()
00095 {
00096   SMDS_VolumeTool myTool;
00097   SMDS_VolumeIteratorPtr vIt = myMesh->volumesIterator();
00098   while ( vIt->more() )
00099   {
00100     myTool.Set( vIt->next() );
00101     for ( int iF = 0; iF < myTool.NbFaces(); ++iF )
00102       if ( myTool.IsFreeFace( iF ))
00103       {
00104         const SMDS_MeshNode** n = myTool.GetFaceNodes(iF);
00105         int                 nbN = myTool.NbFaceNodes(iF);
00106         std::vector< const SMDS_MeshNode*> nodes( n, n+nbN );
00107         if ( !myMesh->FindElement( nodes, SMDSAbs_Face, /*Nomedium=*/false))
00108         {
00109           int nbTria = nbN - 2;
00110           for ( int iT = 0; iT < nbTria; ++iT )
00111           {
00112             myVolumeTrias.push_back( new SMDS_FaceOfNodes( n[0], n[1+iT], n[2+iT] ));
00113           }
00114         }
00115       }
00116   }
00117 }
00118 
00119 //================================================================================
00123 //================================================================================
00124 
00125 SMDS_ElemIteratorPtr DriverSTL_W_SMDS_Mesh::getFaces() const
00126 {
00127   SMDS_ElemIteratorPtr facesIter = myMesh->elementsIterator(SMDSAbs_Face);
00128   SMDS_ElemIteratorPtr tmpTriaIter( new SMDS_ElementVectorIterator( myVolumeTrias.begin(),
00129                                                                     myVolumeTrias.end()));
00130   typedef std::vector< SMDS_ElemIteratorPtr > TElemIterVector;
00131   TElemIterVector iters(2);
00132   iters[0] = facesIter;
00133   iters[1] = tmpTriaIter;
00134   
00135   typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
00136   return SMDS_ElemIteratorPtr( new TItersIter( iters ));
00137 }
00138 
00139 // static methods
00140 
00141 static void writeInteger( const Standard_Integer& theVal,
00142                          OSD_File& ofile )
00143 {
00144   union {
00145     Standard_Integer i;
00146     char c[4];
00147   }u;
00148 
00149   u.i = theVal;
00150 
00151   Standard_Integer entier;
00152   entier  =  u.c[0] & 0xFF;
00153   entier |= (u.c[1] & 0xFF) << 0x08;
00154   entier |= (u.c[2] & 0xFF) << 0x10;
00155   entier |= (u.c[3] & 0xFF) << 0x18;
00156 
00157   ofile.Write((char *)&entier,sizeof(u.c));
00158 }
00159 
00160 static void writeFloat  ( const Standard_ShortReal& theVal,
00161                          OSD_File& ofile)
00162 {
00163   union {
00164     Standard_ShortReal f;
00165     char c[4]; 
00166   }u;
00167 
00168   u.f = theVal;
00169 
00170   Standard_Integer entier;
00171 
00172   entier  =  u.c[0] & 0xFF;
00173   entier |= (u.c[1] & 0xFF) << 0x08;
00174   entier |= (u.c[2] & 0xFF) << 0x10;
00175   entier |= (u.c[3] & 0xFF) << 0x18;
00176 
00177   ofile.Write((char *)&entier,sizeof(u.c));
00178 }
00179 
00180 static gp_XYZ getNormale( const SMDS_MeshNode* n1,
00181                           const SMDS_MeshNode* n2,
00182                           const SMDS_MeshNode* n3)
00183 {
00184   SMESH_TNodeXYZ xyz1( n1 );
00185   SMESH_TNodeXYZ xyz2( n2 );
00186   SMESH_TNodeXYZ xyz3( n3 );
00187   gp_XYZ q1 = xyz2 - xyz1;
00188   gp_XYZ q2 = xyz3 - xyz1;
00189   gp_XYZ n  = q1 ^ q2;
00190   double len = n.Modulus();
00191   if ( len > std::numeric_limits<double>::min() )
00192     n /= len;
00193 
00194   return n;
00195 }
00196 
00197 //================================================================================
00202 //================================================================================
00203 
00204 static int getTriangles( const SMDS_MeshElement* face,
00205                          const SMDS_MeshNode**   nodes)
00206 {
00207   // WARNING: implementation must be coherent with counting triangles in writeBinary()
00208   int nbN = face->NbCornerNodes();
00209   const int nbTria = nbN-2;
00210   for ( int i = 0; nbN > 1; --nbN )
00211   {
00212     nodes[ i++ ] = face->GetNode( 0 );
00213     nodes[ i++ ] = face->GetNode( nbN-2 );
00214     nodes[ i++ ] = face->GetNode( nbN-1 );
00215   }
00216   return nbTria;
00217 }
00218 
00219 // private methods
00220 
00221 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
00222 {
00223   Status aResult = DRS_OK;
00224   TCollection_AsciiString aFileName( (char *)myFile.c_str() );
00225   if ( aFileName.IsEmpty() ) {
00226     fprintf(stderr, ">> ERREOR : invalid file name \n");
00227     return DRS_FAIL;
00228   }
00229 
00230   OSD_File aFile = OSD_File(OSD_Path(aFileName));
00231   aFile.Build(OSD_WriteOnly,OSD_Protection());
00232 
00233   char sval[16];
00234   TCollection_AsciiString buf = TCollection_AsciiString ("solid\n");
00235   aFile.Write (buf,buf.Length());buf.Clear();
00236 
00237   const SMDS_MeshNode* triaNodes[2048];
00238 
00239   SMDS_ElemIteratorPtr itFaces = getFaces();
00240   while ( itFaces->more() )
00241   {
00242     const SMDS_MeshElement* aFace = itFaces->next();
00243     int nbTria = getTriangles( aFace, triaNodes );
00244     
00245     for ( int iT = 0, iN = 0; iT < nbTria; ++iT )
00246     {
00247       gp_XYZ normale = getNormale( triaNodes[iN],
00248                                    triaNodes[iN+1],
00249                                    triaNodes[iN+2] );
00250 
00251       buf += " facet normal "; 
00252       sprintf (sval,"% 12e",normale.X());
00253       buf += sval;
00254       buf += " "; 
00255       sprintf (sval,"% 12e",normale.Y());
00256       buf += sval;
00257       buf += " "; 
00258       sprintf (sval,"% 12e",normale.Z());
00259       buf += sval;
00260       buf += '\n';
00261       aFile.Write (buf,buf.Length());buf.Clear();
00262       buf += "   outer loop\n"; 
00263       aFile.Write (buf,buf.Length());buf.Clear();
00264       
00265       for ( int jN = 0; jN < 3; ++jN, ++iN ) {
00266         const SMDS_MeshNode* node = triaNodes[iN];
00267         buf += "     vertex "; 
00268         sprintf (sval,"% 12e",node->X());
00269         buf += sval;
00270         buf += " "; 
00271         sprintf (sval,"% 12e",node->Y());
00272         buf += sval;
00273         buf += " "; 
00274         sprintf (sval,"% 12e",node->Z());
00275         buf += sval;
00276         buf += '\n';
00277         aFile.Write (buf,buf.Length());buf.Clear();
00278       }
00279       buf += "   endloop\n"; 
00280       aFile.Write (buf,buf.Length());buf.Clear();
00281       buf += " endfacet\n"; 
00282       aFile.Write (buf,buf.Length());buf.Clear();
00283     } 
00284   }
00285   buf += "endsolid\n";
00286   aFile.Write (buf,buf.Length());buf.Clear();
00287   
00288   aFile.Close ();
00289 
00290   return aResult;
00291 }
00292 
00293 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const
00294 {
00295   Status aResult = DRS_OK;
00296   TCollection_AsciiString aFileName( (char *)myFile.c_str() );
00297   if ( aFileName.IsEmpty() ) {
00298     fprintf(stderr, ">> ERREOR : invalid filename \n");
00299     return DRS_FAIL;
00300   }
00301 
00302   OSD_File aFile = OSD_File(OSD_Path(aFileName));
00303   aFile.Build(OSD_WriteOnly,OSD_Protection());
00304 
00305   // we first count the number of triangles
00306   // WARNING: counting triangles must be coherent with getTriangles()
00307   int nbTri = 0;
00308   const SMDS_MeshInfo& info = myMesh->GetMeshInfo();
00309   nbTri += info.NbTriangles();
00310   nbTri += info.NbQuadrangles() * 2;
00311   nbTri += myVolumeTrias.size();
00312   if ( info.NbPolygons() > 0 )
00313   {
00314     SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
00315     while ( itFaces->more() )
00316     {
00317       const SMDS_MeshElement* aFace = itFaces->next();
00318       if ( aFace->IsPoly() )
00319         nbTri += aFace->NbNodes() - 2;
00320     }
00321   }
00322 
00323   // char sval[80]; -- avoid writing not initialized memory
00324   TCollection_AsciiString sval(LABEL_SIZE-1,' ');
00325   aFile.Write((Standard_Address)sval.ToCString(),LABEL_SIZE);
00326 
00327   // write number of triangles
00328   writeInteger(nbTri,aFile);  
00329 
00330   // Loop writing nodes
00331 
00332   int dum=0;
00333 
00334   const SMDS_MeshNode* triaNodes[2048];
00335 
00336   SMDS_ElemIteratorPtr itFaces = getFaces();
00337   while ( itFaces->more() )
00338   {
00339     const SMDS_MeshElement* aFace = itFaces->next();
00340     int nbTria = getTriangles( aFace, triaNodes );
00341     
00342     for ( int iT = 0, iN = 0; iT < nbTria; ++iT )
00343     {
00344       gp_XYZ normale = getNormale( triaNodes[iN],
00345                                    triaNodes[iN+1],
00346                                    triaNodes[iN+2] );
00347       writeFloat(normale.X(),aFile);
00348       writeFloat(normale.Y(),aFile);
00349       writeFloat(normale.Z(),aFile);
00350 
00351       for ( int jN = 0; jN < 3; ++jN, ++iN )
00352       {
00353         const SMDS_MeshNode* node = triaNodes[iN];
00354         writeFloat(node->X(),aFile);
00355         writeFloat(node->Y(),aFile);
00356         writeFloat(node->Z(),aFile);
00357       }
00358       aFile.Write (&dum,2);
00359     } 
00360   }
00361   aFile.Close ();
00362 
00363   return aResult;
00364 }