00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00039 #include <OSD_Path.hxx>
00040 #include <OSD_Protection.hxx>
00041
00042 #include <TCollection_AsciiString.hxx>
00043 #include <gp_XYZ.hxx>
00044
00045 #include "utilities.h"
00046
00047
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, 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
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
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
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
00306
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
00324 TCollection_AsciiString sval(LABEL_SIZE-1,' ');
00325 aFile.Write((Standard_Address)sval.ToCString(),LABEL_SIZE);
00326
00327
00328 writeInteger(nbTri,aFile);
00329
00330
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 }