From: eap Date: Mon, 24 Sep 2012 11:15:01 +0000 (+0000) Subject: HEXA_27021382: EDF 1985 SMESH: Read/write of .mesh files (GMF format) X-Git-Tag: V6_6_0a1~97 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=d9d9b3662766e52325dbf71a029b7e89990f0f63;p=modules%2Fsmesh.git HEXA_27021382: EDF 1985 SMESH: Read/write of .mesh files (GMF format) --- diff --git a/src/DriverGMF/DriverGMF_Read.cxx b/src/DriverGMF/DriverGMF_Read.cxx new file mode 100644 index 000000000..332519b2e --- /dev/null +++ b/src/DriverGMF/DriverGMF_Read.cxx @@ -0,0 +1,357 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, Read to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverGMF_Read.cxx +// Created : Mon Sep 17 17:03:02 2012 +// Author : Edward AGAPOV (eap) + +#include "DriverGMF_Read.hxx" +#include "DriverGMF_Write.hxx" + +#include "SMESHDS_Group.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Comment.hxx" + +extern "C" +{ +#include "libmesh5.h" +} + +#include + +// -------------------------------------------------------------------------------- +// Closing GMF mesh at destruction +DriverGMF_MeshCloser::~DriverGMF_MeshCloser() +{ + if ( _gmfMeshID ) + GmfCloseMesh( _gmfMeshID ); +} +// -------------------------------------------------------------------------------- +DriverGMF_Read::DriverGMF_Read(): + Driver_SMESHDS_Mesh() +{ +} +// -------------------------------------------------------------------------------- +DriverGMF_Read::~DriverGMF_Read() +{ +} + +//================================================================================ +/*! + * \brief Read a GMF file + */ +//================================================================================ + +Driver_Mesh::Status DriverGMF_Read::Perform() +{ + Status status = DRS_OK; + + int dim, version; + + // open the file + int meshID = GmfOpenMesh( myFile.c_str(), GmfRead, &version, &dim ); + if ( !meshID ) + return addMessage( SMESH_Comment("Can't open for reading ") << myFile, /*fatal=*/true ); + + DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction + + // Read nodes + + int nbNodes = GmfStatKwd(meshID, GmfVertices); + if ( nbNodes < 1 ) + return addMessage( "No nodes in the mesh", /*fatal=*/true ); + + GmfGotoKwd(meshID, GmfVertices); + + int ref; + + const int nodeIDShift = myMesh->GetMeshInfo().NbNodes(); + if ( version != GmfFloat ) + { + double x, y, z; + for ( int i = 1; i <= nbNodes; ++i ) + { + GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref); + myMesh->AddNodeWithID( x,y,z, nodeIDShift + i); + } + } + else + { + float x, y, z; + for ( int i = 1; i <= nbNodes; ++i ) + { + GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref); + myMesh->AddNodeWithID( x,y,z, nodeIDShift + i); + } + } + + // Read elements + + int iN[28]; + + /* Read edges */ + const int edgeIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbEdges = GmfStatKwd(meshID, GmfEdges)) + { + GmfGotoKwd(meshID, GmfEdges); + for ( int i = 1; i <= nbEdges; ++i ) + { + GmfGetLin(meshID, GmfEdges, &iN[0], &iN[1], &ref); + if ( !myMesh->AddEdgeWithID( iN[0], iN[1], edgeIDShift + i )) + status = storeBadNodeIds( "GmfEdges",i, 2, iN[0], iN[1] ); + } + } + /* Read quadratic edges */ + const int edge2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbEdges = GmfStatKwd(meshID, GmfEdgesP2)) + { + GmfGotoKwd(meshID, GmfEdgesP2); + for ( int i = 1; i <= nbEdges; ++i ) + { + GmfGetLin(meshID, GmfEdgesP2, &iN[0], &iN[1], &iN[2], &ref); + if ( !myMesh->AddEdgeWithID( iN[0], iN[1], iN[2], edge2IDShift + i )) + status = storeBadNodeIds( "GmfEdgesP2",i, 3, iN[0], iN[1], iN[2] ); + } + } + /* Read triangles */ + const int triaIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTria = GmfStatKwd(meshID, GmfTriangles)) + { + GmfGotoKwd(meshID, GmfTriangles); + for ( int i = 1; i <= nbTria; ++i ) + { + GmfGetLin(meshID, GmfTriangles, &iN[0], &iN[1], &iN[2], &ref); + if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], triaIDShift + i )) + status = storeBadNodeIds( "GmfTriangles",i, 3, iN[0], iN[1], iN[2] ); + } + } + /* Read quadratic triangles */ + const int tria2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTria = GmfStatKwd(meshID, GmfTrianglesP2)) + { + GmfGotoKwd(meshID, GmfTrianglesP2); + for ( int i = 1; i <= nbTria; ++i ) + { + GmfGetLin(meshID, GmfTrianglesP2, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref); + if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2],iN[3],iN[4],iN[5], + tria2IDShift + i )) + status = storeBadNodeIds( "GmfTrianglesP2",i, 6, iN[0],iN[1],iN[2],iN[3],iN[4],iN[5] ); + } + } + /* Read quadrangles */ + const int quadIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilaterals)) + { + GmfGotoKwd(meshID, GmfQuadrilaterals); + for ( int i = 1; i <= nbQuad; ++i ) + { + GmfGetLin(meshID, GmfQuadrilaterals, &iN[0], &iN[1], &iN[2], &iN[3], &ref); + if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3], quadIDShift + i )) + status = storeBadNodeIds( "GmfQuadrilaterals",i, 4, iN[0], iN[1],iN[2], iN[3] ); + } + } + /* Read bi-quadratic quadrangles */ + const int quad2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilateralsQ2)) + { + GmfGotoKwd(meshID, GmfQuadrilateralsQ2); + for ( int i = 1; i <= nbQuad; ++i ) + { + GmfGetLin(meshID, GmfQuadrilateralsQ2, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &ref); + if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],iN[6],iN[7],iN[8], + quad2IDShift + i )) + status = storeBadNodeIds( "GmfQuadrilateralsQ2",i, + 9, iN[0],iN[1],iN[2],iN[3],iN[4],iN[5],iN[6],iN[7],iN[8] ); + } + } + /* Read terahedra */ + const int tetIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedra)) + { + GmfGotoKwd(meshID, GmfTetrahedra); + for ( int i = 1; i <= nbTet; ++i ) + { + GmfGetLin(meshID, GmfTetrahedra, &iN[0], &iN[1], &iN[2], &iN[3], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], tetIDShift + i )) + status = storeBadNodeIds( "GmfTetrahedra",i, 4, iN[0], iN[1],iN[2], iN[3] ); + } + } + /* Read quadratic terahedra */ + const int tet2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedraP2)) + { + GmfGotoKwd(meshID, GmfTetrahedraP2); + for ( int i = 1; i <= nbTet; ++i ) + { + GmfGetLin(meshID, GmfTetrahedraP2, &iN[0], &iN[1], &iN[2], + &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &iN[9], &ref); + if ( !myMesh->AddVolumeWithID( iN[0],iN[2],iN[1],iN[3], + iN[6],iN[5],iN[4], + iN[7],iN[9],iN[8], tet2IDShift + i )) + status = storeBadNodeIds( "GmfTetrahedraP2",i, 10, iN[0],iN[1],iN[2],iN[3], + iN[4],iN[5],iN[6],iN[7],iN[8],iN[9] ); + } + } + /* Read pyramids */ + const int pyrIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbPyr = GmfStatKwd(meshID, GmfPyramids)) + { + GmfGotoKwd(meshID, GmfPyramids); + for ( int i = 1; i <= nbPyr; ++i ) + { + GmfGetLin(meshID, GmfPyramids, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[4], pyrIDShift + i )) + status = storeBadNodeIds( "GmfPyramids",i, 5, iN[0], iN[1],iN[2], iN[3], iN[4] ); + } + } + /* Read hexahedra */ + const int hexIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbHex = GmfStatKwd(meshID, GmfHexahedra)) + { + GmfGotoKwd(meshID, GmfHexahedra); + for ( int i = 1; i <= nbHex; ++i ) + { + GmfGetLin(meshID, GmfHexahedra, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1], iN[4], iN[7], iN[6], iN[5], + hexIDShift + i)) + status = storeBadNodeIds( "GmfHexahedra",i, + 8, iN[0], iN[1],iN[2], iN[3], iN[4], iN[7], iN[6], iN[5] ); + } + } + /* Read tri-quadratic hexahedra */ + const int hex2IDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbHex = GmfStatKwd(meshID, GmfHexahedraQ2)) + { + GmfGotoKwd(meshID, GmfHexahedraQ2); + for ( int i = 1; i <= nbHex; ++i ) + { + GmfGetLin(meshID, GmfHexahedraQ2, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], + &iN[6], &iN[7], &iN[8],&iN[9],&iN[10],&iN[11],&iN[12],&iN[13],&iN[14], + &iN[15],&iN[16],&iN[17],&iN[18],&iN[19],&iN[20],&iN[21],&iN[22],&iN[23], + &iN[24],&iN[25],&iN[26], &ref); + if ( !myMesh->AddVolumeWithID( iN[0],iN[3],iN[2],iN[1],iN[4],iN[7],iN[6],iN[5],iN[11],iN[10], + iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17], + iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26], + hex2IDShift + i )) + status = storeBadNodeIds( "GmfHexahedraQ2",i, 27, + iN[0],iN[3],iN[2],iN[1],iN[4], iN[7],iN[6],iN[5],iN[11],iN[10], + iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17], + iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26]); + } + } + /* Read prism */ + const int prismIDShift = myMesh->GetMeshInfo().NbElements(); + if ( int nbPrism = GmfStatKwd(meshID, GmfPrisms)) + { + GmfGotoKwd(meshID, GmfPrisms); + for ( int i = 1; i <= nbPrism; ++i ) + { + GmfGetLin(meshID, GmfPrisms, + &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref); + if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[5], iN[4], prismIDShift + i)) + status = storeBadNodeIds( "GmfPrisms",i, + 6, iN[0], iN[1],iN[2], iN[3], iN[4], iN[5] ); + } + } + + // Read required entities into groups + + // get ids of existing groups + std::set< int > groupIDs; + const std::set& groups = myMesh->GetGroups(); + std::set::const_iterator grIter = groups.begin(); + for ( ; grIter != groups.end(); ++grIter ) + groupIDs.insert( (*grIter)->GetID() ); + if ( groupIDs.empty() ) groupIDs.insert( 0 ); + + const int kes[4][3] = { { GmfRequiredVertices, SMDSAbs_Node, nodeIDShift }, + { GmfRequiredEdges, SMDSAbs_Edge, edgeIDShift }, + { GmfRequiredTriangles, SMDSAbs_Face, triaIDShift }, + { GmfRequiredQuadrilaterals,SMDSAbs_Face, quadIDShift }}; + const char* names[4] = { "_required_Vertices" , + "_required_Edges" , + "_required_Triangles" , + "_required_Quadrilaterals" }; + for ( int i = 0; i < 4; ++i ) + { + int gmfKwd = kes[i][0]; + SMDSAbs_ElementType entity = (SMDSAbs_ElementType) kes[i][1]; + int shift = kes[i][2]; + if ( int nb = GmfStatKwd(meshID, gmfKwd)) + { + const int newID = *groupIDs.rbegin() + 1; + groupIDs.insert( newID ); + SMESHDS_Group* group = new SMESHDS_Group( newID, myMesh, entity ); + group->SetStoreName( names[i] ); + myMesh->AddGroup( group ); + + GmfGotoKwd(meshID, gmfKwd); + for ( int i = 0; i < nb; ++i ) + { + GmfGetLin(meshID, gmfKwd, &iN[0] ); + group->Add( shift + iN[0] ); + } + } + } + + return status; +} + +//================================================================================ +/*! + * \brief Store a message about invalid IDs of nodes + */ +//================================================================================ + +Driver_Mesh::Status DriverGMF_Read::storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...) +{ + if ( myStatus != DRS_OK ) + return myStatus; + + SMESH_Comment msg; + + va_list VarArg; + va_start(VarArg, nb); + + for ( int i = 0; i < nb; ++i ) + { + int id = va_arg(VarArg, int ); + if ( !myMesh->FindNode( id )) + msg << " " << id; + } + va_end(VarArg); + + if ( !msg.empty() ) + { + std::string nbStr; + const char* nbNames[] = { "1-st ", "2-nd ", "3-d " }; + if ( elemNb < 3 ) nbStr = nbNames[ elemNb-1 ]; + else nbStr = SMESH_Comment(elemNb) << "-th "; + + return addMessage + ( SMESH_Comment("Wrong node IDs of ")<< nbStr << gmfKwd << ":" << msg, + /*fatal=*/false ); + } + return DRS_OK; +} diff --git a/src/DriverGMF/DriverGMF_Read.hxx b/src/DriverGMF/DriverGMF_Read.hxx new file mode 100644 index 000000000..a003804f0 --- /dev/null +++ b/src/DriverGMF/DriverGMF_Read.hxx @@ -0,0 +1,57 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, Read to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverGMF_Read.hxx +// Created : Mon Sep 17 15:36:47 2012 +// Author : Edward AGAPOV (eap) + + +#ifndef __DriverGMF_Read_HXX__ +#define __DriverGMF_Read_HXX__ + +#include "SMESH_DriverGMF.hxx" + +#include "Driver_SMESHDS_Mesh.h" + +#include +#include + +/*! + * \brief Driver reading a mesh from the GMF file. The mesh to read is selected by + * an index (counted form 0) set via SetMeshId() + */ +class MESHDriverGMF_EXPORT DriverGMF_Read : public Driver_SMESHDS_Mesh +{ +public: + + DriverGMF_Read(); + ~DriverGMF_Read(); + + virtual Status Perform(); + + private: + + Status storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...); + +}; + + +#endif diff --git a/src/DriverGMF/DriverGMF_Write.cxx b/src/DriverGMF/DriverGMF_Write.cxx new file mode 100644 index 000000000..78f414b43 --- /dev/null +++ b/src/DriverGMF/DriverGMF_Write.cxx @@ -0,0 +1,319 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverGMF_Write.cxx +// Created : Mon Sep 17 17:03:02 2012 +// Author : Edward AGAPOV (eap) + +#include "DriverGMF_Write.hxx" + +#include "SMESHDS_GroupBase.hxx" +#include "SMESHDS_Mesh.hxx" +#include "SMESH_Comment.hxx" + +extern "C" +{ +#include "libmesh5.h" +} + +#include + +#define BEGIN_ELEM_WRITE( SMDSEntity, GmfKwd, elem ) \ + elemIt = myMesh->elementEntityIterator( SMDSEntity ); \ + if ( elemIt->more() ) \ + { \ + GmfSetKwd(meshID, GmfKwd, myMesh->GetMeshInfo().NbEntities( SMDSEntity )); \ + for ( int gmfID = 1; elemIt->more(); ++gmfID ) \ + { \ + const SMDS_MeshElement* elem = elemIt->next(); \ + GmfSetLin(meshID, GmfKwd, + +#define END_ELEM_WRITE( elem ) \ + elem->getshapeId() ); \ + }} \ + +#define END_ELEM_WRITE_ADD_TO_MAP( elem, e2id ) \ + elem->getshapeId() ); \ + e2id.insert( e2id.end(), make_pair( elem, gmfID )); \ + }} \ + + +DriverGMF_Write::DriverGMF_Write(): + Driver_SMESHDS_Mesh() +{ +} +DriverGMF_Write::~DriverGMF_Write() +{ +} + +Driver_Mesh::Status DriverGMF_Write::Perform() +{ + const int dim = 3, version = 3; + + int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim ); + if ( !meshID ) + return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true ); + + DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction + + // nodes + std::map< const SMDS_MeshNode* , int > node2IdMap; + int iN = 0, nbNodes = myMesh->NbNodes(); + GmfSetKwd( meshID, GmfVertices, nbNodes ); + double xyz[3]; + SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator(); + while ( nodeIt->more() ) + { + const SMDS_MeshNode* n = nodeIt->next(); + n->GetXYZ( xyz ); + GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() ); + node2IdMap.insert( node2IdMap.end(), make_pair( n, ++iN )); + } + if ( iN != nbNodes ) + return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true); + + + SMDS_ElemIteratorPtr elemIt; + typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap; + + // edges + TElem2IDMap edge2IDMap; + BEGIN_ELEM_WRITE( SMDSEntity_Edge, GmfEdges, edge ) + node2IdMap[ edge->GetNode( 0 )], + node2IdMap[ edge->GetNode( 1 )], + END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap ); + + // quadratic edges + BEGIN_ELEM_WRITE( SMDSEntity_Quad_Edge, GmfEdgesP2, edge ) + node2IdMap[ edge->GetNode( 0 )], + node2IdMap[ edge->GetNode( 1 )], + node2IdMap[ edge->GetNode( 2 )], + END_ELEM_WRITE( edge ); + + // triangles + TElem2IDMap tria2IDMap; + BEGIN_ELEM_WRITE( SMDSEntity_Triangle, GmfTriangles, tria ) + node2IdMap[ tria->GetNode( 0 )], + node2IdMap[ tria->GetNode( 1 )], + node2IdMap[ tria->GetNode( 2 )], + END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap ); + + // quadratic triangles + BEGIN_ELEM_WRITE( SMDSEntity_Quad_Triangle, GmfTrianglesP2, tria ) + node2IdMap[ tria->GetNode( 0 )], + node2IdMap[ tria->GetNode( 1 )], + node2IdMap[ tria->GetNode( 2 )], + node2IdMap[ tria->GetNode( 3 )], + node2IdMap[ tria->GetNode( 4 )], + node2IdMap[ tria->GetNode( 5 )], + END_ELEM_WRITE( tria ); + + // quadrangles + TElem2IDMap quad2IDMap; + BEGIN_ELEM_WRITE( SMDSEntity_Quadrangle, GmfQuadrilaterals, quad ) + node2IdMap[ quad->GetNode( 0 )], + node2IdMap[ quad->GetNode( 1 )], + node2IdMap[ quad->GetNode( 2 )], + node2IdMap[ quad->GetNode( 3 )], + END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap ); + + // bi-quadratic quadrangles + BEGIN_ELEM_WRITE( SMDSEntity_BiQuad_Quadrangle, GmfQuadrilateralsQ2, quad ) + node2IdMap[ quad->GetNode( 0 )], + node2IdMap[ quad->GetNode( 3 )], + node2IdMap[ quad->GetNode( 2 )], + node2IdMap[ quad->GetNode( 1 )], + node2IdMap[ quad->GetNode( 7 )], + node2IdMap[ quad->GetNode( 6 )], + node2IdMap[ quad->GetNode( 5 )], + node2IdMap[ quad->GetNode( 4 )], + node2IdMap[ quad->GetNode( 8 )], + END_ELEM_WRITE( quad ); + + // terahedra + BEGIN_ELEM_WRITE( SMDSEntity_Tetra, GmfTetrahedra, tetra ) + node2IdMap[ tetra->GetNode( 0 )], + node2IdMap[ tetra->GetNode( 2 )], + node2IdMap[ tetra->GetNode( 1 )], + node2IdMap[ tetra->GetNode( 3 )], + END_ELEM_WRITE( tetra ); + + // quadratic terahedra + BEGIN_ELEM_WRITE( SMDSEntity_Quad_Tetra, GmfTetrahedraP2, tetra ) + node2IdMap[ tetra->GetNode( 0 )], + node2IdMap[ tetra->GetNode( 2 )], + node2IdMap[ tetra->GetNode( 1 )], + node2IdMap[ tetra->GetNode( 3 )], + node2IdMap[ tetra->GetNode( 6 )], + node2IdMap[ tetra->GetNode( 5 )], + node2IdMap[ tetra->GetNode( 4 )], + node2IdMap[ tetra->GetNode( 7 )], + node2IdMap[ tetra->GetNode( 9 )], + node2IdMap[ tetra->GetNode( 8 )], + END_ELEM_WRITE( tetra ); + + // pyramids + BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra ) + node2IdMap[ pyra->GetNode( 0 )], + node2IdMap[ pyra->GetNode( 2 )], + node2IdMap[ pyra->GetNode( 1 )], + node2IdMap[ pyra->GetNode( 3 )], + node2IdMap[ pyra->GetNode( 4 )], + END_ELEM_WRITE( pyra ); + + // hexahedra + BEGIN_ELEM_WRITE( SMDSEntity_Hexa, GmfHexahedra, hexa ) + node2IdMap[ hexa->GetNode( 0 )], + node2IdMap[ hexa->GetNode( 3 )], + node2IdMap[ hexa->GetNode( 2 )], + node2IdMap[ hexa->GetNode( 1 )], + node2IdMap[ hexa->GetNode( 4 )], + node2IdMap[ hexa->GetNode( 7 )], + node2IdMap[ hexa->GetNode( 6 )], + node2IdMap[ hexa->GetNode( 5 )], + END_ELEM_WRITE( hexa ); + + // tri-quadratic hexahedra + BEGIN_ELEM_WRITE( SMDSEntity_TriQuad_Hexa, GmfHexahedraQ2, hexa ) + node2IdMap[ hexa->GetNode( 0 )], + node2IdMap[ hexa->GetNode( 3 )], + node2IdMap[ hexa->GetNode( 2 )], + node2IdMap[ hexa->GetNode( 1 )], + node2IdMap[ hexa->GetNode( 4 )], + node2IdMap[ hexa->GetNode( 7 )], + node2IdMap[ hexa->GetNode( 6 )], + node2IdMap[ hexa->GetNode( 5 )], + node2IdMap[ hexa->GetNode( 11 )], + node2IdMap[ hexa->GetNode( 10 )], + node2IdMap[ hexa->GetNode( 9 )], + node2IdMap[ hexa->GetNode( 8 )], + node2IdMap[ hexa->GetNode( 12 )], + node2IdMap[ hexa->GetNode( 15 )], + node2IdMap[ hexa->GetNode( 14 )], + node2IdMap[ hexa->GetNode( 13 )], + node2IdMap[ hexa->GetNode( 19 )], + node2IdMap[ hexa->GetNode( 18 )], + node2IdMap[ hexa->GetNode( 17 )], + node2IdMap[ hexa->GetNode( 16 )], + node2IdMap[ hexa->GetNode( 20 )], + node2IdMap[ hexa->GetNode( 24 )], + node2IdMap[ hexa->GetNode( 23 )], + node2IdMap[ hexa->GetNode( 22 )], + node2IdMap[ hexa->GetNode( 21 )], + node2IdMap[ hexa->GetNode( 25 )], + node2IdMap[ hexa->GetNode( 26 )], + END_ELEM_WRITE( hexa ); + + // prism + BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism ) + node2IdMap[ prism->GetNode( 0 )], + node2IdMap[ prism->GetNode( 2 )], + node2IdMap[ prism->GetNode( 1 )], + node2IdMap[ prism->GetNode( 3 )], + node2IdMap[ prism->GetNode( 5 )], + node2IdMap[ prism->GetNode( 4 )], + END_ELEM_WRITE( prism ); + + + // required entities + SMESH_Comment badGroups; + const std::set& groupSet = myMesh->GetGroups(); + std::set::const_iterator grIt = groupSet.begin(); + for ( ; grIt != groupSet.end(); ++grIt ) + { + const SMESHDS_GroupBase* group = *grIt; + std::string groupName = group->GetStoreName(); + std::string::size_type pos = groupName.find( "_required_" ); + if ( pos == std::string::npos ) continue; + + int gmfKwd; + SMDSAbs_EntityType smdsEntity; + std::string entity = groupName.substr( pos + strlen("_required_")); + if ( entity == "Vertices" ) { + gmfKwd = GmfRequiredVertices; + smdsEntity = SMDSEntity_Node; + } + else if ( entity == "Edges" ) { + gmfKwd = GmfRequiredEdges; + smdsEntity = SMDSEntity_Edge; + } + else if ( entity == "Triangles" ) { + gmfKwd = GmfRequiredTriangles; + smdsEntity = SMDSEntity_Triangle; + } + else if ( entity == "Quadrilaterals" ) { + gmfKwd = GmfRequiredQuadrilaterals; + smdsEntity = SMDSEntity_Quadrangle; + } + else { + addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false ); + continue; + } + + // check elem type in the group + int nbOkElems = 0; + SMDS_ElemIteratorPtr elemIt = group->GetElements(); + while ( elemIt->more() ) + nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity ); + + if ( nbOkElems != group->Extent() && nbOkElems == 0 ) + { + badGroups << " " << groupName; + continue; + } + + // choose a TElem2IDMap + TElem2IDMap* elem2IDMap = 0; + if ( smdsEntity == SMDSEntity_Quadrangle && + myMesh->GetMeshInfo().NbEntities( smdsEntity ) != myMesh->NbFaces() ) + elem2IDMap = & quad2IDMap; + else if ( smdsEntity == SMDSEntity_Triangle && + myMesh->GetMeshInfo().NbEntities( smdsEntity ) != myMesh->NbFaces() ) + elem2IDMap = & tria2IDMap; + else if ( smdsEntity == SMDSEntity_Edge && + myMesh->GetMeshInfo().NbEntities( smdsEntity ) != myMesh->NbEdges() ) + elem2IDMap = & edge2IDMap; + + // write the group + GmfSetKwd( meshID, gmfKwd, nbOkElems ); + if ( elem2IDMap ) + for ( elemIt = group->GetElements(); elemIt->more(); ) + { + const SMDS_MeshElement* elem = elemIt->next(); + if ( elem->GetEntityType() == smdsEntity ) + GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] ); + } + else + for ( elemIt = group->GetElements(); elemIt->more(); ) + { + const SMDS_MeshElement* elem = elemIt->next(); + if ( elem->GetEntityType() == smdsEntity ) + GmfSetLin( meshID, gmfKwd, elem->GetID() ); + } + + } // loop on groups + + if ( !badGroups.empty() ) + addMessage( SMESH_Comment("Groups including elements of inappropriate geometry:") + << badGroups, /*fatal=*/false ); + + return DRS_OK; +} diff --git a/src/DriverGMF/DriverGMF_Write.hxx b/src/DriverGMF/DriverGMF_Write.hxx new file mode 100644 index 000000000..fd0918d09 --- /dev/null +++ b/src/DriverGMF/DriverGMF_Write.hxx @@ -0,0 +1,59 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : DriverGMF_Write.hxx +// Created : Mon Sep 17 15:36:47 2012 +// Author : Edward AGAPOV (eap) + + +#ifndef __DriverGMF_Write_HXX__ +#define __DriverGMF_Write_HXX__ + +#include "SMESH_DriverGMF.hxx" + +#include "Driver_SMESHDS_Mesh.h" +#include "SMDSAbs_ElementType.hxx" + +/*! + * \brief Driver Writing a mesh into a GMF file. + */ +class MESHDriverGMF_EXPORT DriverGMF_Write : public Driver_SMESHDS_Mesh +{ +public: + + DriverGMF_Write(); + ~DriverGMF_Write(); + + virtual Status Perform(); +}; + +/*! + * \brief An object closing GMF mesh at destruction + */ +struct DriverGMF_MeshCloser +{ + int _gmfMeshID; + DriverGMF_MeshCloser( const int gmfMeshID ): _gmfMeshID(gmfMeshID) {} + ~DriverGMF_MeshCloser(); +}; + + +#endif diff --git a/src/DriverGMF/Makefile.am b/src/DriverGMF/Makefile.am new file mode 100644 index 000000000..895c83a2f --- /dev/null +++ b/src/DriverGMF/Makefile.am @@ -0,0 +1,50 @@ +# Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# header files +salomeinclude_HEADERS = \ + DriverGMF_Read.hxx \ + DriverGMF_Write.hxx \ + SMESH_DriverGMF.hxx \ + libmesh5.h + +# Libraries targets +lib_LTLIBRARIES = libMeshDriverGMF.la +dist_libMeshDriverGMF_la_SOURCES = \ + DriverGMF_Read.cxx \ + DriverGMF_Write.cxx \ + libmesh5.c + +# additionnal information to compil and link file +libMeshDriverGMF_la_CPPFLAGS = \ + $(KERNEL_CXXFLAGS) \ + $(CAS_CPPFLAGS) \ + $(VTK_INCLUDES) \ + $(BOOST_CPPFLAGS) \ + -I$(srcdir)/../Driver \ + -I$(srcdir)/../SMESHUtils \ + -I$(srcdir)/../SMDS \ + -I$(srcdir)/../SMESHDS + +libMeshDriverGMF_la_LDFLAGS = \ + $(BOOST_LIBS) \ + ../Driver/libMeshDriver.la \ + ../SMESHUtils/libSMESHUtils.la diff --git a/src/DriverGMF/SMESH_DriverGMF.hxx b/src/DriverGMF/SMESH_DriverGMF.hxx new file mode 100755 index 000000000..dd901a3a2 --- /dev/null +++ b/src/DriverGMF/SMESH_DriverGMF.hxx @@ -0,0 +1,40 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SMESH_DriverGMF.hxx +// Author : Alexander A. BORODIN +// Module : SMESH +// +#ifndef _SMESH_DriverGMF_HXX_ +#define _SMESH_DriverGMF_HXX_ + +#ifdef WNT + #if defined MESHDriverGMF_EXPORTS || defined MeshDriverGMF_EXPORTS + #define MESHDriverGMF_EXPORT __declspec( dllexport ) + #else + #define MESHDriverGMF_EXPORT __declspec( dllimport ) + #endif +#else + #define MESHDriverGMF_EXPORT +#endif + +#endif diff --git a/src/DriverGMF/libmesh5.c b/src/DriverGMF/libmesh5.c new file mode 100644 index 000000000..b16c39c93 --- /dev/null +++ b/src/DriverGMF/libmesh5.c @@ -0,0 +1,1346 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 5.46 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: apr 03 2012 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Includes */ +/*----------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include "libmesh5.h" + + +/*----------------------------------------------------------*/ +/* Defines */ +/*----------------------------------------------------------*/ + +#define Asc 1 +#define Bin 2 +#define MshFil 4 +#define SolFil 8 +#define MaxMsh 100 +#define InfKwd 1 +#define RegKwd 2 +#define SolKwd 3 +#define WrdSiz 4 +#define BufSiz 10000 + + +/*----------------------------------------------------------*/ +/* Structures */ +/*----------------------------------------------------------*/ + +typedef struct +{ + int typ, SolSiz, NmbWrd, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ]; + long pos; + char fmt[ GmfMaxTyp*9 ]; +}KwdSct; + +typedef struct +{ + int dim, ver, mod, typ, cod, pos; + long NexKwdPos, siz; + KwdSct KwdTab[ GmfMaxKwd + 1 ]; + FILE *hdl; + int *IntBuf; + float *FltBuf; + unsigned char *buf; + char FilNam[ GmfStrSiz ]; + double DblBuf[1000/8]; + unsigned char blk[ BufSiz + 1000 ]; +}GmfMshSct; + + +/*----------------------------------------------------------*/ +/* Global variables */ +/*----------------------------------------------------------*/ + +static int GmfIniFlg=0; +static GmfMshSct *GmfMshTab[ MaxMsh + 1 ]; +static const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] = +{ {"Reserved", "", "", ""}, + {"MeshVersionFormatted", "", "", "i"}, + {"Reserved", "", "", ""}, + {"Dimension", "", "", "i"}, + {"Vertices", "Vertex", "i", "dri"}, + {"Edges", "Edge", "i", "iii"}, + {"Triangles", "Triangle", "i", "iiii"}, + {"Quadrilaterals", "Quadrilateral", "i", "iiiii"}, + {"Tetrahedra", "Tetrahedron", "i", "iiiii"}, + {"Prisms", "Prism", "i", "iiiiiii"}, + {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"}, + {"IterationsAll", "IterationAll","","i"}, + {"TimesAll", "TimeAll","","r"}, + {"Corners", "Corner", "i", "i"}, + {"Ridges", "Ridge", "i", "i"}, + {"RequiredVertices", "RequiredVertex", "i", "i"}, + {"RequiredEdges", "RequiredEdge", "i", "i"}, + {"RequiredTriangles", "RequiredTriangle", "i", "i"}, + {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"}, + {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"}, + {"NormalAtVertices", "NormalAtVertex", "i", "ii"}, + {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"}, + {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"}, + {"AngleOfCornerBound", "", "", "r"}, + {"TrianglesP2", "TriangleP2", "i", "iiiiiii"}, + {"EdgesP2", "EdgeP2", "i", "iiii"}, + {"SolAtPyramids", "SolAtPyramid", "i", "sr"}, + {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"}, + {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"}, + {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iiii"}, + {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"}, + {"Fault_NearTri", "Fault_NearTri", "i", "i"}, + {"Fault_Inter", "Fault_Inter", "i", "i"}, + {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"}, + {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"}, + {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"}, + {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"}, + {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"}, + {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"}, + {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"}, + {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"}, + {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"}, + {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"}, + {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"}, + {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"}, + {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"}, + {"Polygons", "Polygon", "", "iiiiiiiii"}, + {"Fault_Overlap", "Fault_Overlap", "i", "i"}, + {"Pyramids", "Pyramid", "i", "iiiiii"}, + {"BoundingBox", "", "", "drdr"}, + {"Body","i", "drdrdrdr"}, + {"PrivateTable", "PrivateTable", "i", "i"}, + {"Fault_BadShape", "Fault_BadShape", "i", "i"}, + {"End", "", "", ""}, + {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"}, + {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"}, + {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"}, + {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"}, + {"Tangents", "Tangent", "i", "dr"}, + {"Normals", "Normal", "i", "dr"}, + {"TangentAtVertices", "TangentAtVertex", "i", "ii"}, + {"SolAtVertices", "SolAtVertex", "i", "sr"}, + {"SolAtEdges", "SolAtEdge", "i", "sr"}, + {"SolAtTriangles", "SolAtTriangle", "i", "sr"}, + {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"}, + {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"}, + {"SolAtPrisms", "SolAtPrism", "i", "sr"}, + {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"}, + {"DSolAtVertices", "DSolAtVertex", "i", "sr"}, + {"ISolAtVertices", "ISolAtVertex", "i", "i"}, + {"ISolAtEdges", "ISolAtEdge", "i", "ii"}, + {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"}, + {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"}, + {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"}, + {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"}, + {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"}, + {"Iterations", "","","i"}, + {"Time", "","","r"}, + {"Fault_SmallTri", "Fault_SmallTri","i","i"}, + {"CoarseHexahedra", "CoarseHexahedron", "i", "i"} + }; + + +/*----------------------------------------------------------*/ +/* Prototypes of local procedures */ +/*----------------------------------------------------------*/ + +static void ScaWrd(GmfMshSct *, unsigned char *); +static void ScaDblWrd(GmfMshSct *, unsigned char *); +static void ScaBlk(GmfMshSct *, unsigned char *, int); +static long GetPos(GmfMshSct *); +static void RecWrd(GmfMshSct *, unsigned char *); +static void RecDblWrd(GmfMshSct *, unsigned char *); +static void RecBlk(GmfMshSct *, unsigned char *, int); +static void SetPos(GmfMshSct *, long); +static int ScaKwdTab(GmfMshSct *); +static void ExpFmt(GmfMshSct *, int); +static void ScaKwdHdr(GmfMshSct *, int); + + +/*----------------------------------------------------------*/ +/* Open a mesh file in read or write mod */ +/*----------------------------------------------------------*/ + +int GmfOpenMesh(const char *FilNam, int mod, ...) +{ + int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0; + char str[ GmfStrSiz ]; + va_list VarArg; + GmfMshSct *msh; + char *ptr; + int k; + + if(!GmfIniFlg) + { + for(i=0;i<=MaxMsh;i++) + GmfMshTab[i] = NULL; + + GmfIniFlg = 1; + } + + /*---------------------*/ + /* MESH STRUCTURE INIT */ + /*---------------------*/ + + for(i=1;i<=MaxMsh;i++) + if(!GmfMshTab[i]) + { + MshIdx = i; + break; + } + + if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) ) + return(0); + + /* Copy the FilNam into the structure */ + + if(strlen(FilNam) + 7 >= GmfStrSiz) + { + free (msh); + return(0); + } + + strcpy(msh->FilNam, FilNam); + + /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */ + + msh->mod = mod; + msh->buf = (unsigned char *)msh->DblBuf; + msh->FltBuf = (float *)msh->DblBuf; + msh->IntBuf = (int *)msh->DblBuf; + + k = strlen(msh->FilNam) - 6; + if(k < 0) + k = 0; + ptr = msh->FilNam+k; + if(strstr(ptr, ".meshb")) + msh->typ |= (Bin | MshFil); + else if(strstr(ptr, ".mesh")) + msh->typ |= (Asc | MshFil); + else if(strstr(ptr, ".solb")) + msh->typ |= (Bin | SolFil); + else if(strstr(ptr, ".sol")) + msh->typ |= (Asc | SolFil); + else { + free (msh); + return(0); + } + + /* Open the file in the required mod and initialyse the mesh structure */ + + if(msh->mod == GmfRead) + { + + /*-----------------------*/ + /* OPEN FILE FOR READING */ + /*-----------------------*/ + + va_start(VarArg, mod); + PtrVer = va_arg(VarArg, int *); + PtrDim = va_arg(VarArg, int *); + va_end(VarArg); + + /* Create the name string and open the file */ + + if(!(msh->hdl = fopen(msh->FilNam, "rb"))) + { + free (msh); + return(0); + } + + /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */ + + if(msh->typ & Bin) + { + fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl); + + if( (msh->cod != 1) && (msh->cod != 16777216) ) + { + free (msh); + return(0); + } + + ScaWrd(msh, (unsigned char *)&msh->ver); + + if( (msh->ver < 1) || (msh->ver > 3) ) + { + free (msh); + return(0); + } + + if( (msh->ver == 3) && (sizeof(long) == 4) ) + { + free (msh); + return(0); + } + + ScaWrd(msh, (unsigned char *)&KwdCod); + + if(KwdCod != GmfDimension) + { + free (msh); + return(0); + } + + GetPos(msh); + ScaWrd(msh, (unsigned char *)&msh->dim); + } + else + { + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") ); + + if(res == EOF) + { + free (msh); + return(0); + } + + fscanf(msh->hdl, "%d", &msh->ver); + + if( (msh->ver < 1) || (msh->ver > 3) ) + { + free (msh); + return(0); + } + + do + { + res = fscanf(msh->hdl, "%s", str); + }while( (res != EOF) && strcmp(str, "Dimension") ); + + if(res == EOF) + { + free (msh); + return(0); + } + + fscanf(msh->hdl, "%d", &msh->dim); + } + + if( (msh->dim != 2) && (msh->dim != 3) ) + { + free (msh); + return(0); + } + + (*PtrVer) = msh->ver; + (*PtrDim) = msh->dim; + + /*------------*/ + /* KW READING */ + /*------------*/ + + /* Read the list of kw present in the file */ + + if(!ScaKwdTab(msh)) + { + free (msh); + return(0); + } + + GmfMshTab[ MshIdx ] = msh; + + return(MshIdx); + } + else if(msh->mod == GmfWrite) + { + + /*-----------------------*/ + /* OPEN FILE FOR WRITING */ + /*-----------------------*/ + + msh->cod = 1; + + /* Check if the user provided a valid version number and dimension */ + + va_start(VarArg, mod); + msh->ver = va_arg(VarArg, int); + msh->dim = va_arg(VarArg, int); + va_end(VarArg); + + if( (msh->ver < 1) || (msh->ver > 3) ) + { + free (msh); + return(0); + } + + if( (msh->ver == 3) && (sizeof(long) == 4) ) + { + free (msh); + return(0); + } + + if( (msh->dim != 2) && (msh->dim != 3) ) + { + free (msh); + return(0); + } + + /* Create the mesh file */ + + if(!(msh->hdl = fopen(msh->FilNam, "wb"))) + { + free (msh); + return(0); + } + + GmfMshTab[ MshIdx ] = msh; + + + /*------------*/ + /* KW WRITING */ + /*------------*/ + + /* Write the mesh version and dimension */ + + if(msh->typ & Asc) + { + fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver); + fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim); + } + else + { + RecWrd(msh, (unsigned char *)&msh->cod); + RecWrd(msh, (unsigned char *)&msh->ver); + GmfSetKwd(MshIdx, GmfDimension, 0); + RecWrd(msh, (unsigned char *)&msh->dim); + } + + return(MshIdx); + } + else + { + free (msh); + return(0); + } +} + + +/*----------------------------------------------------------*/ +/* Close a meshfile in the right way */ +/*----------------------------------------------------------*/ + +int GmfCloseMesh(int MshIdx) +{ + int res = 1; + GmfMshSct *msh; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + RecBlk(msh, msh->buf, 0); + + /* In write down the "End" kw in write mode */ + + if(msh->mod == GmfWrite){ + if(msh->typ & Asc) + fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]); + else + GmfSetKwd(MshIdx, GmfEnd, 0); + } + /* Close the file and free the mesh structure */ + + if(fclose(msh->hdl)) + res = 0; + + free(msh); + GmfMshTab[ MshIdx ] = NULL; + + return(res); +} + + +/*----------------------------------------------------------*/ +/* Read the number of lines and set the position to this kwd*/ +/*----------------------------------------------------------*/ + +int GmfStatKwd(int MshIdx, int KwdCod, ...) +{ + int i, *PtrNmbTyp, *PtrSolSiz, *TypTab; + GmfMshSct *msh; + KwdSct *kwd; + va_list VarArg; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + if(!kwd->NmbLin) + return(0); + + /* Read further arguments if this kw is a sol */ + + if(kwd->typ == SolKwd) + { + va_start(VarArg, KwdCod); + + PtrNmbTyp = va_arg(VarArg, int *); + *PtrNmbTyp = kwd->NmbTyp; + + PtrSolSiz = va_arg(VarArg, int *); + *PtrSolSiz = kwd->SolSiz; + + TypTab = va_arg(VarArg, int *); + + for(i=0;iNmbTyp;i++) + TypTab[i] = kwd->TypTab[i]; + + va_end(VarArg); + } + + return(kwd->NmbLin); +} + + +/*----------------------------------------------------------*/ +/* Set the current file position to a given kwd */ +/*----------------------------------------------------------*/ + +int GmfGotoKwd(int MshIdx, int KwdCod) +{ + GmfMshSct *msh; + KwdSct *kwd; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + if(!kwd->NmbLin) + return(0); + + return(fseek(msh->hdl, kwd->pos, SEEK_SET)); +} + + +/*----------------------------------------------------------*/ +/* Write the kwd and set the number of lines */ +/*----------------------------------------------------------*/ + +int GmfSetKwd(int MshIdx, int KwdCod, ...) +{ + int i, NmbLin=0, *TypTab; + long CurPos; + va_list VarArg; + GmfMshSct *msh; + KwdSct *kwd; + + if( (MshIdx < 1) || (MshIdx > MaxMsh) ) + return(0); + + msh = GmfMshTab[ MshIdx ]; + RecBlk(msh, msh->buf, 0); + + if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) ) + return(0); + + kwd = &msh->KwdTab[ KwdCod ]; + + /* Read further arguments if this kw has a header */ + + if(strlen(GmfKwdFmt[ KwdCod ][2])) + { + va_start(VarArg, KwdCod); + NmbLin = va_arg(VarArg, int); + + if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr")) + { + kwd->NmbTyp = va_arg(VarArg, int); + TypTab = va_arg(VarArg, int *); + + for(i=0;iNmbTyp;i++) + kwd->TypTab[i] = TypTab[i]; + } + + va_end(VarArg); + } + + /* Setup the kwd info */ + + ExpFmt(msh, KwdCod); + + if(!kwd->typ) + return(0); + else if(kwd->typ == InfKwd) + kwd->NmbLin = 1; + else + kwd->NmbLin = NmbLin; + + /* Store the next kwd position in binary file */ + + if( (msh->typ & Bin) && msh->NexKwdPos ) + { + CurPos = ftell(msh->hdl); + fseek(msh->hdl, msh->NexKwdPos, SEEK_SET); + SetPos(msh, CurPos); + fseek(msh->hdl, CurPos, SEEK_SET); + } + + /* Write the header */ + + if(msh->typ & Asc) + { + fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]); + + if(kwd->typ != InfKwd) + fprintf(msh->hdl, "%d\n", kwd->NmbLin); + + /* In case of solution field, write the extended header */ + + if(kwd->typ == SolKwd) + { + fprintf(msh->hdl, "%d ", kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + fprintf(msh->hdl, "%d ", kwd->TypTab[i]); + + fprintf(msh->hdl, "\n\n"); + } + } + else + { + RecWrd(msh, (unsigned char *)&KwdCod); + msh->NexKwdPos = ftell(msh->hdl); + SetPos(msh, 0); + + if(kwd->typ != InfKwd) + RecWrd(msh, (unsigned char *)&kwd->NmbLin); + + /* In case of solution field, write the extended header at once */ + + if(kwd->typ == SolKwd) + { + RecWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + RecWrd(msh, (unsigned char *)&kwd->TypTab[i]); + } + } + + /* Reset write buffer position */ + msh->pos = 0; + + /* Estimate the total file size and check whether it crosses the 2GB threshold */ + + msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz; + + if(msh->siz > 2E9) + return(0); + else + return(kwd->NmbLin); +} + + +/*----------------------------------------------------------*/ +/* Read a full line from the current kwd */ +/*----------------------------------------------------------*/ + +void GmfGetLin(int MshIdx, int KwdCod, ...) +{ + int i, j; + float *FltSolTab; + double *DblSolTab; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + + if(kwd->typ != SolKwd) + { + int k, nb_repeat = 0; + + if(msh->ver == 1) + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fscanf(msh->hdl, "%f", va_arg(VarArg, float *)); + else if(kwd->fmt[i] == 'n') { + fscanf(msh->hdl, "%d", &nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;khdl, "%d", va_arg(VarArg, int *)); + } + else + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *)); + else if(kwd->fmt[i] == 'n') { + ScaWrd(msh, (unsigned char *)&nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;ktyp & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fscanf(msh->hdl, "%lf", va_arg(VarArg, double *)); + else if(kwd->fmt[i] == 'n') { + fscanf(msh->hdl, "%d", &nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;khdl, "%d", va_arg(VarArg, int *)); + } + else + fscanf(msh->hdl, "%d", va_arg(VarArg, int *)); + } + else + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *)); + else if(kwd->fmt[i] == 'n') { + ScaWrd(msh, (unsigned char *)&nb_repeat); + *(va_arg(VarArg, int *)) = nb_repeat; + for(k=0;kver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fscanf(msh->hdl, "%f", &FltSolTab[j]); + else + ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd); + } + else + { + DblSolTab = va_arg(VarArg, double *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fscanf(msh->hdl, "%lf", &DblSolTab[j]); + else + for(j=0;jSolSiz;j++) + ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]); + } + } + + va_end(VarArg); +} + + +/*----------------------------------------------------------*/ +/* Write a full line from the current kwd */ +/*----------------------------------------------------------*/ + +void GmfSetLin(int MshIdx, int KwdCod, ...) +{ + int i, j, pos, *IntBuf; + float *FltSolTab; + double *DblSolTab, *DblBuf; + va_list VarArg; + GmfMshSct *msh = GmfMshTab[ MshIdx ]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Start decoding the arguments */ + + va_start(VarArg, KwdCod); + + if(kwd->typ != SolKwd) + { + int k, nb_repeat = 0; + + if(msh->ver == 1) + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double)); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + fprintf(msh->hdl, "%d ", nb_repeat); + for(k=0;khdl, "%d ", va_arg(VarArg, int)); + } + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + int size_of_block = kwd->SolSiz; + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + msh->FltBuf[i] = va_arg(VarArg, double); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + msh->FltBuf[i] = nb_repeat; + for(k=0;kIntBuf[i+1+k] = va_arg(VarArg, int); + size_of_block ++; + } + } + else + msh->IntBuf[i] = va_arg(VarArg, int); + + RecBlk(msh, msh->buf, size_of_block); + } + } + else + { + if(msh->typ & Asc) + { + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double)); + else if(kwd->fmt[i] == 'n') { + nb_repeat = va_arg(VarArg, int); + fprintf(msh->hdl, "%d ", nb_repeat); + for(k=0;khdl, "%d ", va_arg(VarArg, int)); + } + else + fprintf(msh->hdl, "%d ", va_arg(VarArg, int)); + } + else + { + pos = 0; + + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'r') + { + DblBuf = (double *)&msh->buf[ pos ]; + *DblBuf = va_arg(VarArg, double); + pos += 8; + } + else if(kwd->fmt[i] == 'n') + { + IntBuf = (int *)&msh->buf[ pos ]; + nb_repeat = va_arg(VarArg, int); + *IntBuf = nb_repeat; + pos += 4; + for(k=0;kbuf[ pos ]; + *IntBuf = va_arg(VarArg, int); + pos += 4; + } + } + else + { + IntBuf = (int *)&msh->buf[ pos ]; + *IntBuf = va_arg(VarArg, int); + pos += 4; + } + RecBlk(msh, msh->buf, pos/4); + } + } + } + else + { + if(msh->ver == 1) + { + FltSolTab = va_arg(VarArg, float *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fprintf(msh->hdl, "%g ", FltSolTab[j]); + else + RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd); + } + else + { + DblSolTab = va_arg(VarArg, double *); + + if(msh->typ & Asc) + for(j=0;jSolSiz;j++) + fprintf(msh->hdl, "%.15lg ", DblSolTab[j]); + else + RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd); + } + } + + va_end(VarArg); + + if(msh->typ & Asc) + fprintf(msh->hdl, "\n"); +} + + +/*----------------------------------------------------------*/ +/* Private procedure for transmesh : copy a whole line */ +/*----------------------------------------------------------*/ + +void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod) +{ + double d; + float f; + int i, a; + GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ]; + KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ]; + + for(i=0;iSolSiz;i++) + { + if(kwd->fmt[i] == 'r') + { + if(InpMsh->ver == 1) + { + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%f", &f); + else + ScaWrd(InpMsh, (unsigned char *)&f); + + d = f; + } + else + { + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%lf", &d); + else + ScaDblWrd(InpMsh, (unsigned char *)&d); + + f = (float)d; + } + + if(OutMsh->ver == 1) + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%g ", f); + else + RecWrd(OutMsh, (unsigned char *)&f); + else + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%.15g ", d); + else + RecDblWrd(OutMsh, (unsigned char *)&d); + } + else if(kwd->fmt[i] == 'n') + { + int k, nb_repeat = 0; + + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + nb_repeat = a; + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + + for(k=0;ktyp & Asc) + fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + } + } + else + { + if(InpMsh->typ & Asc) + fscanf(InpMsh->hdl, "%d", &a); + else + ScaWrd(InpMsh, (unsigned char *)&a); + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "%d ", a); + else + RecWrd(OutMsh, (unsigned char *)&a); + } + } + + if(OutMsh->typ & Asc) + fprintf(OutMsh->hdl, "\n"); +} + + +/*----------------------------------------------------------*/ +/* Find every kw present in a meshfile */ +/*----------------------------------------------------------*/ + +static int ScaKwdTab(GmfMshSct *msh) +{ + int KwdCod; + long NexPos, CurPos, EndPos; + char str[ GmfStrSiz ]; + + if(msh->typ & Asc) + { + /* Scan each string in the file until the end */ + + while(fscanf(msh->hdl, "%s", str) != EOF) + { + /* Fast test in order to reject quickly the numeric values */ + + if(isalpha(str[0])) + { + /* Search which kwd code this string is associated with, + then get its header and save the curent position in file (just before the data) */ + + for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++) + if(!strcmp(str, GmfKwdFmt[ KwdCod ][0])) + { + ScaKwdHdr(msh, KwdCod); + break; + } + } + else if(str[0] == '#') + while(fgetc(msh->hdl) != '\n'); + } + } + else + { + /* Get file size */ + + CurPos = ftell(msh->hdl); + fseek(msh->hdl, 0, SEEK_END); + EndPos = ftell(msh->hdl); + fseek(msh->hdl, CurPos, SEEK_SET); + + /* Jump through kwd positions in the file */ + + do + { + /* Get the kwd code and the next kwd position */ + + ScaWrd(msh, (unsigned char *)&KwdCod); + NexPos = GetPos(msh); + + if(NexPos > EndPos) + return(0); + + /* Check if this kwd belongs to this mesh version */ + + if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) ) + ScaKwdHdr(msh, KwdCod); + + /* Go to the next kwd */ + + if(NexPos) + fseek(msh->hdl, NexPos, SEEK_SET); + }while(NexPos && (KwdCod != GmfEnd)); + } + + return(1); +} + + +/*----------------------------------------------------------*/ +/* Read and setup the keyword's header */ +/*----------------------------------------------------------*/ + +static void ScaKwdHdr(GmfMshSct *msh, int KwdCod) +{ + int i; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + if(!strcmp("i", GmfKwdFmt[ KwdCod ][2])) + { + if(msh->typ & Asc) + fscanf(msh->hdl, "%d", &kwd->NmbLin); + else + ScaWrd(msh, (unsigned char *)&kwd->NmbLin); + } + else + kwd->NmbLin = 1; + + if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3])) + { + if(msh->typ & Asc) + { + fscanf(msh->hdl, "%d", &kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + fscanf(msh->hdl, "%d", &kwd->TypTab[i]); + } + else + { + ScaWrd(msh, (unsigned char *)&kwd->NmbTyp); + + for(i=0;iNmbTyp;i++) + ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]); + } + } + + ExpFmt(msh, KwdCod); + kwd->pos = ftell(msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Expand the compacted format and compute the line size */ +/*----------------------------------------------------------*/ + +static void ExpFmt(GmfMshSct *msh, int KwdCod) +{ + int i, j, TmpSiz=0; + char chr; + const char *InpFmt = GmfKwdFmt[ KwdCod ][3]; + KwdSct *kwd = &msh->KwdTab[ KwdCod ]; + + /* Set the kwd's type */ + + if(!strlen(GmfKwdFmt[ KwdCod ][2])) + kwd->typ = InfKwd; + else if(!strcmp(InpFmt, "sr")) + kwd->typ = SolKwd; + else + kwd->typ = RegKwd; + + /* Get the solution-field's size */ + + if(kwd->typ == SolKwd) + for(i=0;iNmbTyp;i++) + switch(kwd->TypTab[i]) + { + case GmfSca : TmpSiz += 1; break; + case GmfVec : TmpSiz += msh->dim; break; + case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break; + case GmfMat : TmpSiz += msh->dim * msh->dim; break; + } + + /* Scan each character from the format string */ + + i = kwd->SolSiz = kwd->NmbWrd = 0; + + while(i < strlen(InpFmt)) + { + chr = InpFmt[ i++ ]; + + if(chr == 'd') + { + chr = InpFmt[i++]; + + for(j=0;jdim;j++) + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + else if(chr == 's') + { + chr = InpFmt[i++]; + + for(j=0;jfmt[ kwd->SolSiz++ ] = chr; + } + else + kwd->fmt[ kwd->SolSiz++ ] = chr; + } + + for(i=0;iSolSiz;i++) + if(kwd->fmt[i] == 'i') + kwd->NmbWrd++; + else if(msh->ver >= 2) + kwd->NmbWrd += 2; + else + kwd->NmbWrd++; +} + + +/*----------------------------------------------------------*/ +/* Read a four bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaWrd(GmfMshSct *msh, unsigned char *wrd) +{ + unsigned char swp; + + fread(wrd, WrdSiz, 1, msh->hdl); + + if(msh->cod == 1) + return; + + swp = wrd[3]; + wrd[3] = wrd[0]; + wrd[0] = swp; + + swp = wrd[2]; + wrd[2] = wrd[1]; + wrd[1] = swp; +} + + +/*----------------------------------------------------------*/ +/* Read an eight bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd) +{ + int i; + unsigned char swp; + + fread(wrd, WrdSiz, 2, msh->hdl); + + if(msh->cod == 1) + return; + + for(i=0;i<4;i++) + { + swp = wrd[7-i]; + wrd[7-i] = wrd[i]; + wrd[i] = swp; + } +} + + +/*----------------------------------------------------------*/ +/* Read ablock of four bytes word from a mesh file */ +/*----------------------------------------------------------*/ + +static void ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz) +{ + int i, j; + unsigned char swp, *wrd; + + fread(blk, WrdSiz, siz, msh->hdl); + + if(msh->cod == 1) + return; + + for(i=0;iver >= 3) + ScaDblWrd(msh, (unsigned char*)&pos); + else + { + ScaWrd(msh, (unsigned char*)&IntVal); + pos = IntVal; + } + + return(pos); +} + + +/*----------------------------------------------------------*/ +/* Write a four bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecWrd(GmfMshSct *msh, unsigned char *wrd) +{ + fwrite(wrd, WrdSiz, 1, msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Write an eight bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd) +{ + fwrite(wrd, WrdSiz, 2, msh->hdl); +} + + +/*----------------------------------------------------------*/ +/* Write a block of four bytes word to a mesh file */ +/*----------------------------------------------------------*/ + +static void RecBlk(GmfMshSct *msh, unsigned char *blk, int siz) +{ + /* Copy this line-block into the main mesh buffer */ + + if(siz) + { + memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz); + msh->pos += siz * WrdSiz; + } + + /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */ + + if( (msh->pos > BufSiz) || (!siz && msh->pos) ) + { + fwrite(msh->blk, 1, msh->pos, msh->hdl); + msh->pos = 0; + } +} + + +/*----------------------------------------------------------*/ +/* Write a 4 or 8 bytes position in a mesh file */ +/*----------------------------------------------------------*/ + +static void SetPos(GmfMshSct *msh, long pos) +{ + int IntVal; + + if(msh->ver >= 3) + RecDblWrd(msh, (unsigned char*)&pos); + else + { + IntVal = pos; + RecWrd(msh, (unsigned char*)&IntVal); + } +} diff --git a/src/DriverGMF/libmesh5.h b/src/DriverGMF/libmesh5.h new file mode 100644 index 000000000..eddf200e9 --- /dev/null +++ b/src/DriverGMF/libmesh5.h @@ -0,0 +1,153 @@ + + +/*----------------------------------------------------------*/ +/* */ +/* LIBMESH V 5.46 */ +/* */ +/*----------------------------------------------------------*/ +/* */ +/* Description: handle .meshb file format I/O */ +/* Author: Loic MARECHAL */ +/* Creation date: feb 16 2007 */ +/* Last modification: dec 09 2011 */ +/* */ +/*----------------------------------------------------------*/ + + +/*----------------------------------------------------------*/ +/* Defines */ +/*----------------------------------------------------------*/ + +#define GmfStrSiz 1024 +#define GmfMaxTyp 1000 +#define GmfMaxKwd 80 +#define GmfMshVer 1 +#define GmfRead 1 +#define GmfWrite 2 +#define GmfSca 1 +#define GmfVec 2 +#define GmfSymMat 3 +#define GmfMat 4 +#define GmfFloat 1 +#define GmfDouble 2 + +enum GmfKwdCod +{ + GmfReserved1, \ + GmfVersionFormatted, \ + GmfReserved2, \ + GmfDimension, \ + GmfVertices, \ + GmfEdges, \ + GmfTriangles, \ + GmfQuadrilaterals, \ + GmfTetrahedra, \ + GmfPrisms, \ + GmfHexahedra, \ + GmfIterationsAll, \ + GmfTimesAll, \ + GmfCorners, \ + GmfRidges, \ + GmfRequiredVertices, \ + GmfRequiredEdges, \ + GmfRequiredTriangles, \ + GmfRequiredQuadrilaterals, \ + GmfTangentAtEdgeVertices, \ + GmfNormalAtVertices, \ + GmfNormalAtTriangleVertices, \ + GmfNormalAtQuadrilateralVertices, \ + GmfAngleOfCornerBound, \ + GmfTrianglesP2, \ + GmfEdgesP2, \ + GmfSolAtPyramids, \ + GmfQuadrilateralsQ2, \ + GmfISolAtPyramids, \ + GmfSubDomainFromGeom, \ + GmfTetrahedraP2, \ + GmfFault_NearTri, \ + GmfFault_Inter, \ + GmfHexahedraQ2, \ + GmfExtraVerticesAtEdges, \ + GmfExtraVerticesAtTriangles, \ + GmfExtraVerticesAtQuadrilaterals, \ + GmfExtraVerticesAtTetrahedra, \ + GmfExtraVerticesAtPrisms, \ + GmfExtraVerticesAtHexahedra, \ + GmfVerticesOnGeometricVertices, \ + GmfVerticesOnGeometricEdges, \ + GmfVerticesOnGeometricTriangles, \ + GmfVerticesOnGeometricQuadrilaterals, \ + GmfEdgesOnGeometricEdges, \ + GmfFault_FreeEdge, \ + GmfPolyhedra, \ + GmfPolygons, \ + GmfFault_Overlap, \ + GmfPyramids, \ + GmfBoundingBox, \ + GmfBody, \ + GmfPrivateTable, \ + GmfFault_BadShape, \ + GmfEnd, \ + GmfTrianglesOnGeometricTriangles, \ + GmfTrianglesOnGeometricQuadrilaterals, \ + GmfQuadrilateralsOnGeometricTriangles, \ + GmfQuadrilateralsOnGeometricQuadrilaterals, \ + GmfTangents, \ + GmfNormals, \ + GmfTangentAtVertices, \ + GmfSolAtVertices, \ + GmfSolAtEdges, \ + GmfSolAtTriangles, \ + GmfSolAtQuadrilaterals, \ + GmfSolAtTetrahedra, \ + GmfSolAtPrisms, \ + GmfSolAtHexahedra, \ + GmfDSolAtVertices, \ + GmfISolAtVertices, \ + GmfISolAtEdges, \ + GmfISolAtTriangles, \ + GmfISolAtQuadrilaterals, \ + GmfISolAtTetrahedra, \ + GmfISolAtPrisms, \ + GmfISolAtHexahedra, \ + GmfIterations, \ + GmfTime, \ + GmfFault_SmallTri, \ + GmfCoarseHexahedra +}; + + +/*----------------------------------------------------------*/ +/* External procedures */ +/*----------------------------------------------------------*/ + +extern int GmfOpenMesh(const char *, int, ...); +extern int GmfCloseMesh(int); +extern int GmfStatKwd(int, int, ...); +extern int GmfGotoKwd(int, int); +extern int GmfSetKwd(int, int, ...); +extern void GmfGetLin(int, int, ...); +extern void GmfSetLin(int, int, ...); + + +/*----------------------------------------------------------*/ +/* Fortran 77 API */ +/*----------------------------------------------------------*/ + +#if defined(F77_NO_UNDER_SCORE) +#define call(x) x +#else +#define call(x) x ## _ +#endif + + +/*----------------------------------------------------------*/ +/* Transmesh private API */ +/*----------------------------------------------------------*/ + +#ifdef TRANSMESH + +extern char *GmfKwdFmt[ GmfMaxKwd + 1 ][4]; +extern int GmfCpyLin(int, int, int); + +#endif