in string file,
in boolean overwrite,
in boolean groupElemsByType) raises (SALOME::SALOME_Exception);
+ void ExportStructuredCGNS( in SMESH_IDSource meshPart,
+ in string file,
+ in boolean overwrite) raises (SALOME::SALOME_Exception);
void ExportGMF( in SMESH_IDSource meshPart,
in string file,
in boolean withRequiredGroups) raises (SALOME::SALOME_Exception);
SET(MeshDriverCGNS_HEADERS
DriverCGNS_Read.hxx
DriverCGNS_Write.hxx
+ DriverStructuredCGNS_Write.hxx
SMESH_DriverCGNS.hxx
)
SET(MeshDriverCGNS_SOURCES
DriverCGNS_Read.cxx
DriverCGNS_Write.cxx
+ DriverStructuredCGNS_Write.cxx
)
# --- rules ---
--- /dev/null
+// Copyright (C) 2016-2024 CEA, EDF
+//
+// 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, or (at your option) any later version.
+//
+// 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 : DriverStructuredCGNS_Write.cxx
+// Created : Tuesday March 19 2024
+// Author : Cesar Conopoima (cce)
+
+#include "DriverStructuredCGNS_Write.hxx"
+
+#include "SMDS_IteratorOnIterators.hxx"
+#include "SMDS_MeshNode.hxx"
+#include "SMDS_VolumeTool.hxx"
+#include "SMESHDS_GroupBase.hxx"
+#include "SMESHDS_GroupOnGeom.hxx"
+#include "SMESHDS_Mesh.hxx"
+#include "SMESH_Block.hxx"
+#include "SMESH_Comment.hxx"
+
+#include <TopoDS_Solid.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_DataMapOfShapeReal.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+//CAS
+#include <BRep_Tool.hxx>
+
+// CGNS
+#include <cgnslib.h>
+
+#if CGNS_VERSION < 3100
+# define cgsize_t int
+#endif
+
+
+std::string DriverStructuredCGNS_Write::GetGroupName( const int shapeToIndex, int dim )
+{
+ auto groupBase = myMesh->GetGroups();
+ for( auto grp : groupBase )
+ {
+ /*associate the group based on geometry*/
+ if ( dynamic_cast<SMESHDS_GroupOnGeom*>( grp ))
+ {
+ SMESHDS_GroupOnGeom * geomGrp = dynamic_cast<SMESHDS_GroupOnGeom*>( grp );
+ TopoDS_Shape shape = geomGrp->GetShape();
+ if( myMesh->ShapeToIndex(shape) == shapeToIndex )
+ return std::string(geomGrp->GetStoreName());
+
+ if ( dim==3 && (shape.ShapeType() == TopAbs_COMPSOLID || shape.ShapeType() == TopAbs_COMPOUND ))
+ {
+ for ( TopExp_Explorer fEx( shape, TopAbs_SOLID ); fEx.More(); fEx.Next() )
+ {
+ if( myMesh->ShapeToIndex(fEx.Current()) == shapeToIndex )
+ return std::string(geomGrp->GetStoreName());
+ }
+ }
+
+ if ( dim==2 && (shape.ShapeType() == TopAbs_SHELL || shape.ShapeType() == TopAbs_COMPOUND) )
+ {
+ for ( TopExp_Explorer fEx( shape, TopAbs_FACE, TopAbs_SOLID ); fEx.More(); fEx.Next() )
+ {
+ if( myMesh->ShapeToIndex(fEx.Current()) == shapeToIndex )
+ return std::string(geomGrp->GetStoreName());
+ }
+ }
+ }
+ }
+ return std::string("");
+}
+
+void DriverStructuredCGNS_Write::CheckForGroupNameOnFaceInterfaces( const SMESHUtils::SMESH_RegularGrid* grid, std::vector<std::string>& boundaryNames )
+{
+ auto groupBase = myMesh->GetGroups();
+ for( auto grp : groupBase )
+ {
+ if ( dynamic_cast<SMESHDS_GroupOnGeom*>( grp ) )
+ {
+ SMESHDS_GroupOnGeom * geomGrp = dynamic_cast<SMESHDS_GroupOnGeom*>( grp );
+ TopoDS_Shape shape = geomGrp->GetShape();
+ if( shape.ShapeType() == TopAbs_FACE )
+ {
+ SMESHUtils::SMESH_RegularGrid::FaceType f = grid->getFaceTypeByGeomFace( shape );
+ if ( f != SMESHUtils::SMESH_RegularGrid::B_NONE )
+ boundaryNames[ int(f) ] = geomGrp->GetStoreName();
+ }
+
+ if ( shape.ShapeType() == TopAbs_SHELL || shape.ShapeType() == TopAbs_COMPOUND )
+ {
+ for ( TopExp_Explorer fEx( shape, TopAbs_FACE, TopAbs_SOLID ); fEx.More(); fEx.Next() )
+ {
+ SMESHUtils::SMESH_RegularGrid::FaceType f = grid->getFaceTypeByGeomFace( fEx.Current() );
+ if ( f != SMESHUtils::SMESH_RegularGrid::B_NONE )
+ boundaryNames[ int(f) ] = geomGrp->GetStoreName();
+ }
+ }
+ }
+ }
+}
+
+void DriverStructuredCGNS_Write::CheckForGroupNameOnEdgeInterfaces( const SMESHUtils::SMESH_RegularGrid* grid, std::vector<std::string>& boundaryNames )
+{
+ auto groupBase = myMesh->GetGroups();
+ for( auto grp : groupBase )
+ {
+ if ( dynamic_cast<SMESHDS_GroupOnGeom*>( grp ) )
+ {
+ SMESHDS_GroupOnGeom * geomGrp = dynamic_cast<SMESHDS_GroupOnGeom*>( grp );
+ TopoDS_Shape shape = geomGrp->GetShape();
+ if( shape.ShapeType() == TopAbs_EDGE )
+ {
+ SMESHUtils::SMESH_RegularGrid::EdgeType e = grid->getEdgeTypeByGeomEdge( shape );
+ if ( e != SMESHUtils::SMESH_RegularGrid::NONE )
+ boundaryNames[ int(e) ] = geomGrp->GetStoreName();
+ }
+
+ if ( shape.ShapeType() == TopAbs_COMPOUND )
+ {
+ for ( TopExp_Explorer fEx( shape, TopAbs_EDGE ); fEx.More(); fEx.Next() )
+ {
+ SMESHUtils::SMESH_RegularGrid::EdgeType e = grid->getEdgeTypeByGeomEdge( fEx.Current() );
+ if ( e != SMESHUtils::SMESH_RegularGrid::NONE )
+ boundaryNames[ int(e) ] = geomGrp->GetStoreName();
+ }
+ }
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Write the mesh into the CGNS file
+ */
+//================================================================================
+
+Driver_Mesh::Status DriverStructuredCGNS_Write::Perform()
+{
+ myErrorMessages.clear();
+
+ if ( !myMesh || myMesh->GetMeshInfo().NbElements() < 1 )
+ return addMessage( !myMesh ? "NULL mesh" : "Empty mesh (no elements)", /*fatal = */true );
+
+ if ( Driver_Mesh::IsMeshTooLarge< cgsize_t >( myMesh, /*checkIDs =*/ false))
+ return DRS_TOO_LARGE_MESH;
+
+ // open the file
+ if ( cg_open(myFile.c_str(), CG_MODE_MODIFY, &_fn) != CG_OK &&
+ cg_open(myFile.c_str(), CG_MODE_WRITE, &_fn) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // create a Base
+ // --------------
+
+ const int spaceDim = 3;
+ int meshDim = 1;
+ if ( myMesh->NbFaces() > 0 ) meshDim = 2;
+ if ( myMesh->NbVolumes() > 0 ) meshDim = 3;
+
+ if ( myMeshName.empty() )
+ {
+ int nbases = 0;
+ if ( cg_nbases( _fn, &nbases) == CG_OK )
+ myMeshName = ( SMESH_Comment("Base_") << nbases+1 );
+ else
+ myMeshName = "Base_0";
+ }
+ int iBase;
+ if ( cg_base_write( _fn, myMeshName.c_str(), meshDim, spaceDim, &iBase ) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ if ( cg_goto(_fn, iBase, "end") != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ if ( cg_descriptor_write("About", "Created by SMESH") != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // create a structured Zone
+ // --------------
+
+ TopoDS_Shape shape = myMesh->ShapeToMesh();
+
+ if ( meshDim == 3 )
+ {
+ std::set<std::string> zNames;
+ for ( TopExp_Explorer fEx( shape, TopAbs_SOLID ); fEx.More(); fEx.Next() )
+ {
+ TopoDS_Solid currentSolid = TopoDS::Solid(fEx.Current());
+
+ if ( myMesh->HasStructuredGridFilled(currentSolid) )
+ {
+ auto grid = myMesh->GetTheGrid(currentSolid).get();
+ int imax = grid->nx();
+ int jmax = grid->ny();
+ int kmax = grid->nz();
+
+ cgsize_t size[9] = {imax, jmax, kmax, imax - 1, jmax - 1, kmax - 1, 0, 0, 0};
+
+ std::string zoneName = GetGroupName(myMesh->ShapeToIndex(currentSolid),meshDim);
+ zoneName = zoneName.empty() ? "ZONESOLID" + std::to_string(myMesh->ShapeToIndex(currentSolid)) : zoneName;
+ if ( zNames.count(zoneName) != 0 )
+ zoneName = zoneName + "_" + std::to_string(myMesh->ShapeToIndex(currentSolid));
+ zNames.insert( zoneName );
+ // write Zone
+ int iZone;
+ if(cg_zone_write(_fn, iBase, zoneName.c_str(), size,
+ CGNS_ENUMV(Structured), &iZone) != CG_OK)
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write Grid
+ int iGrid=0;
+ if(cg_grid_write(_fn, iBase, iZone, "GridCoordinates", &iGrid) != CG_OK)
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write the Coordinates
+ std::vector< double > coords( grid->Size() /*nx*ny*nz*/);
+ // write X-Coordinates
+ auto coordIter = grid->CoordinateBegin();
+ for ( int i = 0; i < grid->Size(); coordIter.Next(), i++ )
+ coords[i] = coordIter.Value()->X();
+
+ if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble),
+ "CoordinateX", &coords[0], &iGrid) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write Y-Coordinates
+ coordIter = grid->CoordinateBegin();
+ for ( int i = 0; i < grid->Size(); coordIter.Next(), i++ )
+ coords[i] = coordIter.Value()->Y();
+
+ if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble),
+ "CoordinateY", &coords[0], &iGrid) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write Z-Coordinates
+ coordIter = grid->CoordinateBegin();
+ for ( int i = 0; i < grid->Size(); coordIter.Next(), i++ )
+ coords[i] = coordIter.Value()->Z();
+
+ if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble),
+ "CoordinateZ", &coords[0], &iGrid) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+ //end write Coordinates
+
+ // Write Boundary condition for the grid faces
+ std::vector<std::vector<cgsize_t>> allRanges;
+ std::vector<std::string> boundaryNames(6,"");
+ grid->getAllFaceIndexLimits( allRanges );
+ CheckForGroupNameOnFaceInterfaces(grid,boundaryNames);
+
+ int faceId = 0;
+ std::set<std::string> bNames;
+ for (auto pRange : allRanges)
+ {
+ if(pRange[3] < pRange[0]) {std::swap(pRange[0],pRange[3]);}
+ if(pRange[4] < pRange[1]) {std::swap(pRange[1],pRange[4]);}
+ if(pRange[5] < pRange[2]) {std::swap(pRange[2],pRange[5]);}
+ int cgIndexBoco = 0;
+ std::string boundaryName = boundaryNames[faceId].empty() ? zoneName + "_" + std::to_string(faceId) : boundaryNames[faceId];
+ if ( bNames.count(boundaryName)!=0 )
+ boundaryName = boundaryName + "_" + std::to_string(faceId);
+ bNames.insert( boundaryName );
+ if(cg_boco_write(_fn, iBase, iZone, boundaryName.c_str(), CGNS_ENUMV(BCTypeNull),
+ CGNS_ENUMV(PointRange), 2, &pRange[0], &cgIndexBoco) != CG_OK) return addMessage(cg_get_error(), /*fatal = */true);
+ faceId++;
+ }
+ // End write boundary
+
+ // Writte Interfaces
+ for ( TopExp_Explorer fEx( shape, TopAbs_SOLID ); fEx.More(); fEx.Next() )
+ {
+ TopoDS_Solid neighbourSolid = TopoDS::Solid(fEx.Current());
+ if ( !currentSolid.IsSame( neighbourSolid ) && myMesh->HasStructuredGridFilled(neighbourSolid))
+ {
+ std::vector<int> interface;
+ grid->GetFaceInterfaces(myMesh->GetTheGrid(neighbourSolid).get(), interface);
+ if ( !interface.empty() )
+ {
+ int iConn;
+ std::string neigbourZoneName = GetGroupName(myMesh->ShapeToIndex(neighbourSolid),meshDim);
+ neigbourZoneName = neigbourZoneName.empty() ? "ZONESOLID" + std::to_string(myMesh->ShapeToIndex(neighbourSolid)) : neigbourZoneName;
+ std::string interfaceName = zoneName + "_" + neigbourZoneName + "_" + std::to_string(interface[0]);
+ if(cg_1to1_write(_fn, iBase, iZone, interfaceName.c_str(), neigbourZoneName.c_str(),
+ &interface[1], &interface[7], &interface[13], &iConn) != CG_OK) return addMessage(cg_get_error(), /*fatal = */true);
+ }
+
+ }
+ }
+ }
+ }
+ }
+ else if ( meshDim == 2 )
+ {
+ std::set<std::string> zNames;
+ for ( TopExp_Explorer fEx( shape, TopAbs_FACE ); fEx.More(); fEx.Next() )
+ {
+ TopoDS_Face currentFace = TopoDS::Face(fEx.Current());
+
+ if ( myMesh->HasStructuredGridFilled(currentFace) )
+ {
+ auto grid = myMesh->GetTheGrid(currentFace).get();
+ int imax = grid->nx();
+ int jmax = grid->ny();
+ int iZone;
+ cgsize_t size[6] = {imax, jmax, imax - 1, jmax - 1, 0, 0};
+
+ std::string zoneName = GetGroupName(myMesh->ShapeToIndex(currentFace),meshDim);
+ zoneName = zoneName.empty() ? "ZONEFACE" + std::to_string(myMesh->ShapeToIndex(currentFace)) : zoneName;
+
+ if ( zNames.count(zoneName) != 0 )
+ zoneName = zoneName + "_" + std::to_string(myMesh->ShapeToIndex(currentFace));
+ zNames.insert( zoneName );
+ // write Zone
+ if(cg_zone_write(_fn, iBase, zoneName.c_str(), size,
+ CGNS_ENUMV(Structured), &iZone) != CG_OK)
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write Grid
+ int iGrid;
+ if(cg_grid_write(_fn, iBase, iZone, "GridCoordinates", &iGrid) != CG_OK)
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write the Coordinates
+ std::vector< double > coords( grid->Size() /*nx*ny*nz*/);
+
+ // write X-Coordinates
+ auto coordIter = grid->CoordinateBegin();
+ for ( int i = 0; i < grid->Size(); coordIter.Next(), i++ )
+ coords[i] = coordIter.Value()->X();
+
+ if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble),
+ "CoordinateX", &coords[0], &iGrid) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write Y-Coordinates
+ coordIter = grid->CoordinateBegin();
+ for ( int i = 0; i < grid->Size(); coordIter.Next(), i++ )
+ coords[i] = coordIter.Value()->Y();
+
+ if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble),
+ "CoordinateY", &coords[0], &iGrid) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ // write Z-Coordinates
+ coordIter = grid->CoordinateBegin();
+ for ( int i = 0; i < grid->Size(); coordIter.Next(), i++ )
+ coords[i] = coordIter.Value()->Z();
+
+ if ( cg_coord_write( _fn, iBase, iZone, CGNS_ENUMV(RealDouble),
+ "CoordinateZ", &coords[0], &iGrid) != CG_OK )
+ return addMessage( cg_get_error(), /*fatal = */true );
+
+ //End write Coordinates
+
+ // Write Boundary condition for the grid edges
+ std::vector<std::vector<cgsize_t>> allRanges;
+ std::vector<std::string> boundaryNames(4,"");
+ grid->getAllEdgeIndexLimits( allRanges );
+ CheckForGroupNameOnEdgeInterfaces(grid,boundaryNames);
+ int edgeId = 0;
+ std::set<std::string> bNames;
+ for (auto pRange : allRanges)
+ {
+ if(pRange[2] < pRange[0]) {std::swap(pRange[0],pRange[2]);}
+ if(pRange[1] < pRange[3]) {std::swap(pRange[1],pRange[3]);}
+ int cgIndexBoco = 0;
+ std::string boundaryName = boundaryNames[edgeId].empty() ? zoneName + "_" + std::to_string(edgeId) : boundaryNames[edgeId];
+ if ( bNames.count(boundaryName)!=0)
+ boundaryName = boundaryName + "_" + std::to_string(edgeId);
+ bNames.insert( boundaryName );
+ if(cg_boco_write(_fn, iBase, iZone, boundaryName.c_str(), CGNS_ENUMV(BCTypeNull),
+ CGNS_ENUMV(PointRange), 2, &pRange[0], &cgIndexBoco) != CG_OK) return addMessage(cg_get_error(), /*fatal = */true);
+ edgeId++;
+ }
+ // End write Boundary
+
+ // Writte Interfaces
+ for ( TopExp_Explorer fEx( shape, TopAbs_FACE ); fEx.More(); fEx.Next() )
+ {
+ TopoDS_Face neighbourFace = TopoDS::Face(fEx.Current());
+ if ( !currentFace.IsSame( neighbourFace ) && myMesh->HasStructuredGridFilled(neighbourFace) )
+ {
+ std::vector<int> interface;
+ grid->GetEdgeInterfaces(myMesh->GetTheGrid(neighbourFace).get(), interface);
+
+ if ( !interface.empty() )
+ {
+ int iConn;
+ std::string neigbourZoneName = GetGroupName(myMesh->ShapeToIndex(neighbourFace),meshDim);
+ neigbourZoneName = neigbourZoneName.empty() ? "ZONEFACE" + std::to_string(myMesh->ShapeToIndex(neighbourFace)) : neigbourZoneName;
+ std::string interfaceName = zoneName + "_" + neigbourZoneName + "_" + std::to_string(interface[0]);
+ if(cg_1to1_write(_fn, iBase, iZone, interfaceName.c_str(), neigbourZoneName.c_str(),
+ &interface[1], &interface[5], &interface[9], &iConn) != CG_OK) return addMessage(cg_get_error(), /*fatal = */true);
+
+ }
+ }
+ }
+ } /*end if grid filled*/
+ } /*foreach face*/
+ }
+
+ return DRS_OK;
+}
+
+//================================================================================
+/*!
+ * \brief Constructor
+ */
+//================================================================================
+
+DriverStructuredCGNS_Write::DriverStructuredCGNS_Write(): _fn(0)
+{
+}
+
+//================================================================================
+/*!
+ * \brief Close the cgns file at destruction
+ */
+//================================================================================
+
+DriverStructuredCGNS_Write::~DriverStructuredCGNS_Write()
+{
+ if ( _fn > 0 )
+ cg_close( _fn );
+}
--- /dev/null
+// Copyright (C) 2016-2024 CEA, EDF
+//
+// 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, or (at your option) any later version.
+//
+// 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 : DriverStructuredCGNS_Write.hxx
+// Created : Tuesday March 19 2024
+// Author : Cesar Conopoima (cce)
+
+#ifndef __DriverStructuredCGNS_Write_HXX__
+#define __DriverStructuredCGNS_Write_HXX__
+
+// occt
+#include <TopoDS.hxx>
+
+// smesh
+#include "SMESH_DriverCGNS.hxx"
+#include "SMESH_RegularGridTemplate.hxx"
+#include "Driver_SMESHDS_Mesh.h"
+
+#include <vector>
+#include <string>
+
+/*!
+ * \brief Driver writinging a mesh into the CGNS file.
+ */
+class MESHDriverCGNS_EXPORT DriverStructuredCGNS_Write : public Driver_SMESHDS_Mesh
+{
+public:
+
+ DriverStructuredCGNS_Write();
+ ~DriverStructuredCGNS_Write();
+
+ virtual Status Perform();
+
+ /*!
+ * \brief Search for a SMESHDS_GroupOnGeom associated to the geometry and return his name
+ * \param shapeToIndex, the index of the shape as given by shapeToIndex method
+ * \return the name of the group if found or an empty name
+ */
+ std::string GetGroupName( const int shapeToIndex, int dim );
+
+ /*!
+ * \brief Fill name of face interfaces associated to mesh groups
+ */
+ void CheckForGroupNameOnFaceInterfaces( const SMESHUtils::SMESH_RegularGrid* grid, std::vector<std::string>& interfaceNames );
+
+ /*!
+ * \brief Fill name of edge interfaces associated to mesh groups
+ */
+ void CheckForGroupNameOnEdgeInterfaces( const SMESHUtils::SMESH_RegularGrid* grid, std::vector<std::string>& interfaceNames );
+
+private:
+ int _fn; //!< file index
+};
+
+#endif
const int nbnodes,
std::set<const SMDS_MeshNode*>& oldNodes );
- void setNbShapes( size_t nbShapes );
-
+ void setNbShapes( size_t nbShapes );
// Fields PRIVATE
double ymin;
double ymax;
double zmin;
- double zmax;
+ double zmax;
};
#ifdef WITH_CGNS
#include "DriverCGNS_Read.hxx"
#include "DriverCGNS_Write.hxx"
+#include "DriverStructuredCGNS_Write.hxx"
#endif
#include <GEOMUtils.hxx>
if ( res != Driver_Mesh::DRS_OK )
throw SALOME_Exception("Export failed");
}
+//================================================================================
+/*!
+ * \brief Export the mesh to the StructuredCGNS file
+ */
+//================================================================================
+
+void SMESH_Mesh::ExportStructuredCGNS(const char * file, const SMESHDS_Mesh* meshPart, const char * meshName)
+{
+
+ int res = Driver_Mesh::DRS_OK;
+ SMESH_TRY;
+
+#ifdef WITH_CGNS
+ auto myMesh = meshPart ? (SMESHDS_Mesh*) meshPart : _meshDS;
+
+ if ( myMesh->HasSomeStructuredGridFilled() )
+ {
+ DriverStructuredCGNS_Write writer;
+ writer.SetFile( file );
+ writer.SetMesh( const_cast<SMESHDS_Mesh*>( myMesh ));
+ writer.SetMeshName( SMESH_Comment("Mesh_") << myMesh->GetPersistentId());
+ if ( meshName && meshName[0] )
+ writer.SetMeshName( meshName );
+
+ res = writer.Perform();
+ if ( res != Driver_Mesh::DRS_OK )
+ {
+ SMESH_ComputeErrorPtr err = writer.GetError();
+ if ( err && !err->IsOK() && !err->myComment.empty() )
+ throw SALOME_Exception(("Export failed: " + err->myComment ).c_str() );
+ }
+ }
+
+#endif
+ SMESH_CATCH( SMESH::throwSalomeEx );
+
+ if ( res == Driver_Mesh::DRS_TOO_LARGE_MESH )
+ {
+ std::cout << "\n\n\n Going into too large mesh file path\n\n\n\n";
+ throw TooLargeForExport("CGNS");
+ }
+
+ if ( res != Driver_Mesh::DRS_OK )
+ throw SALOME_Exception("Export failed");
+}
//================================================================================
/*!
const SMESHDS_Mesh* mesh,
const char * meshName = 0,
const bool groupElemsByType = false);
+ void ExportStructuredCGNS(const char * file,
+ const SMESHDS_Mesh* mesh,
+ const char * meshName = 0);
void ExportGMF(const char * file,
const SMESHDS_Mesh* mesh,
bool withRequiredGroups = true );
${OpenCASCADE_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/SMDS
+ ${PROJECT_SOURCE_DIR}/src/SMESHUtils
${TBB_INCLUDES}
)
${OpenCASCADE_KERNEL}
${OpenCASCADE_ModelingData_LIBRARIES}
${KERNEL_SALOMELocalTrace}
- SMDS
+ SMDS
+ SMESHUtils
${TBB_LIBS}
)
#include "SMESHDS_Script.hxx"
#include "SMESHDS_TSubMeshHolder.hxx"
-#include <Standard_ErrorHandler.hxx>
-#include <Standard_OutOfRange.hxx>
+// #include <BRep_Tool.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Vertex.hxx>
+#include <Standard_ErrorHandler.hxx>
+#include <Standard_OutOfRange.hxx>
+
#include "utilities.h"
class SMESHDS_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< const SMESHDS_SubMesh >
void SMESHDS_Mesh::ClearMesh()
{
+ myRegularGrid.Clear();
+
myScript->ClearMesh();
SMDS_Mesh::Clear();
//=======================================================================
SMESHDS_Mesh::~SMESHDS_Mesh()
{
+ myRegularGrid.Clear();
// myScript
delete myScript;
// submeshes
myGrid->ModifyCellNodes(vtkVolId, localClonedNodeIds);
return true;
}
+
+/* Create a structured grid associated to the shapeId meshed
+ * @remark the grid dimension (nx, ny, nz) is not associated to a space direction, those dimensions denotes which index
+ * run faster in the nested loop defining the nodes of a structured grid.
+ * for( k in range(0,nz) )
+ * for( j in range(0,ny) )
+ * for( i in range(0,nx) )
+ * @param shape been meshed, pass the shape that would be passed to SetNodeOnFace or SetNodeInVolume method.
+ * @param nx, faster dimension
+ * @param ny, medium dimension
+ * @param nz, slower dimension
+ * @return define a new * SMESH_StructuredGrid to the shapeId.
+ */
+void SMESHDS_Mesh::SetStructuredGrid( const TopoDS_Shape & shape, const int nx, const int ny, const int nz )
+{
+ int index = myIndexToShape.FindIndex(shape);
+ if ( index != 0 )
+ {
+ if ( myRegularGrid.IsBound(index) )
+ myRegularGrid.UnBind(index);
+
+ myRegularGrid.Bind(index, std::make_shared<SMESHUtils::SMESH_RegularGrid>(index,nx,ny,nz));
+ }
+
+}
+
+void SMESHDS_Mesh::SetNodeOnStructuredGrid( const TopoDS_Shape & shape, const std::shared_ptr<gp_Pnt>& P, const int iIndex, const int jIndex, const int kIndex )
+{
+ int index = myIndexToShape.FindIndex(shape);
+ if ( index != 0 && myRegularGrid.IsBound(index) )
+ myRegularGrid.Seek(index)->get()->SetNode( P, iIndex, jIndex, kIndex );
+}
+
+void SMESHDS_Mesh::SetNodeOnStructuredGrid( const TopoDS_Shape & shape, const SMDS_MeshNode* P, const int iIndex, const int jIndex, const int kIndex )
+{
+ int index = myIndexToShape.FindIndex(shape);
+ if ( index != 0 && myRegularGrid.IsBound(index) )
+ myRegularGrid.Seek(index)->get()->SetNode( P, iIndex, jIndex, kIndex );
+}
+
+void SMESHDS_Mesh::SetNodeOnStructuredGrid( const TopoDS_Shape & shape, const SMDS_MeshNode* P, const int index )
+{
+ int shapeIndex = myIndexToShape.FindIndex(shape);
+ if ( shapeIndex != 0 && myRegularGrid.IsBound(shapeIndex) )
+ myRegularGrid.Seek(shapeIndex)->get()->SetNode( P, index );
+}
+
+bool SMESHDS_Mesh::HasStructuredGridFilled( const TopoDS_Shape & shape ) const
+{
+ int index = myIndexToShape.FindIndex(shape);
+ if ( index != 0 && myRegularGrid.IsBound(index) )
+ return true;
+ else
+ return false;
+}
+
+bool SMESHDS_Mesh::HasSomeStructuredGridFilled() const
+{
+ bool hasSomeStructuredGrid = false;
+ for ( TopExp_Explorer fEx( myShape, TopAbs_SOLID ); fEx.More(); fEx.Next() )
+ {
+ TopoDS_Solid solid = TopoDS::Solid(fEx.Current());
+ if ( HasStructuredGridFilled( solid ) ) hasSomeStructuredGrid = true;
+ }
+ for ( TopExp_Explorer fEx( myShape, TopAbs_FACE ); fEx.More(); fEx.Next() )
+ {
+ TopoDS_Face face = TopoDS::Face(fEx.Current());
+ if ( HasStructuredGridFilled( face ) ) hasSomeStructuredGrid = true;
+ }
+ return hasSomeStructuredGrid;
+}
+
+const std::shared_ptr<SMESHUtils::SMESH_RegularGrid>& SMESHDS_Mesh::GetTheGrid( const TopoDS_Shape & shape )
+{
+ int index = myIndexToShape.FindIndex(shape);
+ if ( index != 0 && myRegularGrid.IsBound(index) )
+ return *myRegularGrid.Seek(index);
+}
\ No newline at end of file
#include "SMESH_SMESHDS.hxx"
#include "SMDS_Mesh.hxx"
+#include "SMESH_Utils.hxx"
+#include "SMESH_RegularGrid.hxx"
#include "SMESHDS_SubMesh.hxx"
#include <Basics_OCCTVersion.hxx>
void CleanDownWardConnectivity();
void BuildDownWardConnectivity(bool withEdges);
+ virtual void SetStructuredGrid( const TopoDS_Shape & shape, const int nx, const int ny, const int nz = 1 );
+ virtual void SetNodeOnStructuredGrid( const TopoDS_Shape & shape, const std::shared_ptr<gp_Pnt>& P, const int iIndex, const int jIndex, const int kIndex = 0 );
+ virtual void SetNodeOnStructuredGrid( const TopoDS_Shape & shape, const SMDS_MeshNode* point, const int iIndex, const int jIndex, const int kIndex = 0 );
+ virtual void SetNodeOnStructuredGrid( const TopoDS_Shape & shape, const SMDS_MeshNode* point, const int index );
+ virtual bool HasStructuredGridFilled( const TopoDS_Shape & shape ) const;
+ virtual bool HasSomeStructuredGridFilled() const;
+ virtual const std::shared_ptr<SMESHUtils::SMESH_RegularGrid>& GetTheGrid( const TopoDS_Shape & shape );
~SMESHDS_Mesh();
private:
int add( const SMDS_MeshElement* elem, SMESHDS_SubMesh* subMesh );
SMESHDS_SubMesh* getSubmesh( const TopoDS_Shape & shape);
+
+ // Index the regular grid associated to the mesh in the geometry index
+ NCollection_DataMap<int,std::shared_ptr<SMESHUtils::SMESH_RegularGrid>> myRegularGrid;
};
{
format = "CGNS";
notSupportedElemTypes.push_back( SMESH::Entity_Ball );
- }
+ }
else if ( isGMF )
{
format = "GMF";
bool toFindOutDim = true;
bool saveNumbers = resMgr->booleanValue( "SMESH", "med_save_numbers", true );
bool toRenumber = true;
+ bool structureCGNS = false;
double zTol = resMgr->doubleValue( "SMESH", "med_ztolerance", 0. );
QString aFilter, aTitle = QObject::tr("SMESH_EXPORT_MESH");
anInitialPath + QString("/") + aMeshName,
aFilter, aTitle, false);
}
- else if ( isCGNS || isUNV || isDAT ) // Export to [ CGNS | UNV | DAT ] - one option
+ else if ( isCGNS )
+ {
+ const char* theOptionResource = "cgns_group_elems_by_type";
+ bool option = resMgr->booleanValue( "SMESH", theOptionResource, false );
+
+ QStringList checkBoxes;
+ checkBoxes << QObject::tr( "CGNS_EXPORT_ELEMS_BY_TYPE" ) << QObject::tr("STRUCTUREDCGNS");
+
+ SalomeApp_CheckFileDlg* fd = new SalomeApp_CheckFileDlg ( SMESHGUI::desktop(), false, checkBoxes, true, true );
+
+ fd->setWindowTitle( aTitle );
+ fd->setNameFilter( QObject::tr( "CGNS_FILES_FILTER" ) + " (*.cgns)" );
+
+ if ( !anInitialPath.isEmpty() )
+ fd->setDirectory( anInitialPath );
+ fd->selectFile( aMeshName );
+ SMESHGUI_FileValidator* fv = new SMESHGUI_FileValidator( fd );
+ fd->setValidator( fv );
+ fd->SetChecked( option, 0 );
+
+ if ( fd->exec() )
+ {
+ aFilename = fd->selectedFile();
+ structureCGNS = fd->IsChecked( 1 );
+ }
+
+ toOverwrite = fv->isOverwrite( aFilename );
+ option = fd->IsChecked( 0 );
+ SMESHGUI::resourceMgr()->setValue("SMESH", theOptionResource, option );
+ toCreateGroups = option;
+
+ delete fd;
+ }
+ else if ( isUNV || isDAT ) // Export to [ UNV | DAT ] - one option
{
- const char* theOptionResource = isCGNS ? "cgns_group_elems_by_type" : "export_renumber";
+ const char* theOptionResource = "export_renumber";
bool option = resMgr->booleanValue( "SMESH", theOptionResource, false );
QStringList checkBoxes;
- checkBoxes << QObject::tr( isCGNS ? "CGNS_EXPORT_ELEMS_BY_TYPE" : "SMESH_RENUMBER" );
+ checkBoxes << QObject::tr( "SMESH_RENUMBER" );
SalomeApp_CheckFileDlg* fd =
new SalomeApp_CheckFileDlg ( SMESHGUI::desktop(), false, checkBoxes, true, true );
fd->setWindowTitle( aTitle );
- if ( isCGNS )
- fd->setNameFilter( QObject::tr( "CGNS_FILES_FILTER" ) + " (*.cgns)" );
- else if ( isUNV )
+ if ( isUNV )
fd->setNameFilter( QObject::tr( "IDEAS_FILES_FILTER" ) + " (*.unv)" );
else if ( isDAT )
fd->setNameFilter( QObject::tr( "DAT_FILES_FILTER" ) + " (*.dat)" );
toOverwrite = fv->isOverwrite( aFilename );
option = fd->IsChecked( 0 );
SMESHGUI::resourceMgr()->setValue("SMESH", theOptionResource, option );
- ( isCGNS ? toCreateGroups : toRenumber ) = option;
+ toRenumber = option;
delete fd;
}
else if ( isSTL ) // Export to STL
{
QMap<QString, int> aFilterMap;
+ QStringList filters;
aFilterMap.insert( QObject::tr( "STL_ASCII_FILES_FILTER" ) + " (*.stl)", 1 );
aFilterMap.insert( QObject::tr( "STL_BIN_FILES_FILTER" ) + " (*.stl)", 0 );
-
- QStringList filters;
+
QMap<QString, int>::const_iterator it = aFilterMap.begin();
for ( ; it != aFilterMap.end(); ++it )
- filters.push_back( it.key() );
-
+ filters.push_back( it.key() );
+
SUIT_FileDlg* fd = new SUIT_FileDlg( SMESHGUI::desktop(), false, true, true );
fd->setWindowTitle( aTitle );
fd->setNameFilters( filters );
- fd->selectNameFilter( QObject::tr( "STL_ASCII_FILES_FILTER" ) + " (*.stl)" );
+
if ( !anInitialPath.isEmpty() )
fd->setDirectory( anInitialPath );
fd->selectFile(aMeshName);
while (!is_ok) {
if ( fd->exec() )
aFilename = fd->selectedFile();
- aIsASCII_STL = (aFilterMap[fd->selectedNameFilter()]) == 1 ? true: false;
+ if ( isSTL )
+ aIsASCII_STL = (aFilterMap[fd->selectedNameFilter()]) == 1 ? true: false;
is_ok = true;
}
delete fd;
else if ( isCGNS )
{
aMeshIter = aMeshList.begin();
+
for( int aMeshIndex = 0; aMeshIter != aMeshList.end(); aMeshIter++, aMeshIndex++ )
{
SMESH::SMESH_IDSource_var aMeshOrGroup = (*aMeshIter).first;
SMESH::SMESH_Mesh_var aMeshItem = aMeshOrGroup->GetMesh();
- aMeshItem->ExportCGNS( aMeshOrGroup,
- aFilename.toUtf8().data(),
- toOverwrite && aMeshIndex == 0,
- toCreateGroups );
+
+ if ( !structureCGNS )
+ aMeshItem->ExportCGNS( aMeshOrGroup,
+ aFilename.toUtf8().data(),
+ toOverwrite && aMeshIndex == 0,
+ toCreateGroups );
+ else
+ aMeshItem->ExportStructuredCGNS( aMeshOrGroup,
+ aFilename.toUtf8().data(),
+ toOverwrite && aMeshIndex == 0 );
}
}
else if ( isGMF )
QObject::tr("SMESH_WRN_WARNING"),
QObject::tr("SMESH_EXPORT_FAILED_SHORT") + "\n\n" + exText);
}
- else
+ else if ( isMED )
+ {
SUIT_MessageBox::warning(SMESHGUI::desktop(),
QObject::tr("SMESH_WRN_WARNING"),
QObject::tr("SMESH_EXPORT_FAILED") + SalomeApp_Tools::ExceptionToString(S_ex));
+ }
+ else
+ SUIT_MessageBox::warning(SMESHGUI::desktop(),
+ QObject::tr("SMESH_WRN_WARNING"),
+ SalomeApp_Tools::ExceptionToString(S_ex));
wc.resume();
}
}
pix = resMgr->loadPixmap( "SMESH", tr( QString( "ICON_%1" ).arg( po_id ).toLatin1().data() ), false );
if ( !pix.isNull() )
icon = QIcon( pix );
-
+
QString tooltip = tr( QString( "TOP_%1" ).arg( po_id ).toLatin1().data() ),
menu = tr( QString( "MEN_%1" ).arg( po_id ).toLatin1().data() ),
status_bar = tr( QString( "STB_%1" ).arg( po_id ).toLatin1().data() );
<source>CGNS_EXPORT_ELEMS_BY_TYPE</source>
<translation>Group elements by type</translation>
</message>
+ <message>
+ <source>STRUCTUREDCGNS</source>
+ <translation>Structured version (only for Hexahedron(i,j,k) and Quadrangle: Mapping meshes)</translation>
+ </message>
<message>
<source>GMF_ASCII_FILES_FILTER</source>
<translation>GMF ASCII files</translation>
<source>CGNS_EXPORT_ELEMS_BY_TYPE</source>
<translation>Groupe les éléments par type</translation>
</message>
+ <message>
+ <source>STRUCTUREDCGNS</source>
+ <translation>Format structuré (uniquement pour les maillages Hexahedron(i,j,k) et Quadrangle: Mapping)</translation>
+ </message>
<message>
<source>GMF_ASCII_FILES_FILTER</source>
<translation>Fichiers GMF ASCII</translation>
<source>CGNS_EXPORT_ELEMS_BY_TYPE</source>
<translation>タイプで要素をグループ化</translation>
</message>
+ <message>
+ <source>STRUCTUREDCGNS</source>
+ <translation>CGNS 構造化バージョンのエクスポート</translation>
+ </message>
<message>
<source>GMF_ASCII_FILES_FILTER</source>
<translation>GMFアスキーファイル</translation>
SMESH_Indexer.hxx
SMESH_BoostTxtArchive.hxx
SMESH_MGLicenseKeyGen.hxx
+ SMESH_RegularGrid.hxx
+ SMESH_RegularGridTemplate.hxx
)
# --- sources ---
SMESH_PolyLine.cxx
SMESH_BoostTxtArchive.cxx
SMESH_MGLicenseKeyGen.cxx
+ SMESH_RegularGrid.cxx
)
# --- rules ---
--- /dev/null
+// Copyright (C) 2016-2024 CEA, EDF
+//
+// 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, or (at your option) any later version.
+//
+// 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_StructuredGrid.cxx
+// Created : Sun March 24 09:58 2024
+// Author : Cesar Conopoima (cce)
+
+//CAS
+#include <BRep_Tool.hxx>
+
+// SMESH
+#include "SMDS_MeshNode.hxx"
+#include "SMESH_TypeDefs.hxx"
+#include "SMESH_RegularGridTemplate.hxx"
+
+using namespace SMESHUtils;
+
+SMESH_RegularGrid::SMESH_RegularGrid( const int id, const int nx, const int ny, const int nz ) :
+myId(id),
+mnx(nx),
+mny(ny),
+mnz(nz),
+mns(nx*ny*nz)
+{
+ myCoordinates.Resize(0,mnx*mny*mnz-1, false);
+ myCoordinates.Init(nullptr);
+}
+
+void SMESH_RegularGrid::SetNode( const std::shared_ptr<gp_Pnt>& point, const int iIndex, const int jIndex, const int zIndex )
+{
+ int index = zIndex * mnx * mny + jIndex * mnx + iIndex;
+ if ( mns > 0 && index < mns && myCoordinates[ index ] == nullptr )
+ myCoordinates[ index ] = point;
+}
+
+void SMESH_RegularGrid::SetNode( const SMDS_MeshNode* point, const int iIndex, const int jIndex, const int zIndex )
+{
+
+ int index = zIndex * mnx * mny + jIndex * mnx + iIndex;
+ if ( mns > 0 && index < mns && myCoordinates[ index ] == nullptr )
+ myCoordinates[ index ] = std::move( std::make_shared<gp_Pnt>(point->X(),point->Y(),point->Z()));
+}
+
+void SMESH_RegularGrid::SetNode( const SMDS_MeshNode* point, const int index )
+{
+ if ( mns > 0 && index < mns && myCoordinates[ index ] == nullptr )
+ myCoordinates[ index ] = std::move( std::make_shared<gp_Pnt>(point->X(),point->Y(),point->Z()));
+}
+
+const std::shared_ptr<gp_Pnt> SMESH_RegularGrid::GetNode( const int iIndex, const int jIndex, const int zIndex )
+{
+ int index = zIndex * mnx * mny + jIndex * mnx + iIndex;
+ if ( index > -1 && index < mns )
+ return myCoordinates[ index ];
+ else
+ return nullptr;
+}
+
+
+std::tuple<int,int,int> SMESH_RegularGrid::GetIJK(const int index) const
+{
+ int K = int(index/(mnx*mny));
+ int J = int(index/mnx) % mny;
+ int I = index % mnx;
+ return std::tuple<int,int,int>(I,J,K);
+}
+
+std::vector<int> SMESH_RegularGrid::getEdgeIndexLimitsInverted( const EdgeType edge ) const
+{
+ auto limits = getEdgeIndexLimits( edge );
+ std::swap(limits[0],limits[2]);
+ std::swap(limits[1],limits[3]);
+ return limits;
+}
+
+std::vector<int> SMESH_RegularGrid::getEdgeIndexLimits( const EdgeType edge ) const
+{
+ switch ( edge ) {
+ case EdgeType::BOTTOM:
+ return std::vector<int>{1,1,mnx,1};
+ break;
+ case EdgeType::RIGHT:
+ return std::vector<int>{mnx,1,mnx,mny};
+ break;
+ case EdgeType::TOP:
+ return std::vector<int>{mnx,mny,1,mny};
+ break;
+ case EdgeType::LEFT:
+ return std::vector<int>{1,mny,1,1};
+ break;
+ default:
+ return std::vector<int>{1,1,mnx,1};
+ break;
+ }
+}
+
+std::vector<int> SMESH_RegularGrid::getFaceIndexLimits( const int start, const int end ) const
+{
+ auto startIJK = GetIJK(start);
+ auto endIJK = GetIJK(end);
+ int iStart = std::get<0>(startIJK);
+ int jStart = std::get<1>(startIJK);
+ int kStart = std::get<2>(startIJK);
+ int iEnd = std::get<0>(endIJK);
+ int jEnd = std::get<1>(endIJK);
+ int kEnd = std::get<2>(endIJK);
+ return std::vector<int>{iStart+1,jStart+1,kStart+1,iEnd+1,jEnd+1,kEnd+1};
+}
+
+std::vector<int> SMESH_RegularGrid::getEdgeIndexLimits( const int start, const int end ) const
+{
+ auto startIJK = GetIJK(start);
+ auto endIJK = GetIJK(end);
+ int iStart = std::get<0>(startIJK);
+ int jStart = std::get<1>(startIJK);
+ int iEnd = std::get<0>(endIJK);
+ int jEnd = std::get<1>(endIJK);
+ return std::vector<int>{iStart+1,jStart+1,iEnd+1,jEnd+1};
+}
+
+std::vector<int> SMESH_RegularGrid::getFaceIndexLimits( const FaceType face ) const
+{
+ switch ( face ) {
+ case FaceType::B_BOTTOM:
+ return std::vector<int>{1,1,1,mnx,mny,1}; /*V0-V2*/
+ break;
+ case FaceType::B_RIGHT:
+ return std::vector<int>{mnx,1,1,mnx,mny,mnz}; /*V1-V6*/
+ break;
+ case FaceType::B_BACK:
+ return std::vector<int>{1,mny,1,mnx,mny,mnz}; /*V3-V6*/
+ break;
+ case FaceType::B_LEFT:
+ return std::vector<int>{1,1,1,1,mny,mnz}; /*V0-V7*/
+ break;
+ case FaceType::B_FRONT:
+ return std::vector<int>{1,1,1,mnx,1,mnz}; /*V0-V5*/
+ break;
+ case FaceType::B_TOP:
+ return std::vector<int>{1,1,mnz,mnx,mny,mnz}; /*V4-V6*/
+ break;
+ default:
+ return std::vector<int>{1,1,1,mnx,mny,1};
+ break;
+ }
+}
+
+int SMESH_RegularGrid::getEdgeSize( const EdgeType edge ) const
+{
+ switch ( edge ) {
+ case EdgeType::BOTTOM:
+ case EdgeType::TOP:
+ return mnx;
+ break;
+ case EdgeType::RIGHT:
+ case EdgeType::LEFT:
+ return mny;
+ break;
+ default:
+ return mnx;
+ break;
+ }
+}
+
+int SMESH_RegularGrid::getFaceSize( const FaceType edge ) const
+{
+ switch ( edge ) {
+ case FaceType::B_BOTTOM:
+ case FaceType::B_TOP:
+ return mnx*mny;
+ break;
+ case FaceType::B_RIGHT:
+ case FaceType::B_LEFT:
+ return mny*mnz;
+ break;
+ case FaceType::B_FRONT:
+ case FaceType::B_BACK:
+ return mnx*mnz;
+ break;
+ default:
+ return mnx;
+ break;
+ }
+}
+
+
+void SMESH_RegularGrid::getAllEdgeIndexLimits(std::vector<std::vector<int>>& allRanges)
+{
+ this->foreachGridSide( [&]( EdgeType edge )
+ {
+ allRanges.push_back( getEdgeIndexLimits(edge) );
+ });
+}
+
+void SMESH_RegularGrid::getAllFaceIndexLimits(std::vector<std::vector<int>>& allRanges)
+{
+ this->foreachGridFace( [&]( FaceType face )
+ {
+ allRanges.push_back( getFaceIndexLimits(face) );
+ });
+}
+
+std::vector<int> SMESH_RegularGrid::nodesOfFace( SMESH_RegularGrid::FaceType face ) const
+{
+ size_t faceSize=0;
+ if ( face == SMESH_RegularGrid::B_BOTTOM || face == SMESH_RegularGrid::B_TOP )
+ faceSize = mnx*mny;
+ if ( face == SMESH_RegularGrid::B_LEFT || face == SMESH_RegularGrid::B_RIGHT )
+ faceSize = mny*mnz;
+ if ( face == SMESH_RegularGrid::B_BACK || face == SMESH_RegularGrid::B_FRONT )
+ faceSize = mnx*mnz;
+
+ std::vector<int> index(faceSize);
+ switch ( face ) {
+ case FaceType::B_BOTTOM:
+ for (size_t i = 0; i < faceSize; i++)
+ index[ i ] = i;
+ break;
+ case FaceType::B_TOP:
+ for (size_t i = 0; i < faceSize; i++)
+ index[ i ] = mnx * mny * mnz - mnx * mny + i;
+ break;
+ case FaceType::B_RIGHT:
+ for (size_t i = 0; i < faceSize; i++)
+ {
+ auto dv = std::div(i,mny);
+ index[ i ] = dv.quot * mnx * mny + (mnx-1)*(dv.rem+1)+dv.rem;
+ }
+ break;
+ case FaceType::B_LEFT:
+ for (size_t i = 0; i < faceSize; i++)
+ {
+ auto dv = std::div(i,mny);
+ index[ i ] = dv.quot * mnx * mny + (dv.rem) * mnx;
+ }
+ break;
+ case FaceType::B_BACK:
+ for (size_t i = 0; i < faceSize; i++)
+ {
+ auto dv = std::div(i,mnx);
+ index[ i ] = dv.quot * mnx * mny + mny * mnx - mnx + dv.rem;
+ }
+ break;
+ case FaceType::B_FRONT:
+ for (size_t i = 0; i < faceSize; i++)
+ {
+ auto dv = std::div(i,mnx);
+ index[ i ] = dv.quot * mnx * mny + dv.rem;
+ }
+ break;
+ default:
+ break;
+ }
+ return index;
+}
+
+std::vector<int> SMESH_RegularGrid::nodesOfSide( SMESH_RegularGrid::EdgeType edge ) const
+{
+ size_t sideSize = ( edge == SMESH_RegularGrid::BOTTOM ) || ( edge == SMESH_RegularGrid::TOP ) ? mnx : mny;
+ std::vector<int> index(sideSize);
+ switch ( edge ) {
+ case EdgeType::BOTTOM:
+ for (size_t i = 0; i < sideSize; i++)
+ index[ i ] = i;
+ break;
+ case EdgeType::RIGHT:
+ for (size_t i = 0; i < sideSize; i++)
+ index[ i ] = mnx*(i+1)-1;
+ break;
+ case EdgeType::TOP:
+ for (size_t i = 0; i < sideSize; i++)
+ index[ i ] = mnx*mny-(i+1);
+ break;
+ case EdgeType::LEFT:
+ for (size_t i = 0; i < sideSize; i++)
+ index[ i ] = mnx*mny-(i+1)*mnx;
+ break;
+ default:
+ break;
+ }
+ return index;
+}
+
+// Return the index of the nodes at begin and end of the edge
+std::pair<int,int> SMESH_RegularGrid::getEdgeLimits( const EdgeType edge ) const
+{
+ switch ( edge ) {
+ case EdgeType::BOTTOM:
+ return std::make_pair(0,mnx-1);
+ break;
+ case EdgeType::RIGHT:
+ return std::make_pair(mnx-1,mnx*mny-1);
+ break;
+ case EdgeType::TOP:
+ return std::make_pair(mnx*mny-1,mnx*mny-mnx);
+ break;
+ case EdgeType::LEFT:
+ return std::make_pair(mnx*mny-mnx,0);
+ break;
+ default:
+ return std::make_pair(0,mnx-1);
+ break;
+ }
+}
+
+int SMESH_RegularGrid::getFaceCoordinateIndex( const VertexType v ) const
+{
+ switch ( v ) {
+ case VertexType::V0:
+ return 0;
+ break;
+ case VertexType::V1:
+ return mnx-1;
+ break;
+ case VertexType::V2:
+ return mnx*mny-1;
+ break;
+ case VertexType::V3:
+ return mnx*mny-mnx;
+ break;
+ case VertexType::V4:
+ return mnx*mny*mnz-mnx*mny;
+ break;
+ case VertexType::V5:
+ return mnx*mny*mnz-mnx*mny+mnx-1;
+ break;
+ case VertexType::V6:
+ return mnx*mny*mnz-1;
+ break;
+ case VertexType::V7:
+ return mnx*mny*mnz-mnx;
+ break;
+ default:
+ return 0;
+ break;
+ }
+}
+
+std::tuple<int,int,int,int> SMESH_RegularGrid::getFaceLimits( const FaceType face ) const
+{
+ switch ( face ) {
+ case FaceType::B_BOTTOM: /*V0-V2-V1-V3*/
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V0),
+ getFaceCoordinateIndex(VertexType::V2),
+ getFaceCoordinateIndex(VertexType::V1),
+ getFaceCoordinateIndex(VertexType::V3)};
+ break;
+ case FaceType::B_RIGHT: /*V1-V6-V2-V5*/
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V1),
+ getFaceCoordinateIndex(VertexType::V6),
+ getFaceCoordinateIndex(VertexType::V2),
+ getFaceCoordinateIndex(VertexType::V5)};
+ break;
+ case FaceType::B_BACK: /*V3-V6-V2-V7*/
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V3),
+ getFaceCoordinateIndex(VertexType::V6),
+ getFaceCoordinateIndex(VertexType::V2),
+ getFaceCoordinateIndex(VertexType::V7)};
+ break;
+ case FaceType::B_LEFT: /*V0-V7-V3-V4*/
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V0),
+ getFaceCoordinateIndex(VertexType::V7),
+ getFaceCoordinateIndex(VertexType::V3),
+ getFaceCoordinateIndex(VertexType::V4)};
+ break;
+ case FaceType::B_FRONT: /*V0-V5-V1-V4*/
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V0),
+ getFaceCoordinateIndex(VertexType::V5),
+ getFaceCoordinateIndex(VertexType::V1),
+ getFaceCoordinateIndex(VertexType::V4)};
+ break;
+ case FaceType::B_TOP:
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V4),
+ getFaceCoordinateIndex(VertexType::V6),
+ getFaceCoordinateIndex(VertexType::V5),
+ getFaceCoordinateIndex(VertexType::V7)};
+ break;
+ default:
+ return std::tuple<int,int,int,int>{getFaceCoordinateIndex(VertexType::V0),
+ getFaceCoordinateIndex(VertexType::V2),
+ getFaceCoordinateIndex(VertexType::V1),
+ getFaceCoordinateIndex(VertexType::V3)};
+ break;
+ }
+}
+
+void SMESH_RegularGrid::GetCommontInterface( FaceType face, SMESH_RegularGrid * grid, std::vector<int>& interface )
+{
+ const double tol = Precision::Confusion(); /*confusion is 1e-7, the recommended tolerance to find coincident points in 3D*/
+ auto vertex = getFaceLimits( face );
+ auto v0 = myCoordinates[std::get<0>(vertex)];
+ auto v1 = myCoordinates[std::get<1>(vertex)];
+ auto v2 = myCoordinates[std::get<2>(vertex)];
+ auto v3 = myCoordinates[std::get<3>(vertex)];
+
+ auto foundOneTrue = [](int begin, int end, std::vector<bool>& v ) -> bool
+ {
+ for ( int i = begin; i <= end; i++ )
+ if ( v[i] )
+ return true;
+ return false;
+ };
+
+ auto foundTrueColum = [](int colum, std::vector<bool>& v ) -> bool
+ {
+ int strikeSize = 4;
+ for ( int i = 0; i < strikeSize; i++ )
+ if ( v[colum + i*strikeSize] )
+ return true;
+ return false;
+ };
+
+ grid->foreachGridFace( [&]( FaceType gridFace )
+ {
+ std::vector<int> interfaceRange,interfaceDonor,tranformationRange,tranformationDonor;
+
+ auto neighboorVertex = grid->getFaceLimits( gridFace );
+
+ auto v4 = grid->GetNode(std::get<0>(neighboorVertex));
+ auto v5 = grid->GetNode(std::get<1>(neighboorVertex));
+ auto v6 = grid->GetNode(std::get<2>(neighboorVertex));
+ auto v7 = grid->GetNode(std::get<3>(neighboorVertex));
+
+
+ std::vector<bool> trueTable({ v0->IsEqual(*v4,tol),v0->IsEqual(*v5,tol),v0->IsEqual(*v6,tol),v0->IsEqual(*v7,tol),
+ v1->IsEqual(*v4,tol),v1->IsEqual(*v5,tol),v1->IsEqual(*v6,tol),v1->IsEqual(*v7,tol),
+ v2->IsEqual(*v4,tol),v2->IsEqual(*v5,tol),v2->IsEqual(*v6,tol),v2->IsEqual(*v7,tol),
+ v3->IsEqual(*v4,tol),v3->IsEqual(*v5,tol),v3->IsEqual(*v6,tol),v3->IsEqual(*v7,tol)});
+
+ std::vector<bool> trueCorner({foundOneTrue(0,3,trueTable),
+ foundOneTrue(4,7,trueTable),
+ foundOneTrue(8,11,trueTable),
+ foundOneTrue(12,15,trueTable) });
+
+ if ( trueCorner[0] &&
+ trueCorner[1] &&
+ trueCorner[2] &&
+ trueCorner[3] ) /*Face to Face interface 100% conform*/
+ {
+ interfaceRange = this->getFaceIndexLimits( face );
+ interfaceDonor = grid->getFaceIndexLimits( gridFace );
+ }
+ else if ( trueCorner[0] || trueCorner[1] ||
+ trueCorner[2] || trueCorner[3] ) /*Partial Face to Face. Only one intersection then all the other 3 vertex are: 2 in the edges 1 inside the face*/
+ {
+ // Two possible cases:
+ // 1) face < gridFace
+ if ( this->getFaceSize( face ) < grid->getFaceSize( gridFace ) )
+ {
+ auto nodeToSearch = trueCorner[0] ? v1 : trueCorner[2] ? v3 : trueCorner[1] ? v0 : v2;
+
+ grid->foreachNodeOnFace( gridFace, [&] (const std::shared_ptr<gp_Pnt> sidePoint, const int nodeIndex)
+ {
+ if ( nodeToSearch->IsEqual( *sidePoint, tol ) )
+ {
+ interfaceRange = this->getFaceIndexLimits( face );
+
+ auto startIndex = foundTrueColum(0,trueTable) ? std::get<0>(neighboorVertex) :
+ foundTrueColum(2,trueTable) ? std::get<2>(neighboorVertex) :
+ foundTrueColum(1,trueTable) ? std::get<1>(neighboorVertex) :
+ std::get<3>(neighboorVertex);
+
+ interfaceDonor = startIndex < nodeIndex ?
+ grid->getFaceIndexLimits( startIndex, nodeIndex ) :
+ grid->getFaceIndexLimits( nodeIndex, startIndex );
+ return;
+ }
+ });
+ }
+ // 2) face > gridEdge
+ else if ( this->getFaceSize( face ) > grid->getFaceSize( gridFace ) )
+ {
+ auto nodeToSearch = foundTrueColum(0,trueTable) ? v5 :
+ foundTrueColum(2,trueTable) ? v7 :
+ foundTrueColum(1,trueTable) ? v4 : v6;
+
+ this->foreachNodeOnFace( face, [&] (const std::shared_ptr<gp_Pnt> sidePoint, const int nodeIndex )
+ {
+ if ( nodeToSearch->IsEqual( *sidePoint, tol ) )
+ {
+ auto startIndex = trueCorner[0] ? std::get<0>(vertex) :
+ trueCorner[2] ? std::get<2>(vertex) :
+ trueCorner[1] ? std::get<1>(vertex) : std::get<3>(vertex);
+
+ interfaceRange = startIndex < nodeIndex ?
+ this->getFaceIndexLimits( startIndex, nodeIndex) :
+ this->getFaceIndexLimits( nodeIndex, startIndex );
+
+ interfaceDonor = grid->getFaceIndexLimits( gridFace );
+ return;
+ }
+ });
+ }
+ }
+
+ if ( !interfaceRange.empty() && !interfaceDonor.empty() )
+ {
+ tranformationRange = this->computeTransformation( face, gridFace, interfaceRange, interfaceDonor );
+ tranformationDonor = grid->computeTransformation( gridFace, face, interfaceDonor, interfaceRange );
+ interface = std::vector<int>{(int)face}+interfaceRange+interfaceDonor+tranformationRange;
+ auto dualInterface = std::vector<int>{(int)face}+interfaceDonor+interfaceRange+tranformationDonor;
+ this->setInterface( face, grid->id(), interface );
+ grid->setInterface( gridFace, this->id(), dualInterface );
+ }
+ });
+}
+
+void SMESH_RegularGrid::GetCommontInterface( EdgeType edge, SMESH_RegularGrid * grid, std::vector<int>& interface )
+{
+ const double tol = Precision::Confusion(); /*confusion is 1e-7, the recommended tolerance to find coincident points in 3D*/
+ auto vertex = getEdgeLimits( edge );
+ auto v0 = myCoordinates[vertex.first];
+ auto v1 = myCoordinates[vertex.second];
+
+ grid->foreachGridSide( [&]( EdgeType gridEdge )
+ {
+ std::vector<int> interfaceRange,interfaceDonor,tranformationRange,tranformationDonor;
+ auto neighboorVertex = grid->getEdgeLimits( gridEdge );
+ auto v2 = grid->GetNode(neighboorVertex.first);
+ auto v3 = grid->GetNode(neighboorVertex.second);
+
+ std::vector<bool> trueTable({ v0->IsEqual(*v2,tol),
+ v0->IsEqual(*v3,tol),
+ v1->IsEqual(*v2,tol),
+ v1->IsEqual(*v3,tol) });
+
+ if ( (trueTable[0] || trueTable[1] ) && /*Case start-end vertex are coincident in both edges trivial*/
+ (trueTable[2] ||trueTable[3] ) )
+ {
+ interfaceRange = this->getEdgeIndexLimits( edge );
+ interfaceDonor = grid->getEdgeIndexLimitsInverted( gridEdge );
+ }
+ else if ( trueTable[0] || /*Case start OR end vertex are coincident in both edges*/
+ trueTable[1] ||
+ trueTable[2] ||
+ trueTable[3] )
+ {
+ // Two possible cases:
+ // 1) edge < gridEdge means that v1 is going to be found as an intersection inside gridEdge side!!!
+ if ( this->getEdgeSize( edge ) < grid->getEdgeSize( gridEdge ) )
+ {
+ auto nodeToSearch = (trueTable[0] || trueTable[1]) ? v1 : v0;
+ grid->foreachNodeOnSide( gridEdge, [&] (const std::shared_ptr<gp_Pnt> sidePoint, const int nodeIndex)
+ {
+ if ( nodeToSearch->IsEqual( *sidePoint, tol ) )
+ {
+ interfaceRange = this->getEdgeIndexLimits( edge );
+ auto startIndex = (trueTable[0] || trueTable[2]) ? neighboorVertex.first : neighboorVertex.second;
+ interfaceDonor = startIndex < nodeIndex ?
+ grid->getEdgeIndexLimits( startIndex, nodeIndex ) :
+ grid->getEdgeIndexLimits( nodeIndex, startIndex );
+
+ }
+ });
+ }
+ // 2) edge > gridEdge means that v2 or v3 are going to be found as an intersection inside edge side!!!
+ else if ( this->getEdgeSize( edge ) > grid->getEdgeSize( gridEdge ) )
+ {
+ auto nodeToSearch = (trueTable[0] || trueTable[2]) ? v3 : v2;
+ this->foreachNodeOnSide( edge, [&] (const std::shared_ptr<gp_Pnt> sidePoint, const int nodeIndex)
+ {
+ if ( nodeToSearch->IsEqual( *sidePoint, tol ) )
+ {
+ auto startIndex = (trueTable[0] || trueTable[1]) ? vertex.first : vertex.second;
+ interfaceRange = startIndex < nodeIndex ?
+ this->getEdgeIndexLimits( startIndex, nodeIndex) :
+ this->getEdgeIndexLimits( nodeIndex, startIndex );
+
+ interfaceDonor = grid->getEdgeIndexLimitsInverted( gridEdge );
+ }
+ });
+ }
+ }
+ else /*Case nor start nor end are coincident in both edges but one of the edges can be embemded completly in the other*/
+ {
+ // Discard quickly non parallel and far edges
+ auto v01 = v1->Coord()-v0->Coord();
+ auto v23 = v3->Coord()-v2->Coord();
+ if ( std::fabs( v01.Dot(v23) ) == 1.0 /*parallel edges might have intersection*/ )
+ {
+ double v01Module = v01.Modulus();
+ double v23Module = v23.Modulus();
+ auto ref = v01Module > v23Module ? v01 : v23;
+ auto v0Ref = v01Module > v23Module ? v0->Coord() : v2->Coord();
+ auto v2Ref = v01Module > v23Module ? std::pair<gp_XYZ,gp_XYZ>(v2->Coord(),v3->Coord()) : std::pair<gp_XYZ,gp_XYZ>(v0->Coord(),v1->Coord());
+
+ auto t = ref.X() != 0. ? std::pair<double,double>( (v2Ref.first.X()-v0Ref.X())/ref.X(), (v2Ref.second.X()-v0Ref.X())/ref.X()) :
+ ref.Y() != 0. ? std::pair<double,double>( (v2Ref.first.Y()-v0Ref.Y())/ref.Y(), (v2Ref.second.Y()-v0Ref.Y())/ref.Y()) :
+ std::pair<double,double>( (v2Ref.first.Z()-v0Ref.Z())/ref.Z(), (v2Ref.second.Z()-v0Ref.Z())/ref.Z());
+
+ // check if the smaller edge contains a point inside the bigger one
+ // use the 3D line equation for this.
+ // 1) t goes from [0,1] in the reference (bigger) edge. Check if any of the points of the other edge is 0 <= t12 <= 1
+
+ if ( (t.first >= 0. && t.first <= 1.) || (t.second >= 0. && t.second <= 1.) )
+ {
+ bool isFirstVertex = t.first >= 0. && t.first <= 1.;
+ bool isSecondVertex = t.second >= 0. && t.second <= 1.;
+
+ if ( v01Module > v23Module && (isFirstVertex && isSecondVertex) /*100% edge embeded in the other && edge>gridEdge*/ )
+ {
+ int startIndex = -1;
+ int endIndex = -1;
+ bool firstToBeFound = true;
+ this->foreachNodeOnSide( edge, [&] (const std::shared_ptr<gp_Pnt> sidePoint, const int nodeIndex)
+ {
+ if ( v2->IsEqual( *sidePoint, tol ) || v3->IsEqual( *sidePoint, tol ) )
+ {
+ if ( firstToBeFound )
+ {
+ startIndex = nodeIndex;
+ firstToBeFound = false;
+ }
+ else
+ endIndex = nodeIndex;
+ }
+ });
+
+ if ( startIndex != -1 && endIndex != -1 )
+ {
+ interfaceRange = this->getEdgeIndexLimits( startIndex, endIndex );
+ interfaceDonor = grid->getEdgeIndexLimitsInverted( gridEdge );
+ }
+ }
+ else if ( (isFirstVertex && isSecondVertex) /*100% edge embeded in the other && gridEdge>edge*/ )
+ {
+ int startIndex = -1;
+ int endIndex = -1;
+ bool firstToBeFound = true;
+ grid->foreachNodeOnSide( gridEdge, [&] (const std::shared_ptr<gp_Pnt> sidePoint, const int nodeIndex)
+ {
+ if ( v0->IsEqual( *sidePoint, tol ) || v1->IsEqual( *sidePoint, tol ) )
+ {
+ if ( firstToBeFound )
+ {
+ startIndex = nodeIndex;
+ firstToBeFound = false;
+ }
+ else
+ endIndex = nodeIndex;
+ }
+ });
+
+ if ( startIndex != -1 && endIndex != -1 )
+ {
+ interfaceRange = this->getEdgeIndexLimits( edge );
+ interfaceDonor = grid->getEdgeIndexLimits( startIndex, endIndex );
+ }
+ }
+ }
+ }
+ }
+
+ if ( !interfaceRange.empty() && !interfaceDonor.empty() )
+ {
+ tranformationRange = this->computeTransformation( edge, gridEdge, interfaceRange, interfaceDonor );
+ tranformationDonor = grid->computeTransformation( gridEdge, edge, interfaceDonor, interfaceRange );
+ interface = std::vector<int>{(int)edge} + interfaceRange+interfaceDonor+tranformationRange;
+ auto dualInterface = std::vector<int>{(int)edge} + interfaceDonor+interfaceRange+tranformationDonor;
+ this->setInterface( edge, grid->id(), interface );
+ grid->setInterface( gridEdge, this->id(), dualInterface );
+ }
+ });
+}
+
+std::vector<int> SMESH_RegularGrid::computeTransformation( const SMESH_RegularGrid::EdgeType edge, SMESH_RegularGrid::EdgeType gridDonorEdge,
+ std::vector<int>& interfaceRange, std::vector<int>& interfaceDonor ) const
+{
+ std::vector<int> transform(2);
+ int r[2], d[2];
+ for(int i = 0; i < 2; i++) {
+ r[i] = interfaceRange[i + 2] - interfaceRange[i];
+ d[i] = interfaceDonor[i + 2] - interfaceDonor[i];
+ }
+ for(int i = 0; i < 2; i++) {
+ transform[i] = 0;
+ for(int j = 0; j < 2; j++) {
+ if(std::abs(r[i]) == std::abs(d[j])) { // == 0 on an interface
+ transform[i] = j + 1;
+ if(!r[i] && !d[j]) { // on an interface
+ // both interfaces correspond to a min index or to a max index
+ bool topBottom = (edge == SMESH_RegularGrid::BOTTOM || edge == SMESH_RegularGrid::TOP) && (gridDonorEdge == SMESH_RegularGrid::BOTTOM || gridDonorEdge == SMESH_RegularGrid::TOP);
+ bool leftRight = (edge == SMESH_RegularGrid::RIGHT || edge == SMESH_RegularGrid::LEFT) && (gridDonorEdge == SMESH_RegularGrid::RIGHT || gridDonorEdge == SMESH_RegularGrid::LEFT);
+ if( topBottom || leftRight )
+ transform[i] *= -1;
+ }
+ else {
+ if(r[i] * d[j] < 0) transform[i] *= -1;
+ }
+ }
+ }
+ }
+ return transform;
+}
+
+std::vector<int> SMESH_RegularGrid::computeTransformation( const SMESH_RegularGrid::FaceType face, SMESH_RegularGrid::FaceType gridDonorFace,
+ std::vector<int>& interfaceRange, std::vector<int>& interfaceDonor ) const
+{
+ std::vector<int> transform(3);
+ int r[3], d[3];
+ for(int i = 0; i < 3; i++) {
+ r[i] = interfaceRange[i + 3] - interfaceRange[i];
+ d[i] = interfaceDonor[i + 3] - interfaceDonor[i];
+ }
+ for(int i = 0; i < 3; i++) {
+ transform[i] = 0;
+ for(int j = 0; j < 3; j++) {
+ if(std::abs(r[i]) == std::abs(d[j])) { // == 0 on an interface
+ transform[i] = j + 1;
+ if(!r[i] && !d[j]) { // on an interface
+ // both interfaces correspond to a min index or to a max index
+ bool bothMin = ( face == SMESH_RegularGrid::B_BOTTOM ||
+ face == SMESH_RegularGrid::B_LEFT ||
+ face == SMESH_RegularGrid::B_FRONT ) &&
+ (gridDonorFace == SMESH_RegularGrid::B_BOTTOM ||
+ gridDonorFace == SMESH_RegularGrid::B_LEFT ||
+ gridDonorFace == SMESH_RegularGrid::B_FRONT );
+
+ bool bothMax = (face == SMESH_RegularGrid::B_TOP ||
+ face == SMESH_RegularGrid::B_RIGHT ||
+ face == SMESH_RegularGrid::B_BACK ) &&
+ (gridDonorFace == SMESH_RegularGrid::B_TOP ||
+ gridDonorFace == SMESH_RegularGrid::B_RIGHT ||
+ gridDonorFace == SMESH_RegularGrid::B_FRONT );
+
+ if( bothMin || bothMax )
+ transform[i] *= -1;
+ }
+ else {
+ if(r[i] * d[j] < 0) transform[i] *= -1;
+ }
+ }
+ }
+ }
+ return transform;
+}
+
+void SMESH_RegularGrid::setInterface( SMESH_RegularGrid::EdgeType edge, const int gridId, std::vector<int>& interface )
+{
+ myInterfaceMap[edge][gridId] = interface;
+}
+
+void SMESH_RegularGrid::setInterface( SMESH_RegularGrid::FaceType face, const int gridId, std::vector<int>& interface )
+{
+ myFaceInterafaceMap[face][gridId] = interface;
+}
+
+SMESH_RegularGrid::FaceType SMESH_RegularGrid::getFaceTypeByGeomFace( TopoDS_Shape shapeFace ) const
+{
+ const double tol = Precision::Confusion();
+ SMESH_RegularGrid::FaceType foundFace = SMESH_RegularGrid::B_NONE;
+ this->foreachGridFace( [&]( FaceType face )
+ {
+ auto faceLimits = getFaceLimits(face);
+ auto v0 = myCoordinates[std::get<0>(faceLimits)];
+ auto v1 = myCoordinates[std::get<1>(faceLimits)];
+ auto v2 = myCoordinates[std::get<2>(faceLimits)];
+ auto v3 = myCoordinates[std::get<3>(faceLimits)];
+ int nVertex = 0;
+ int nVertexInFace = 0;
+ for ( TopExp_Explorer fEx( shapeFace, TopAbs_VERTEX ); fEx.More(); fEx.Next() )
+ {
+ gp_Pnt pV = BRep_Tool::Pnt( TopoDS::Vertex(fEx.Current()) );
+ nVertexInFace += int( v0->IsEqual(pV,tol) ) + int( v1->IsEqual(pV,tol) ) + int( v2->IsEqual(pV,tol) ) + int( v3->IsEqual(pV,tol) ) ;
+ nVertex++;
+ }
+ if ( nVertex == nVertexInFace )
+ {
+ foundFace = face;
+ return;
+ }
+ });
+
+ return foundFace;
+}
+
+SMESH_RegularGrid::EdgeType SMESH_RegularGrid::getEdgeTypeByGeomEdge( TopoDS_Shape shapeEdge ) const
+{
+ const double tol = Precision::Confusion();
+ SMESH_RegularGrid::EdgeType foundEdge = SMESH_RegularGrid::NONE;
+ this->foreachGridSide ( [&]( EdgeType edge )
+ {
+ auto edgeLimits = getEdgeLimits(edge);
+ auto v0 = myCoordinates[edgeLimits.first];
+ auto v1 = myCoordinates[edgeLimits.second];
+ int nVertex = 0;
+ int nVertexInEdge = 0;
+ for ( TopExp_Explorer fEx( shapeEdge, TopAbs_VERTEX ); fEx.More(); fEx.Next() )
+ {
+ gp_Pnt pV = BRep_Tool::Pnt( TopoDS::Vertex(fEx.Current()) );
+ nVertexInEdge += int( v0->IsEqual(pV,tol) ) + int( v1->IsEqual(pV,tol) );
+ nVertex++;
+ }
+ if ( nVertex == nVertexInEdge )
+ {
+ foundEdge = edge;
+ return;
+ }
+ });
+
+ return foundEdge;
+}
+
+bool SMESH_RegularGrid::GetPrecomputedInterface( EdgeType edge, const SMESH_RegularGrid * grid, std::vector<int>& interface )
+{
+ if ( myInterfaceMap.count(edge) && myInterfaceMap[edge].count(grid->id()) )
+ {
+ interface = myInterfaceMap[edge][grid->id()];
+ return true;
+ }
+ return false;
+}
+
+bool SMESH_RegularGrid::GetPrecomputedInterface( FaceType face, const SMESH_RegularGrid * grid, std::vector<int>& interface )
+{
+ if ( myFaceInterafaceMap.count(face) && myFaceInterafaceMap[face].count(grid->id()) )
+ {
+ interface = myFaceInterafaceMap[face][grid->id()];
+ return true;
+ }
+ return false;
+}
+
+void SMESH_RegularGrid::GetEdgeInterfaces( SMESH_RegularGrid * grid, std::vector<int>& interface )
+{
+ this->foreachGridSide( [&]( EdgeType edge )
+ {
+ if ( !this->GetPrecomputedInterface( edge, grid, interface ) )
+ this->GetCommontInterface( edge, grid, interface );
+ });
+}
+
+void SMESH_RegularGrid::GetFaceInterfaces( SMESH_RegularGrid * grid, std::vector<int>& interface )
+{
+ this->foreachGridFace( [&]( FaceType face )
+ {
+ if ( !this->GetPrecomputedInterface( face, grid, interface ) )
+ this->GetCommontInterface( face, grid, interface );
+ });
+}
+
+
+SMESH_RegularGrid::~SMESH_RegularGrid()
+{
+ myInterfaceMap.clear();
+ myFaceInterafaceMap.clear();
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2016-2024 CEA, EDF
+//
+// 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, or (at your option) any later version.
+//
+// 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_RegularGrid.hxx
+// Created : Sun March 24 09:58 2024
+// Author : Cesar Conopoima (cce)
+
+
+#ifndef __SMESH_RegularGrid_HXX__
+#define __SMESH_RegularGrid_HXX__
+
+//OCC
+#include <Precision.hxx>
+#include <NCollection_Array1.hxx>
+
+//STD
+#include <functional>
+#include <memory>
+
+#include "SMESH_Utils.hxx"
+#include "SMDS_MeshNode.hxx"
+
+#include <gp_Pnt.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_DataMapOfShapeReal.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS.hxx>
+#include <vector>
+#include <map>
+
+class Adaptor3d_Surface;
+class Adaptor2d_Curve2d;
+class Adaptor3d_Curve;
+class gp_Pnt;
+class gp_XYZ;
+
+template <typename T>
+std::vector<T> operator+(std::vector<T> const &x, std::vector<T> const &y)
+{
+ std::vector<T> vec;
+ vec.reserve(x.size() + y.size());
+ vec.insert(vec.end(), x.begin(), x.end());
+ vec.insert(vec.end(), y.begin(), y.end());
+ return vec;
+}
+
+namespace SMESHUtils
+{
+ /*!
+ * \brief Define a regular grid of nx,ny,nz dimension. A vector with gp_Pnt is
+ * defined by default by a canonical order, the canonical order is:
+ * i-index goes faster, then j-index and finaly z-index.
+ * This data structure was created to index mesh nodes created by Quadrangle_2D and Prism_3D meshers.
+ * The StructuredCGNS export driver uses this data structure to define zones, grid coordinate points and interfaces.
+ */
+ class SMESHUtils_EXPORT SMESH_RegularGrid
+ {
+ public:
+
+ SMESH_RegularGrid( const int id, const int nx, const int ny, const int nz = 1 );
+ void SetNode( const std::shared_ptr<gp_Pnt>& point, const int iIndex, const int jIndex, const int zIndex = 0 );
+ void SetNode( const SMDS_MeshNode* point, const int iIndex, const int jIndex, const int zIndex = 0 );
+ void SetNode( const SMDS_MeshNode* point, const int index );
+ const std::shared_ptr<gp_Pnt> GetNode( const int index ) const { return myCoordinates[index]; };
+ const std::shared_ptr<gp_Pnt> GetNode( const int iIndex, const int jIndex, const int zIndex );
+ int nx() const { return mnx; };
+ int ny() const { return mny; };
+ int nz() const { return mnz; };
+ int Size() { return mns;};
+ NCollection_Array1<std::shared_ptr<gp_Pnt>>::Iterator CoordinateBegin() { return NCollection_Array1<std::shared_ptr<gp_Pnt>>::Iterator( myCoordinates ); };
+ int id() const { return myId; };
+
+ /*
+ *
+ * o------TOP (j=ny-1)----o
+ * | |
+ * | |
+ * | |
+ * LEFT (i=0) RIGTH(i=nx-1)
+ * | |
+ * | |
+ * | |
+ * o------BOTTOM(j=0)-----o
+ */
+ enum EdgeType
+ {
+ BOTTOM,
+ RIGHT,
+ TOP,
+ LEFT,
+ NONE /**/
+ };
+
+ enum VertexType
+ {
+ V0,
+ V1,
+ V2,
+ V3,
+ V4,
+ V5,
+ V6,
+ V7
+ };
+ /* Define vertex numeration convention
+ *
+ * V7 V6
+ * +--------+--------+--------+
+ * / / / /|
+ * +--------+--------+--------+ |
+ * / / / /| |
+ * +--------+--------+--------+ | +
+ * / / / V5 /| |/|
+ * V4 +--------+--------+--------+ | + |
+ * | | | |/| |
+ * | | | + | +
+ * | | |/| |/|
+ * + | | + |
+ * | | | |/| |
+ * | +-------+----------+-| + | + V2
+ * | / V3 |/| |/
+ * + / | +
+ * | / | |/
+ * | / | +
+ * |/ |/
+ * +--------+--------+--------+
+ * V0 V1
+ *
+ * Canonical cartesian axis orientation
+ *
+ * ^ ^ j (or y)
+ * k (or z)| /
+ * | /
+ * |/
+ * +------> i (or x)
+ *
+ *
+ */
+
+ enum FaceType
+ {
+ B_BOTTOM, /*k=0 move (i,j)*/
+ B_RIGHT, /*i=mnx move (j,k)*/
+ B_BACK, /*j=mny move (i,k)*/
+ B_LEFT, /*i=0 move (j,k) */
+ B_FRONT, /*j=0 move (i,k)*/
+ B_TOP, /*k=mnz move (i,j) */
+ B_NONE /**/
+ };
+
+ /*
+ * +--------+--------+--------+
+ * / / / /|
+ * +--------+--------+--------+ |
+ * / / Top / /| |
+ * +--------+--------+--------+ | +
+ * / / / /| |/|
+ * +--------+--------+--------+ | + |
+ * | | | | |/| | <- Right
+ * | | | | + | +
+ * | | | |/| |/|
+ * +--------+--------+--------+ | + |
+ * Left -> | | Front | | |/| |
+ * | | | | + | +
+ * | | | |/| |/
+ * +--------+--------+--------+ | +
+ * | | | | |/
+ * | | | | +
+ * | | | |/
+ * +--------+--------+--------+
+ * ^
+ * |
+ * Bottom
+ *
+ * Canonical cartesian axis orientation
+ *
+ * ^ ^ j (or y)
+ * k (or z)| /
+ * | /
+ * |/
+ * +------> i (or x)
+ *
+ *
+ */
+
+ // \brief Given a grid and a potentially neigbor grid return the vector describing the interface used by the cgns mesh format
+ // \remark the interface vector has the follow informations:
+ // id the target range the donor range the transformation
+ // {edgeId, ibegin,jbegin, iend,jend, transformation}
+ // \remark As interfaces are unique, the dual interface (interaction of the neighbor grid and the current one) is also defined
+ // \param the neighbor grid
+ // \return the interface vector filled
+ void GetEdgeInterfaces( SMESH_RegularGrid * grid, std::vector<int>& interface );
+
+ // \brief Given a grid and a potentially neigbor grid return the vector describing the interface used by the cgns mesh format
+ // \remark the interface vector has the follow informations:
+ // id the target range the donor range the transformation
+ // {edgeId, ibegin,jbegin,kbegin, iend,jend,kend, transformation}
+ // \remark As interfaces are unique, the dual interface (interaction of the neighbor grid and the current one) is also defined
+ // \param the neighbor grid
+ // \return the interface vector filled
+ void GetFaceInterfaces( SMESH_RegularGrid * grid, std::vector<int>& interface );
+
+ // \brief Fill the allRanges vector with the boundaries of the grid
+ void getAllEdgeIndexLimits( std::vector<std::vector<int>>& allRanges );
+
+ // \brief Fill the allRanges vector with the boundaries of the grid
+ void getAllFaceIndexLimits( std::vector<std::vector<int>>& allRanges );
+
+ // \brief Get limits of the edge in the order (ibegin,jbegin,iend,jend)+1 because index in CGNS are not zero based
+ std::vector<int> getEdgeIndexLimits( const EdgeType edge ) const;
+
+ // \brief Get limits of the edge in the order (iend,jend,ibegin,jbegin)+1 because index in CGNS are not zero based
+ std::vector<int> getEdgeIndexLimitsInverted( const EdgeType edge ) const;
+
+ // \brief Get limits of the face in the order (ibegin,jbegin,kbegin,iend,jend,kend)+1 because index in CGNS are not zero based
+ std::vector<int> getFaceIndexLimits( SMESH_RegularGrid::FaceType face ) const;
+
+ // \brief Return the faceType to which the passed geometrical face belows to
+ SMESH_RegularGrid::FaceType getFaceTypeByGeomFace( TopoDS_Shape shapeFace ) const;
+
+ // \brief Return the edgeType to which the passed geometrical edge belows to
+ SMESH_RegularGrid::EdgeType getEdgeTypeByGeomEdge( TopoDS_Shape shapeEdge ) const;
+
+ ~SMESH_RegularGrid();
+
+ protected:
+
+ // Utility functions
+
+ // \brief Given one of the edge types and a grid determine whether or not they are adjacent on that side
+ // \remark There are three types of interfaces.
+ // 1) end to end intersection, both sides are exactly the same
+ // 2) one of the sides is smaller than the other but the grid are conform so the intersection is given exacly node by node
+ // 3) the same for 2) but nodes are not coincident
+ // \param edge, the edge where we are checking for interface
+ // \param grid, a neighbor grid
+ // \return interface, the interface vector filled in case an interface was found
+ void GetCommontInterface( EdgeType edge, SMESH_RegularGrid * grid, std::vector<int>& interface );
+ void GetCommontInterface( FaceType face, SMESH_RegularGrid * grid, std::vector<int>& interface );
+
+ // \brief Accessor method to interfaces already computed by other grid
+ // \param edge, the edge where we are checking for interface
+ // \param grid, a neighbor grid
+ // \param interface, the interface vector filled in case an interface was found
+ bool GetPrecomputedInterface( EdgeType edge, const SMESH_RegularGrid * grid, std::vector<int>& interface );
+
+ // \brief Accessor method to interfaces already computed by other grid
+ // \param face, the face where we are checking for interface
+ // \param grid, a neighbor grid
+ // \param interface, the interface vector filled in case an interface was found
+ bool GetPrecomputedInterface( FaceType face, const SMESH_RegularGrid * grid, std::vector<int>& interface );
+
+ // \brief Set the interface found between two neighbor grids.
+ // \remark fill the inner map between edges and grids used to recover precomputed interfaces with GetPrecomputedInterface method
+ void setInterface( SMESH_RegularGrid::EdgeType edge, const int gridId, std::vector<int>& interface );
+
+ // \brief Set the interface found between two neighbor grids.
+ // \remark fill the inner map between edges and grids used to recover precomputed interfaces with GetPrecomputedInterface method
+ void setInterface( SMESH_RegularGrid::FaceType face, const int gridId, std::vector<int>& interface );
+
+ // \brief Get the coordinate indexes defining the limit of the edge
+ std::pair<int,int> getEdgeLimits( const SMESH_RegularGrid::EdgeType edge ) const;
+
+ // \brief Get the coordinate indexes defining the limit of the face
+ std::tuple<int,int,int,int> getFaceLimits( const SMESH_RegularGrid::FaceType face ) const;
+
+ // \brief Get limits of the edge in the order (ibegin,jbegin,iend,jend)+1 because index in CGNS are not zero based
+ std::vector<int> getEdgeIndexLimits( const int start, const int end ) const;
+ std::vector<int> getFaceIndexLimits( const int start, const int end ) const;
+
+ // \brief Compute the tranformation vector following the rules of the cgns format
+ std::vector<int> computeTransformation( const SMESH_RegularGrid::EdgeType edge, SMESH_RegularGrid::EdgeType gridDonorEdge, std::vector<int>& interfaceRange, std::vector<int>& interfaceDonor ) const;
+
+ // \brief Compute the tranformation vector following the rules of the cgns format
+ std::vector<int> computeTransformation( const SMESH_RegularGrid::FaceType face, SMESH_RegularGrid::FaceType gridDonorFace, std::vector<int>& interfaceRange, std::vector<int>& interfaceDonor ) const;
+
+ // \brief Number of nodes on the edge
+ int getEdgeSize(const EdgeType edge ) const;
+
+ // \brief Number of nodes on the face
+ int getFaceSize(const FaceType face ) const;
+
+ // \brief Coordinate index of the given vertex
+ int getFaceCoordinateIndex( const VertexType v ) const;
+
+ // \brief Given the index of a coordinate return his (i,j,k) location in the grid
+ // \param the index in the coordinates vector
+ // \return a tuple with the (i,j,k) coordinates of the point in the grid
+ std::tuple<int,int,int> GetIJK( const int index ) const;
+
+ // \brief Iterator function to execute the 'fSide' function for each edge side of the grid
+ // \remark utility function to be used as:
+ // grid->foreachGridSide( [&]( EdgeType edge )
+ // {
+ // // Inner logic to be execute for each side of the grid
+ // });
+ template<typename FUNCTION>
+ void foreachGridSide( const FUNCTION& fSide ) const;
+
+ // \brief Iterator function to execute the 'fSide' function for each face side of the grid
+ // \remark utility function to be used as:
+ // grid->foreachGridFace( [&]( FaceType face )
+ // {
+ // // Inner logic to be execute for each face side of the grid
+ // });
+ template<typename FUNCTION>
+ void foreachGridFace( const FUNCTION& fSide ) const;
+
+ // \brief Iterator function to execute the lambda function with argument for each grid point and index in the gridEdge
+ // \remark utility function to be used as:
+ // grid->foreachNodeOnSide( gridEdge, [&]( (const std::shared_ptr<gp_Pnt> , const int nodeIndex ) )
+ // {
+ // // Inner logic to be execute for each node and index of the passed grid edge side
+ // });
+ void foreachNodeOnSide( SMESH_RegularGrid::EdgeType edge, const std::function<void(const std::shared_ptr<gp_Pnt> point, const int index )>& function ) const;
+
+ // \brief Iterator function to execute the lambda function with argument for each grid point and index in the gridFace
+ // \remark utility function to be used as:
+ // grid->foreachNodeOnFace( gridFace, [&]( (const std::shared_ptr<gp_Pnt>, const int nodeIndex ) )
+ // {
+ // // Inner logic to be execute for each node and index of the passed grid face side
+ // });
+ void foreachNodeOnFace( SMESH_RegularGrid::FaceType face, const std::function<void(const std::shared_ptr<gp_Pnt> point, const int index )>& function ) const;
+
+ // \brief Get all the indices of nodes in an edge side
+ // \param edge, the edge of the grid
+ // \return the index of all the nodes in the edge
+ std::vector<int> nodesOfSide( SMESH_RegularGrid::EdgeType edge ) const;
+
+ // \brief Get all the indices of nodes in an face side
+ // \param face, the face of the grid
+ // \return the index of all the nodes in the face
+ std::vector<int> nodesOfFace( SMESH_RegularGrid::FaceType face ) const;
+
+ private:
+ int myId;
+ int mnx,mny,mnz,mns;
+ NCollection_Array1<std::shared_ptr<gp_Pnt>> myCoordinates;
+
+ std::map<SMESH_RegularGrid::EdgeType,std::map<int,std::vector<int>>> myInterfaceMap;
+ std::map<SMESH_RegularGrid::FaceType,std::map<int,std::vector<int>>> myFaceInterafaceMap;
+ };
+}
+
+#endif
--- /dev/null
+// Copyright (C) 2016-2024 CEA, EDF
+//
+// 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, or (at your option) any later version.
+//
+// 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_TemplateRegularGrid.hxx
+// Created : Fry April 05 11:20 2024
+// Author : Cesar Conopoima (cce)
+
+
+#ifndef __SMESH_RegularGridTemplate_HXX__
+#define __SMESH_RegularGridTemplate_HXX__
+
+//STD
+#include <functional>
+
+//SMESH::Utils
+#include "SMESH_RegularGrid.hxx"
+
+namespace SMESHUtils
+{
+ template<typename FUNCTION>
+ void SMESH_RegularGrid::foreachGridSide( const FUNCTION& fSide ) const
+ {
+ for (size_t edgeType = BOTTOM; edgeType <= LEFT; edgeType++)
+ fSide( static_cast<EdgeType>( edgeType ) );
+ }
+
+ template<typename FUNCTION>
+ void SMESH_RegularGrid::foreachGridFace( const FUNCTION& fSide ) const
+ {
+ for (size_t faceType = B_BOTTOM; faceType <= B_TOP; faceType++)
+ fSide( static_cast<FaceType>( faceType ) );
+ }
+
+ void SMESH_RegularGrid::foreachNodeOnSide( SMESH_RegularGrid::EdgeType edge, const std::function<void(const std::shared_ptr<gp_Pnt> point, const int index )>& function ) const
+ {
+ for (auto node : nodesOfSide(edge))
+ function(myCoordinates[node],node);
+ }
+
+ void SMESH_RegularGrid::foreachNodeOnFace( SMESH_RegularGrid::FaceType face, const std::function<void(const std::shared_ptr<gp_Pnt> point, const int index )>& function ) const
+ {
+ for (auto node : nodesOfFace(face))
+ function(myCoordinates[node],node);
+ }
+}
+
+
+#endif
//================================================================================
/*!
- * \brief Export a part of mesh to an STL file
+ * \brief Export a part of mesh to an CGNS file
*/
//================================================================================
#endif
}
+//================================================================================
+/*!
+ * \brief Export a part of mesh to an StructuredCGNS file
+ */
+//================================================================================
+
+void SMESH_Mesh_i::ExportStructuredCGNS( SMESH::SMESH_IDSource_ptr meshPart,
+ const char* file,
+ CORBA::Boolean overwrite )
+{
+#ifdef WITH_CGNS
+ SMESH_TRY;
+ if ( _preMeshInfo )
+ _preMeshInfo->FullLoadFromFile();
+
+ PrepareForWriting(file,overwrite);
+
+ std::string meshName("");
+ SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( meshPart );
+ if ( !so->_is_nil() )
+ {
+ CORBA::String_var name = so->GetName();
+ meshName = name.in();
+ }
+ SMESH_TRY;
+
+ SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
+ SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
+ mesh_i->Load();
+ auto myMesh = mesh_i->GetImpl().GetMeshDS();
+ _impl->ExportStructuredCGNS(file, myMesh, meshName.c_str());
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+
+ TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportStructuredCGNS( "
+ "r'" << file << "', " << overwrite << ", " << meshPart << ")";
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+
+#else
+ THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
+#endif
+}
+
//================================================================================
/*!
* \brief Export a part of mesh to a GMF file
void ExportDAT( const char* file, const CORBA::Boolean renumber );
void ExportUNV( const char* file, const CORBA::Boolean renumber );
void ExportSTL( const char* file, bool isascii );
+
+ void ExportStructuredCGNS(SMESH::SMESH_IDSource_ptr meshPart,
+ const char* file,
+ CORBA::Boolean overwrite);
+
void ExportCGNS(SMESH::SMESH_IDSource_ptr meshPart,
const char* file,
CORBA::Boolean overwrite,
CORBA::Boolean renumber);
void ExportPartToSTL(SMESH::SMESH_IDSource_ptr meshPart,
const char* file,
- CORBA::Boolean isascii);
+ CORBA::Boolean isascii);
CORBA::Double GetComputeProgress();
meshPart = self.mesh
self.mesh.ExportCGNS(meshPart, f, overwrite, groupElemsByType)
+ def ExportStructuredCGNS(self, f, overwrite=1, meshPart=None ):
+ """
+ Export the mesh in a file in Structured CGNS format
+
+ Parameters:
+ f: is the file name
+ overwrite: boolean parameter for overwriting/not overwriting the file
+ meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`) to export instead of the mesh
+ """
+
+ unRegister = genObjUnRegister()
+ if isinstance( meshPart, list ):
+ meshPart = self.GetIDSource( meshPart, SMESH.ALL )
+ unRegister.set( meshPart )
+ if isinstance( meshPart, Mesh ):
+ meshPart = meshPart.mesh
+ elif not meshPart:
+ meshPart = self.mesh
+ self.mesh.ExportStructuredCGNS(meshPart, f, overwrite)
+
def ExportGMF(self, f, meshPart=None):
"""
Export the mesh in a file in GMF format.
// compute internal node coordinates
gp_XYZ coords;
SMESH_Block::ShellPoint( params, pointsOnShapes, coords );
- column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() );
+ column[ z ] = helper.AddNode( coords.X(), coords.Y(), coords.Z() );
} // z loop
if ( toRenumber )
// 5) Create hexahedrons
// ---------------------
-
for ( x = 0; x < xSize-1; ++x ) {
for ( y = 0; y < ySize-1; ++y ) {
vector< const SMDS_MeshNode* >& col00 = columns[ colIndex( x, y )];
for ( z = 0; z < zSize-1; ++z )
{
// bottom face normal of a hexa mush point outside the volume
- if ( toRenumber )
+ if ( toRenumber )
+ {
helper.AddVolume(col00[z], col01[z], col01[z+1], col00[z+1],
- col10[z], col11[z], col11[z+1], col10[z+1]);
+ col10[z], col11[z], col11[z+1], col10[z+1]);
+ }
else
+ {
helper.AddVolume(col00[z], col01[z], col11[z], col10[z],
- col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
+ col00[z+1], col01[z+1], col11[z+1], col10[z+1]);
+ }
}
}
}
if ( toRenumber )
renumHelper.DoReplaceNodes();
+ meshDS->SetStructuredGrid( aShape, zSize, ySize, xSize );
+ for ( x = 0; x < xSize; ++x )
+ for ( y = 0; y < ySize; ++y )
+ for ( z = 0; z < zSize; ++z )
+ meshDS->SetNodeOnStructuredGrid( aShape, columns[colIndex(x,y)][z], z, y, x );
if ( _blockRenumberHyp )
{
SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
Handle(Geom_Surface) S = BRep_Tool::Surface(aFace);
int i,j, geomFaceID = meshDS->ShapeToIndex(aFace);
+
+ meshDS->SetStructuredGrid( aFace, nbhoriz, nbvertic );
+ for (j = 0; j < nbvertic; j++)
+ for (i = 0; i < nbhoriz; i++)
+ {
+ UVPtStruct& uvPnt = quad->UVPt( i, j );
+ auto P = std::make_shared<gp_Pnt>( S->Value( uvPnt.u, uvPnt.v ).Coord() );
+ meshDS->SetNodeOnStructuredGrid( aFace, P, i, j );
+ }
+
for (i = 1; i < nbhoriz - 1; i++)
for (j = 1; j < nbvertic - 1; j++)
{
COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_SOURCE_DIR}/test/test_helper.py ${CMAKE_CURRENT_SOURCE_DIR}/${_test})
SET_TESTS_PROPERTIES(${testname} PROPERTIES ENVIRONMENT "${tests_env}" LABELS "tests")
ENDFOREACH()
+
+INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}/src/SMESHUtils
+ ${PROJECT_SOURCE_DIR}/src/SMDS
+ )
+
+FOREACH(_test ${CPP_TESTS})
+ GET_FILENAME_COMPONENT(testname ${_test} NAME_WE)
+ SET(testname "TESTS_${testname}")
+
+ add_executable(${_test} ${_test}.cxx)
+ target_link_libraries(${_test} SMESHUtils SMDS )
+
+ ADD_TEST(NAME ${testname}
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/${_test} )
+ SET_TESTS_PROPERTIES(${testname} PROPERTIES ENVIRONMENT "${tests_env}" LABELS "tests")
+ENDFOREACH()
+
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CPP_TESTS} PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ DESTINATION ${TEST_INSTALL_DIRECTORY})
ADD_TEST(${TEST_NAME} python ${tfile})
SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${COMPONENT_NAME};${COMPONENT_NAME}_tests")
endforeach()
+
+FOREACH(tfile ${CPP_TESTS})
+ GET_FILENAME_COMPONENT(BASE_NAME ${tfile} NAME_WE)
+ SET(TEST_NAME SMESH_${BASE_NAME})
+ ADD_TEST(${TEST_NAME} SMESH_RegularGridTest )
+ SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES LABELS "${COMPONENT_NAME};${COMPONENT_NAME}_tests")
+endforeach()
--- /dev/null
+// Copyright (C) 2016-2024 CEA, EDF
+//
+// 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, or (at your option) any later version.
+//
+// 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_RegularGridTest.cxx (unit test)
+// Author : Cesar Conopoima (cce)
+
+// std
+#include<iostream>
+#include <memory>
+
+// smesh
+#include "SMESH_RegularGridTemplate.hxx"
+#include "SMDS_MeshNode.hxx"
+
+bool testConstructor()
+{
+ auto regularGrid2D = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(0,5,4));
+ if ( regularGrid2D->Size() != 5*4 ) throw std::runtime_error("2D Grid size not match in testConstructor()\n");
+ auto regularGrid3D = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(0,5,4,20));
+ if ( regularGrid3D->Size() != 5*4*20 ) throw std::runtime_error("3D Grid size not match in testConstructor()\n");
+ return true;
+}
+
+bool testSetGetNode()
+{
+ auto regularGrid = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(0,5,4));
+ double x,y;
+
+ for (size_t j = 0; j < 4; j++)
+ for (size_t i = 0; i < 5; i++)
+ {
+ x = i * 0.1;
+ y = j * 0.1;
+ auto node = std::make_shared<gp_Pnt>( x, y, 0. );
+ regularGrid->SetNode( node, i, j );
+ }
+ for (size_t j = 0; j < 4; j++)
+ for (size_t i = 0; i < 5; i++)
+ {
+ x = i * 0.1;
+ y = j * 0.1;
+ auto node = regularGrid->GetNode( i, j, 0 );
+ if ( node == nullptr ) throw std::runtime_error("error getting node in testSetGetNode()\n");
+ if ( node->X() != x ||
+ node->Y() != y ||
+ node->Z() != 0. ) throw std::runtime_error("error for node not in the correct position in testSetGetNode()\n");
+ }
+
+ return true;
+}
+
+bool testGetCommontInterface1D()
+{
+ int mnx = 5, mny = 4;
+ auto regularGrid0 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(0,mnx,mny));
+ auto regularGrid1 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(1,mnx,mny));
+ double x,y;
+
+ /*side by side grid with 1to1 interface*/
+ /* o-o-o-o-oxo-o-o-o-o */
+ /* o-oG0-o-oxo-o-G1o-o */
+ /* o-o-o-o-oxo-o-o-o-o */
+ /* o-o-o-o-oxo-o-o-o-o */
+
+ for (size_t j = 0; j < mny; j++)
+ for (size_t i = 0; i < mnx; i++)
+ {
+ x = i * 0.1;
+ y = j * 0.1;
+ auto node0 = std::make_shared<gp_Pnt>(x,y,0.);
+ regularGrid0->SetNode( node0, i, j );
+
+ x = i * 0.1 + 0.4;
+ y = j * 0.1;
+ auto node1 = std::make_shared<gp_Pnt>(x,y,0.);
+ regularGrid1->SetNode( node1, i, j );
+ }
+
+ std::vector<int> interface; /* interface at right */
+ regularGrid0->GetEdgeInterfaces( regularGrid1.get(), interface );
+ std::vector<int> expectedRange = regularGrid0->getEdgeIndexLimits(SMESHUtils::SMESH_RegularGrid::RIGHT);
+ std::vector<int> expectedDonorRange = regularGrid1->getEdgeIndexLimitsInverted(SMESHUtils::SMESH_RegularGrid::LEFT);
+
+ if ( interface.size() != 1+mny*2+2 )
+ throw std::runtime_error("1to1 edge interface not found in testGetCommontInterface1D()\n");
+
+ if ( interface[0] != int(SMESHUtils::SMESH_RegularGrid::RIGHT) )
+ throw std::runtime_error("edge found in interface is incorrect testGetCommontInterface1D()\n");
+
+ for (size_t i = 0; i < 4; i++)
+ if ( interface[i+1] != expectedRange[i])
+ throw std::runtime_error("interface range index is incorrect in testGetCommontInterface1D()\n");
+
+ for (size_t i = 0; i < 4; i++)
+ if ( interface[i+5] != expectedDonorRange[i])
+ throw std::runtime_error("interface donor index is incorrect in testGetCommontInterface1D()\n");
+
+ return true;
+}
+
+bool testGetCommontInterface2D()
+{
+ int mnx = 5, mny = 4, mnz = 2;
+ auto regularGrid0 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(0,mnx,mny,mnz));
+ auto regularGrid1 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(1,mnx,mny,mnz));
+ auto regularGrid2 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(2,mnx,mny,mnz));
+ auto regularGrid3 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(3,mnx,mny,mnz));
+ auto regularGrid4 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(4,mnx,mny,mnz));
+ auto regularGrid5 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(5,mnx,mny,mnz));
+ auto regularGrid6 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(6,mnx,mny,mnz));
+ double x,y,z;
+
+ for (size_t k = 0; k < mnz; k++)
+ for (size_t j = 0; j < mny; j++)
+ for (size_t i = 0; i < mnx; i++)
+ {
+ x = i * 0.1;
+ y = j * 0.1;
+ z = k * 0.1;
+ auto node0 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid0->SetNode( node0, i, j, k );
+
+ // Grid at botton
+ x = i * 0.1;
+ y = j * 0.1;
+ z = k * 0.1-0.1;
+ auto node1 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid1->SetNode( node1, i, j, k );
+
+ // Grid at right
+ x = i * 0.1+0.4;
+ y = j * 0.1;
+ z = k * 0.1;
+ auto node2 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid2->SetNode( node2, i, j, k );
+
+ // Grid at back
+ x = i * 0.1;
+ y = j * 0.1+0.3;
+ z = k * 0.1;
+ auto node3 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid3->SetNode( node3, i, j, k );
+
+ // Grid at left
+ x = i * 0.1-0.4;
+ y = j * 0.1;
+ z = k * 0.1;
+ auto node4 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid4->SetNode( node4, i, j, k );
+
+ // Grid at front
+ x = i * 0.1;
+ y = j * 0.1-0.3;
+ z = k * 0.1;
+ auto node5 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid5->SetNode( node5, i, j, k );
+
+ // Grid on top
+ x = i * 0.1;
+ y = j * 0.1;
+ z = k * 0.1+0.1;
+ auto node6 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid6->SetNode( node6, i, j, k );
+ }
+
+ std::vector<std::vector<int>> interface(6);
+ std::vector<std::vector<int>> expectedRange(6);
+ std::vector<std::vector<int>> expectedDonorRange(6);
+
+ regularGrid0->GetFaceInterfaces( regularGrid1.get(), interface[0] );
+ regularGrid0->GetFaceInterfaces( regularGrid2.get(), interface[1] );
+ regularGrid0->GetFaceInterfaces( regularGrid3.get(), interface[2] );
+ regularGrid0->GetFaceInterfaces( regularGrid4.get(), interface[3] );
+ regularGrid0->GetFaceInterfaces( regularGrid5.get(), interface[4] );
+ regularGrid0->GetFaceInterfaces( regularGrid6.get(), interface[5] );
+
+ expectedRange[0] = regularGrid0->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_BOTTOM);
+ expectedRange[1] = regularGrid0->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_RIGHT);
+ expectedRange[2] = regularGrid0->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_BACK);
+ expectedRange[3] = regularGrid0->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_LEFT);
+ expectedRange[4] = regularGrid0->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_FRONT);
+ expectedRange[5] = regularGrid0->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_TOP);
+
+ expectedDonorRange[0] = regularGrid1->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_TOP);
+ expectedDonorRange[1] = regularGrid2->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_LEFT);
+ expectedDonorRange[2] = regularGrid3->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_FRONT );
+ expectedDonorRange[3] = regularGrid4->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_RIGHT);
+ expectedDonorRange[4] = regularGrid5->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_BACK);
+ expectedDonorRange[5] = regularGrid6->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_BOTTOM);
+
+ int interfaceSize = 1+6*2+3;
+ for ( auto itf : interface )
+ {
+ if ( itf.size() != interfaceSize )
+ throw std::runtime_error("1to1 face interface not found in testGetCommontInterface2D()\n");
+ }
+
+ int count = 0;
+ for ( auto itf : interface )
+ {
+ if ( itf[0] != count /*face id of the interface*/)
+ throw std::runtime_error("face found in interface is incorrect testGetCommontInterface2D()\n");
+
+ for (size_t i = 0; i < 6; i++)
+ if ( itf[i+1] != expectedRange[count][i])
+ throw std::runtime_error("interface range index is incorrect in testGetCommontInterface2D()\n");
+
+ for (size_t i = 0; i < 6; i++)
+ if ( itf[i+7] != expectedDonorRange[count][i])
+ throw std::runtime_error("interface donor index is incorrect in testGetCommontInterface2D()\n");
+ count++;
+ }
+
+ return true;
+}
+
+bool testGetPartialInterface2D()
+{
+ int mnx = 5, mny = 4, mnz = 3;
+ int mnxf = 2, mnyf = 2, mnzf = 2;
+ int mnxl = 2, mnyl = 3, mnzl = 2;
+ auto regularGrid0 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(0,mnx,mny,mnz));
+ auto regularGrid1 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(1,mnxf,mnyf,mnzf));
+ auto regularGrid2 = std::unique_ptr<SMESHUtils::SMESH_RegularGrid>( new SMESHUtils::SMESH_RegularGrid(2,mnxl,mnyl,mnzl));
+ double x,y,z;
+
+ for (size_t k = 0; k < mnz; k++)
+ for (size_t j = 0; j < mny; j++)
+ for (size_t i = 0; i < mnx; i++)
+ {
+ x = i * 0.1;
+ y = j * 0.1;
+ z = k * 0.1;
+ auto node0 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid0->SetNode( node0, i, j, k );
+ }
+
+ for (size_t k = 0; k < mnzf; k++)
+ for (size_t j = 0; j < mnyf; j++)
+ for (size_t i = 0; i < mnxf; i++)
+ {
+ // Grid at front
+ x = i * 0.1+0.3;
+ y = -j * 0.1;
+ z = k * 0.1+0.1;
+ auto node1 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid1->SetNode( node1, i, j, k );
+ }
+
+ for (size_t k = 0; k < mnzl; k++)
+ for (size_t j = 0; j < mnyl; j++)
+ for (size_t i = 0; i < mnxl; i++)
+ {
+ // Grid at left
+ x = -i * 0.1;
+ y = j * 0.1+0.1;
+ z = k * 0.1;
+ auto node2 = std::make_shared<gp_Pnt>(x,y,z);
+ regularGrid2->SetNode( node2, i, j, k );
+ }
+
+ std::vector<std::vector<int>> interface(2);
+ std::vector<int> faceId = {SMESHUtils::SMESH_RegularGrid::B_FRONT,SMESHUtils::SMESH_RegularGrid::B_LEFT}; /*faces where interfaces are*/
+ std::vector<std::vector<int>> expectedRange(2);
+ std::vector<std::vector<int>> expectedDonorRange(2);
+
+ regularGrid0->GetFaceInterfaces( regularGrid1.get(), interface[0] );
+ regularGrid0->GetFaceInterfaces( regularGrid2.get(), interface[1] );
+
+ expectedRange[0] = std::vector<int>({4,1,2,5,1,3});
+ expectedRange[1] = std::vector<int>({1,4,1,1,2,2});
+
+ expectedDonorRange[0] = regularGrid1->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_FRONT);
+ expectedDonorRange[1] = regularGrid2->getFaceIndexLimits(SMESHUtils::SMESH_RegularGrid::B_LEFT);
+
+ int interfaceSize = 1+6*2+3;
+ for ( auto itf : interface )
+ {
+ if ( itf.size() != interfaceSize )
+ throw std::runtime_error("1to1 face interface not found in testGetPartialInterface2D()\n");
+ }
+
+ int count = 0;
+ for ( auto itf : interface )
+ {
+ if ( itf[0] != faceId[count] /*face id of the interface*/)
+ throw std::runtime_error("face found in interface is incorrect testGetPartialInterface2D()\n");
+
+ for (size_t i = 0; i < 6; i++)
+ if ( itf[i+1] != expectedRange[count][i])
+ throw std::runtime_error("interface range index is incorrect in testGetPartialInterface2D()\n");
+
+ for (size_t i = 0; i < 6; i++)
+ if ( itf[i+7] != expectedDonorRange[count][i])
+ throw std::runtime_error("interface donor index is incorrect in testGetPartialInterface2D()\n");
+ count++;
+ }
+
+ return true;
+}
+
+int main()
+{
+ if ( !testConstructor() || !testSetGetNode() ||
+ !testGetCommontInterface1D() || !testGetCommontInterface2D() ||
+ !testGetPartialInterface2D() )
+ return 1;
+ else
+ return 0;
+
+}
\ No newline at end of file
SMESH_test5.py
)
+
+SET(CPP_TESTS
+ SMESH_RegularGridTest
+)
+
# The following tests can be executed without driver, just by python.
# ----------------------------------------------------------------------------