IPAL54529: Hexahedron(ijk) fails on a block with composite sides if Viscous Layers assigned

+ In Create Mesh dialog define enabled tabs by SMESH_Algo::IsApplicable( shape )
+ Extract SMESH_Indexer from StdMeshers_HexaFromSkin_3D.cxx
This commit is contained in:
eap 2019-07-12 15:15:38 +03:00
parent bb1e4b11d8
commit a87bde2a08
35 changed files with 969 additions and 890 deletions

View File

@ -2,11 +2,10 @@
import salome
salome.salome_init()
import GEOM
from salome.geom import geomBuilder
geompy = geomBuilder.New()
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New()
@ -14,20 +13,20 @@ smesh = smeshBuilder.New()
Box_1 = geompy.MakeBoxDXDYDZ(100, 100, 100)
Disk_1 = geompy.MakeDiskR(100, 1)
Common_1 = geompy.MakeCommon(Disk_1, Box_1)
geompy.addToStudy( Disk_1, "Disk_1" )
geompy.addToStudy( Box_1, "Box_1" )
triaVertex = geompy.GetVertexNearPoint( Common_1, geompy.MakeVertex(0,0,0) )
geompy.addToStudy( Common_1, "Common_1" )
geompy.addToStudyInFather( Common_1, triaVertex, "triaVertex" )
# Set the Geometry for meshing
Mesh_1 = smesh.Mesh(Common_1)
# Define 1D hypothesis and compute the mesh
# Define 1D hypothesis
Regular_1D = Mesh_1.Segment()
Nb_Segments_1 = Regular_1D.NumberOfSegments(10)
Nb_Segments_1.SetDistrType( 0 )
# Create Quadrangle parameters and define the Base Vertex.
Quadrangle_2D = Mesh_1.Quadrangle().TriangleVertex( 8 )
Quadrangle_2D = Mesh_1.Quadrangle().TriangleVertex( triaVertex )
# Compute the mesh
Mesh_1.Compute()

View File

@ -2,14 +2,10 @@
import salome
salome.salome_init()
import GEOM
from salome.geom import geomBuilder
geompy = geomBuilder.New()
import SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New()
from salome.StdMeshers import StdMeshersBuilder
# Make quadrangle face and explode it on edges.
Vertex_1 = geompy.MakeVertex(0, 0, 0)
@ -18,10 +14,6 @@ Vertex_3 = geompy.MakeVertex(40, 30, 0)
Vertex_4 = geompy.MakeVertex(0, 30, 0)
Quadrangle_Face_1 = geompy.MakeQuad4Vertices(Vertex_1, Vertex_4, Vertex_3, Vertex_2)
[Edge_1,Edge_2,Edge_3,Edge_4] = geompy.SubShapeAllSorted(Quadrangle_Face_1, geompy.ShapeType["EDGE"])
geompy.addToStudy( Vertex_1, "Vertex_1" )
geompy.addToStudy( Vertex_2, "Vertex_2" )
geompy.addToStudy( Vertex_3, "Vertex_3" )
geompy.addToStudy( Vertex_4, "Vertex_4" )
geompy.addToStudy( Quadrangle_Face_1, "Quadrangle Face_1" )
geompy.addToStudyInFather( Quadrangle_Face_1, Edge_2, "Edge_2" )
@ -30,25 +22,20 @@ Mesh_1 = smesh.Mesh(Quadrangle_Face_1)
# Create Quadrangle parameters and
# define the Type as Quadrangle Preference
Quadrangle_Parameters_1 = smesh.CreateHypothesis('QuadrangleParams')
Quadrangle_Parameters_1.SetQuadType( StdMeshersBuilder.QUAD_QUADRANGLE_PREF )
Quad_algo = Mesh_1.Quadrangle()
Quadrangle_Parameters_1 = Quad_algo.QuadrangleParameters( smeshBuilder.QUAD_QUADRANGLE_PREF )
# Define other hypotheses and algorithms
Regular_1D = Mesh_1.Segment()
Nb_Segments_1 = Regular_1D.NumberOfSegments(4)
Nb_Segments_1.SetDistrType( 0 )
status = Mesh_1.AddHypothesis(Quadrangle_Parameters_1)
Quadrangle_2D = Mesh_1.Quadrangle()
# Define submesh on one edge to provide different number of segments
Regular_1D_1 = Mesh_1.Segment(geom=Edge_2)
Nb_Segments_2 = Regular_1D_1.NumberOfSegments(10)
Nb_Segments_2.SetDistrType( 0 )
SubMesh_1 = Regular_1D_1.GetSubMesh()
# Compute mesh (with Quadrangle Preference type)
isDone = Mesh_1.Compute()
# Change type to Reduced and compute again
Quadrangle_Parameters_1.SetQuadType( StdMeshersBuilder.QUAD_REDUCED )
Quadrangle_Parameters_1.SetQuadType( smeshBuilder.QUAD_REDUCED )
isDone = Mesh_1.Compute()

View File

@ -89,6 +89,7 @@ class SMESH_EXPORT SMESH_Algo : public SMESH_Hypothesis
std::set<SMDSAbs_GeometryType> _outElemTypes; // produced types of mesh elements
std::string _label; // GUI type name
Features(): _dim( -1 ) {}
bool IsCompatible( const Features& algo2 ) const;
};
/*!

View File

@ -830,7 +830,7 @@ bool HypothesesSet::isAlgo() const
void HypothesesSet::init( bool isAlgo )
{
myIsAlgo = isAlgo;
myIndex = -1;
myIndex = 0;
}
bool HypothesesSet::more() const
@ -864,8 +864,7 @@ int HypothesesSet::maxDim() const
int dim = -1;
for ( int isAlgo = 0; isAlgo < 2; ++isAlgo )
{
thisSet->init( isAlgo );
while ( thisSet->next(), thisSet->more() )
for ( thisSet->init( isAlgo ); thisSet->more(); thisSet->next() )
if ( HypothesisData* hypData = SMESH::GetHypothesisData( thisSet->current() ))
for ( int i = 0; i < hypData->Dim.count(); ++i )
dim = qMax( dim, hypData->Dim[i] );

View File

@ -228,9 +228,8 @@ public:
bool isAlgo() const;
//this method sets internal index to -1, thus before any data access it is necessary to call next()
// CASCADE-like iteration
void init( bool );
bool more() const;
void next();
QString current() const;

View File

@ -828,6 +828,17 @@ bool SMESHGUI_MeshDlg::isTabEnabled(const int theTabId) const
return myTabWg->isTabEnabled( myTabWg->indexOf( myTabs[ theTabId ] ) );
}
//================================================================================
/*!
* \brief Return index of a current tab
* \return tab ID
*/
//================================================================================
int SMESHGUI_MeshDlg::currentTab() const
{
return Dim3D - myTabWg->currentIndex();
}
//================================================================================
/*!
* \brief SLOT called when a Geom selection button is clicked
@ -900,5 +911,8 @@ int SMESHGUI_MeshDlg::currentMeshType( )
//================================================================================
void SMESHGUI_MeshDlg::setCurrentMeshType( const int theIndex )
{
if ( theIndex < myMeshType->count() )
myMeshType->setCurrentIndex( theIndex );
else
myMeshType->setCurrentIndex( 0 );
}

View File

@ -66,20 +66,23 @@ public:
SMESHGUI_MeshDlg( const bool, const bool );
virtual ~SMESHGUI_MeshDlg();
SMESHGUI_MeshTab* tab( const int ) const;
void reset();
void setCurrentTab( const int );
void setMaxHypoDim( const int );
void setTitile( const bool, const bool );
void setHypoSets( const QStringList& );
void setGeomPopupEnabled( const bool );
void disableTab(const int);
void enableTab(const int);
bool isTabEnabled(const int) const;
int getActiveObject();
SMESHGUI_MeshTab* tab( const int ) const;
void enableTab(const int);
void disableTab(const int);
bool isTabEnabled(const int) const;
void setCurrentTab( const int );
int currentTab() const;
void setMaxHypoDim( const int );
void setAvailableMeshType(const QStringList& );
int currentMeshType();
void setCurrentMeshType( const int );
void setTitile( const bool, const bool );
int currentMeshType();
signals:
void hypoSet( const QString& );

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,11 @@
#include "SMESHGUI_SelectionOp.h"
// IDL includes
#include <SALOMEconfig.h>
#include CORBA_CLIENT_HEADER(SMESH_Gen)
#include CORBA_CLIENT_HEADER(GEOM_Gen)
class HypothesesSet;
class SMESHGUI_MeshDlg;
class SMESHGUI_ShapeByMeshOp;
@ -82,7 +87,6 @@ protected slots:
void onPublishShapeByMeshDlg( SUIT_Operation* );
void onCloseShapeByMeshDlg( SUIT_Operation* );
void onAlgoSelected( const int, const int = -1 );
void processSet();
void onHypoCreated( int );
void onHypoEdited( int );
void onAlgoSetByMeshType( const int, const int );
@ -92,11 +96,8 @@ private:
typedef QMap<QString, bool> THypLabelIsAppMap; // typedef: map of hypothesis is applicable
bool isValid( QString& ) const;
bool isCompatibleToGeometry( HypothesisData* ,
QString,
GEOM::GEOM_Object_var);
bool isCompatibleToMeshType( HypothesisData* ,
QString);
bool isCompatibleToGeometry( HypothesisData* , const int);
bool isCompatibleToMeshType( HypothesisData* , const int);
void availableHyps( const int,
const int,
QStringList&,
@ -142,10 +143,9 @@ private:
char* isSubmeshIgnored() const;
_PTR(SObject) getSubmeshByGeom() const;
void selectObject( _PTR(SObject) ) const;
void createMeshTypeList( QStringList& );
void setAvailableMeshType( const QStringList& );
void setFilteredAlgoData( const int, const int );
QString currentMeshTypeName( const int ) const;
void updateMeshTypeList();
void updateHypoSets();
void setFilteredAlgoData();
private:
@ -159,15 +159,17 @@ private:
// The geometry of "invalid sub-mesh" is not a sub-shape of the main shape;
// it is created for the case where a valid sub-shape not found by CopyMeshWithGeom()
QString myGeomEntry;
GEOM::GEOM_Object_var myGeom;
TDim2Type2HypList myExistingHyps; //!< all hypothesis of SMESH module
TDim2Type2HypList myObjHyps; //!< hypothesis assigned to the current
// edited mesh/sub-mesh
// hypdata corresponding to hypotheses present in myDlg
THypDataList myAvailableHypData[4][NbHypTypes];
QString myLastGeomToSelect;
QString myLastGeomEntry;
THypLabelIsAppMap myHypMapIsApplicable;
bool myIgnoreAlgoSelection;
HypothesesSet* myHypoSet;
int myDim, myType, myMaxShapeDim;
QString myObjectToSelect;

View File

@ -8222,7 +8222,7 @@ as they are of improper type:
<translation>
Some sub-shapes not found in the new geometry. They are listed
below along with dependent mesh objects that are marked with
with red in the Object Browser.</translation>
red in the Object Browser.</translation>
</message>
</context>
<context>

View File

@ -61,6 +61,7 @@ SET(SMESHUtils_HEADERS
SMESH_MAT2d.hxx
SMESH_ControlPnt.hxx
SMESH_Delaunay.hxx
SMESH_Indexer.hxx
)
# --- sources ---

View File

@ -276,12 +276,12 @@ const BRepMesh_Triangle* SMESH_Delaunay::GetTriangleNear( int iBndNode )
int nodeIDs[3];
int nbNbNodes = _bndNodes.size();
#if OCC_VERSION_LARGE <= 0x07030000
const BRepMesh::ListOfInteger & linkIds = _triaDS->LinksConnectedTo( iBndNode + 1 );
BRepMesh::ListOfInteger::const_iterator iLink = linkIds.cbegin();
typedef BRepMesh::ListOfInteger TLinkList;
#else
const IMeshData::ListOfInteger & linkIds = _triaDS->LinksConnectedTo( iBndNode + 1 );
IMeshData::ListOfInteger::const_iterator iLink = linkIds.cbegin();
typedef IMeshData::ListOfInteger TLinkList;
#endif
const TLinkList & linkIds = _triaDS->LinksConnectedTo( iBndNode + 1 );
TLinkList::const_iterator iLink = linkIds.cbegin();
for ( ; iLink != linkIds.cend(); ++iLink )
{
const BRepMesh_PairOfIndex & triaIds = _triaDS->ElementsConnectedTo( *iLink );
@ -363,7 +363,7 @@ void SMESH_Delaunay::ToPython() const
text << "import salome, SMESH\n";
text << "salome.salome_init()\n";
text << "from salome.smesh import smeshBuilder\n";
text << "smesh = smeshBuilder.New(salome.myStudy)\n";
text << "smesh = smeshBuilder.New()\n";
text << "mesh=smesh.Mesh()\n";
const char* endl = "\n";
@ -388,5 +388,5 @@ void SMESH_Delaunay::ToPython() const
file.remove();
file.openForWriting();
file.write( text.c_str(), text.size() );
cout << "execfile( '" << fileName << "')" << endl;
cout << "exec(open('" << fileName << "', 'rb').read())";
}

View File

@ -0,0 +1,153 @@
// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, 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_Indexer.hxx
// Created : Tue May 21 18:24:01 2019
// Author : Edward AGAPOV (eap)
#ifndef __SMESH_Indexer_HXX__
#define __SMESH_Indexer_HXX__
//================================================================================
/*!
* \brief Converter of a pair of indices to a sole index, useful to make
* 1D array behave as 2D one
*/
struct SMESH_Indexer
{
size_t _xSize, _ySize;
//! Initialize with size in two directions
SMESH_Indexer( size_t xSize=0, size_t ySize=0 ): _xSize(xSize), _ySize(ySize) {}
//! set size
void set(size_t xSize, size_t ySize ) { _xSize = xSize, _ySize = ySize; }
//! \return size of 1D array
size_t size() const { return _xSize * _ySize; }
// \return 1D index by two indices
size_t operator()(size_t x, size_t y) const { return y * _xSize + x; }
};
//================================================================================
/*!
* \brief Converter of a triple of indices to a sole index, useful to make
* 1D array behave as 3D one
*/
struct SMESH_Indexer3D
{
size_t _xSize, _ySize, _zSize;
//! Initialize with size in two directions
SMESH_Indexer3D( size_t xSize=0, size_t ySize=0, size_t zSize=0 ):
_xSize(xSize), _ySize(ySize), _zSize(zSize) {}
//! set size
void set(size_t xSize, size_t ySize, size_t zSize )
{ _xSize = xSize, _ySize = ySize, _zSize = zSize; }
//! \return size of 1D array
size_t size() const { return _xSize * _ySize * _zSize; }
// \return 1D index by three indices
size_t operator()(size_t x, size_t y, size_t z) const { return z*_xSize*_ySize + y*_xSize + x; }
};
//================================================================================
/*!
* \brief Oriented converter of a pair of integers to a sole index
*
* Allows virtual transformation of an 1D array viewed as 2D one.
* Possible transformations are inverse in one or two directions and exchange of
* the directions. Any combination of these transformations is allowed.
*
* The following code picks up a transformation such that two known array items
* appear in a desired positions:
* \code
* for ( int ori = 0; ori < SMESH_OrientedIndexer::MAX_ORI+1; ++ori )
* {
* SMESH_OrientedIndexer oriIndex( index, ori );
* if ( item1 == array[ oriIndex( i1, j1 ) ] &&
* item2 == array[ oriIndex( i2, j2 ) ])
* {
* // needed transformation found
* }
* }
* \endcode
*/
class SMESH_OrientedIndexer : public SMESH_Indexer
{
typedef SMESH_Indexer TFather;
public:
enum OriFlags //!< transformation types
{
REV_X = 1, REV_Y = 2, SWAP_XY = 4, MAX_ORI = REV_X|REV_Y|SWAP_XY
};
SMESH_OrientedIndexer( const SMESH_Indexer& indexer, const int oriFlags ):
TFather( indexer._xSize, indexer._ySize ),
_xRevFun( (oriFlags & REV_X) ? & reverse : & lazy ),
_yRevFun( (oriFlags & REV_Y) ? & reverse : & lazy ),
_swapFun( (oriFlags & SWAP_XY ) ? & swap : & lazy ),
_xSizeOriented( indexer._xSize ),
_ySizeOriented( indexer._ySize )
{
(*_swapFun)( _xSizeOriented, _ySizeOriented );
}
//!< Return index by XY
size_t operator()(size_t x, size_t y) const
{
(*_swapFun)( x, y );
(*_xRevFun)( x, const_cast< size_t& >( _xSize ));
(*_yRevFun)( y, const_cast< size_t& >( _ySize ));
return TFather::operator()( x, y );
}
//!< Return index for a corner
size_t corner(bool xMax, bool yMax) const
{
size_t x = xMax, y = yMax, size = 2;
(*_swapFun)( x, y );
(*_xRevFun)( x, size );
(*_yRevFun)( y, size );
return TFather::operator()( x ? _xSize-1 : 0,
y ? _ySize-1 : 0 );
}
size_t xSize() const { return _xSizeOriented; }
size_t ySize() const { return _ySizeOriented; }
private:
typedef void (*TFun)(size_t& x, size_t& y);
TFun _xRevFun, _yRevFun, _swapFun;
size_t _xSizeOriented, _ySizeOriented;
static void lazy (size_t& , size_t& ) {}
static void reverse(size_t& x, size_t& size) { x = size - x - 1; }
static void swap (size_t& x, size_t& y) { std::swap( x, y ); }
};
#endif

View File

@ -76,6 +76,7 @@ namespace SMESHUtils
TVECTOR v2( vec );
vec.swap( v2 );
}
/*!
* \brief Auto pointer
*/
@ -91,6 +92,7 @@ namespace SMESHUtils
private:
Deleter( const Deleter& );
};
/*!
* \brief Auto pointer to array
*/
@ -104,6 +106,9 @@ namespace SMESHUtils
ArrayDeleter( const ArrayDeleter& );
};
/*!
* \return SMDS_ElemIteratorPtr on an std container of SMDS_MeshElement's
*/
template < class ELEM_SET >
SMDS_ElemIteratorPtr elemSetIterator( const ELEM_SET& elements )
{
@ -111,6 +116,24 @@ namespace SMESHUtils
< SMDS_pElement, typename ELEM_SET::const_iterator> TSetIterator;
return boost::make_shared< TSetIterator >( elements.begin(), elements.end() );
}
/*!
* \brief Increment enum value
*/
template < typename ENUM >
void Increment( ENUM& v, int delta=1 )
{
v = ENUM( int(v)+delta );
}
/*!
* \brief Return incremented enum value
*/
template < typename ENUM >
ENUM Add( ENUM v, int delta )
{
return ENUM( int(v)+delta );
}
}
//=======================================================================
@ -213,7 +236,7 @@ typedef struct uvPtStruct
double x, y; // 2d parameter, normalized [0,1]
const SMDS_MeshNode * node;
uvPtStruct(): node(NULL) {}
uvPtStruct(const SMDS_MeshNode* n = 0): node(n) {}
inline gp_XY UV() const { return gp_XY( u, v ); }
inline void SetUV( const gp_XY& uv ) { u = uv.X(); v = uv.Y(); }

View File

@ -6145,7 +6145,8 @@ CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char* theAlgoType,
if (aCreator)
{
TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll );
const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
}
else
{

View File

@ -34,6 +34,8 @@
#include <iostream>
#include <sstream>
#include <TopExp_Explorer.hxx>
using namespace std;
//=============================================================================
@ -326,3 +328,24 @@ void SMESH_Hypothesis_i::UpdateAsMeshesRestored()
{
// for hyps needing full data restored
}
//================================================================================
/*!
* \brief Check if a shape includes sub-shapes of a given dimension
*/
//================================================================================
bool GenericHypothesisCreator_i::IsShapeOfDim( const TopoDS_Shape & S,
int dim )
{
TopAbs_ShapeEnum shapeType;
switch ( dim )
{
case 0: shapeType = TopAbs_VERTEX; break;
case 1: shapeType = TopAbs_EDGE; break;
case 2: shapeType = TopAbs_FACE; break;
case 3: shapeType = TopAbs_SOLID; break;
default: return true;
}
return TopExp_Explorer( S, shapeType ).More();
}

View File

@ -148,9 +148,17 @@ public:
::SMESH_Gen* theGenImpl) = 0;
virtual ~GenericHypothesisCreator_i() {}
// return the name of IDL module
// Return the name of IDL module
virtual std::string GetModuleName() = 0;
virtual bool IsApplicable( const TopoDS_Shape &S, bool toCheckAll ) {return true;}
// Check if an algorithm is applicable to a shape
virtual bool IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return IsShapeOfDim( S, algoDim );
}
// Check if a shape includes sub-shapes of a given dimension
static bool IsShapeOfDim( const TopoDS_Shape &S, int dim );
};
//=============================================================================

View File

@ -27,6 +27,7 @@
#include "SMDS_VolumeTool.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_Block.hxx"
#include "SMESH_Indexer.hxx"
#include "SMESH_Mesh.hxx"
#include "SMESH_MeshAlgos.hxx"
#include "SMESH_MesherHelper.hxx"
@ -59,6 +60,10 @@ using namespace std;
namespace
{
// typedefs for struct's moved to SMESHUtils
typedef SMESH_Indexer _Indexer;
typedef SMESH_OrientedIndexer _OrientedIndexer;
enum EBoxSides //!< sides of the block
{
B_BOTTOM=0, B_RIGHT, B_TOP, B_LEFT, B_FRONT, B_BACK, NB_BLOCK_SIDES
@ -143,67 +148,6 @@ namespace
return quad->GetNode( (iNode+2) % 4 );
}
//================================================================================
/*!
* \brief Converter of a pair of integers to a sole index
*/
struct _Indexer
{
int _xSize, _ySize;
_Indexer( int xSize=0, int ySize=0 ): _xSize(xSize), _ySize(ySize) {}
int size() const { return _xSize * _ySize; }
int operator()(int x, int y) const { return y * _xSize + x; }
};
//================================================================================
/*!
* \brief Oriented converter of a pair of integers to a sole index
*/
class _OrientedIndexer : public _Indexer
{
public:
enum OriFlags //!< types of block side orientation
{
REV_X = 1, REV_Y = 2, SWAP_XY = 4, MAX_ORI = REV_X|REV_Y|SWAP_XY
};
_OrientedIndexer( const _Indexer& indexer, const int oriFlags ):
_Indexer( indexer._xSize, indexer._ySize ),
_xSize (indexer._xSize), _ySize(indexer._ySize),
_xRevFun((oriFlags & REV_X) ? & reverse : & lazy),
_yRevFun((oriFlags & REV_Y) ? & reverse : & lazy),
_swapFun((oriFlags & SWAP_XY ) ? & swap : & lazy)
{
(*_swapFun)( _xSize, _ySize );
}
//!< Return index by XY
int operator()(int x, int y) const
{
(*_xRevFun)( x, const_cast<int&>( _xSize ));
(*_yRevFun)( y, const_cast<int&>( _ySize ));
(*_swapFun)( x, y );
return _Indexer::operator()(x,y);
}
//!< Return index for a corner
int corner(bool xMax, bool yMax) const
{
int x = xMax, y = yMax, size = 2;
(*_xRevFun)( x, size );
(*_yRevFun)( y, size );
(*_swapFun)( x, y );
return _Indexer::operator()(x ? _Indexer::_xSize-1 : 0 , y ? _Indexer::_ySize-1 : 0);
}
int xSize() const { return _xSize; }
int ySize() const { return _ySize; }
private:
_Indexer _indexer;
int _xSize, _ySize;
typedef void (*TFun)(int& x, int& y);
TFun _xRevFun, _yRevFun, _swapFun;
static void lazy (int&, int&) {}
static void reverse(int& x, int& size) { x = size - x - 1; }
static void swap (int& x, int& y) { std::swap(x,y); }
};
//================================================================================
/*!
* \brief Structure corresponding to the meshed side of block
@ -216,7 +160,7 @@ namespace
int _nbBlocksFound;
#ifdef _DEBUG_ // want to get SIGSEGV in case of invalid index
#define _grid_access_(pobj, i) pobj->_grid[ ((i) < (int)pobj->_grid.size()) ? i : int(1e100)]
#define _grid_access_(pobj, i) pobj->_grid[ ((i) < pobj->_grid.size()) ? i : int(1e100)]
#else
#define _grid_access_(pobj, i) pobj->_grid[ i ]
#endif

View File

@ -142,6 +142,10 @@ ostream & StdMeshers_QuadrangleParams::SaveTo(ostream & save)
<< " " << _enforcedPoints[i].Y()
<< " " << _enforcedPoints[i].Z();
save << " " << _cornerVertices.size();
for ( size_t i = 0; i < _cornerVertices.size(); ++i )
save << " " << _cornerVertices[i];
return save;
}
@ -182,6 +186,17 @@ istream & StdMeshers_QuadrangleParams::LoadFrom(istream & load)
else
break;
}
if ( load >> nbP && nbP > 0 )
{
int id;
_cornerVertices.reserve( nbP );
while ( _cornerVertices.size() < _cornerVertices.capacity() )
if ( load >> id )
_cornerVertices.push_back( id );
else
break;
}
return load;
}

View File

@ -61,6 +61,9 @@ public:
void GetEnforcedNodes( std::vector< TopoDS_Shape >& shapes,
std::vector< gp_Pnt >& points ) const;
void SetCorners( std::vector< int >& vertexIDs ) { _cornerVertices.swap( vertexIDs ); }
const std::vector< int >& GetCorners() const { return _cornerVertices; }
virtual std::ostream & SaveTo(std::ostream & save);
virtual std::istream & LoadFrom(std::istream & load);
@ -86,6 +89,7 @@ protected:
StdMeshers_QuadType _quadType;
std::vector< TopoDS_Shape > _enforcedVertices;
std::vector< gp_Pnt > _enforcedPoints;
std::vector< int > _cornerVertices;
};
#endif

View File

@ -1048,6 +1048,74 @@ namespace
return true;
}
//================================================================================
/*!
* \brief Return angle between mesh segments of given EDGEs meeting at theVertexNode
*/
//================================================================================
double getAngleByNodes( const int theE1Index,
const int theE2Index,
const SMDS_MeshNode* theVertexNode,
const StdMeshers_FaceSide& theFaceSide,
const gp_Vec& theFaceNormal)
{
int eID1 = theFaceSide.EdgeID( theE1Index );
int eID2 = theFaceSide.EdgeID( theE2Index );
const SMDS_MeshNode *n1 = 0, *n2 = 0;
bool is1st;
SMDS_ElemIteratorPtr segIt = theVertexNode->GetInverseElementIterator( SMDSAbs_Edge );
while ( segIt->more() )
{
const SMDS_MeshElement* seg = segIt->next();
int shapeID = seg->GetShapeID();
if ( shapeID == eID1 )
is1st = true;
else if ( shapeID == eID2 )
is1st = false;
else
continue;
( is1st ? n1 : n2 ) = seg->GetNodeWrap( 1 + seg->GetNodeIndex( theVertexNode ));
}
if ( !n1 || !n2 )
{
std::vector<const SMDS_MeshNode*> nodes;
for ( int is2nd = 0; is2nd < 2; ++is2nd )
{
const SMDS_MeshNode* & n = is2nd ? n2 : n1;
if ( n ) continue;
nodes.clear();
if ( is2nd ) theFaceSide.GetEdgeNodes( theE2Index, nodes );
else theFaceSide.GetEdgeNodes( theE1Index, nodes );
if ( nodes.size() >= 2 )
{
if ( nodes[0] == theVertexNode )
n = nodes[1];
else
n = nodes[ nodes.size() - 2 ];
}
}
}
double angle = -2 * M_PI;
if ( n1 && n2 )
{
SMESH_NodeXYZ p1 = n1, p2 = theVertexNode, p3 = n2;
gp_Vec v1( p1, p2 ), v2( p2, p3 );
try
{
angle = v1.AngleWithRef( v2, theFaceNormal );
}
catch(...)
{
}
if ( std::isnan( angle ))
angle = -2 * M_PI;
}
return angle;
}
//--------------------------------------------------------------------------------
/*!
* \brief EDGE of a FACE
@ -1057,6 +1125,7 @@ namespace
TopoDS_Edge myEdge;
TopoDS_Vertex my1stVertex;
int myIndex;
bool myIsCorner; // is fixed corner
double myAngle; // angle at my1stVertex
int myNbSegments; // discretization
Edge* myPrev; // preceding EDGE
@ -1085,6 +1154,7 @@ namespace
// quality criteria to minimize
int myOppDiff;
int myIsFixedCorner;
double myQuartDiff;
double mySumAngle;
@ -1112,6 +1182,11 @@ namespace
myOppDiff = ( Abs( myNbSeg[0] - myNbSeg[2] ) +
Abs( myNbSeg[1] - myNbSeg[3] ));
myIsFixedCorner = - totNbSeg * ( myCornerE[0]->myIsCorner +
myCornerE[1]->myIsCorner +
myCornerE[2]->myIsCorner +
myCornerE[3]->myIsCorner );
double nbSideIdeal = totNbSeg / 4.;
myQuartDiff = -( Min( Min( myNbSeg[0], myNbSeg[1] ),
Min( myNbSeg[2], myNbSeg[3] )) / nbSideIdeal );
@ -1125,7 +1200,7 @@ namespace
};
// first criterion - equality of nbSeg of opposite sides
int crit1() const { return myOppDiff; }
int crit1() const { return myOppDiff + myIsFixedCorner; }
// second criterion - equality of nbSeg of adjacent sides and sharpness of angles
double crit2() const { return myQuartDiff + mySumAngle; }
@ -1143,7 +1218,7 @@ namespace
//================================================================================
/*!
* \brief Unite EDGEs to get a required number of sides
* \param [in] theNbCorners - the required number of sides
* \param [in] theNbCorners - the required number of sides, 3 or 4
* \param [in] theConsiderMesh - to considered only meshed VERTEXes
* \param [in] theFaceSide - the FACE EDGEs
* \param [out] theVertices - the found corner vertices
@ -1153,7 +1228,7 @@ namespace
void uniteEdges( const int theNbCorners,
const bool theConsiderMesh,
const StdMeshers_FaceSide& theFaceSide,
const TopoDS_Shape& theBaseVertex,
const TopTools_MapOfShape& theFixedVertices,
std::vector<TopoDS_Vertex>& theVertices,
bool& theHaveConcaveVertices)
{
@ -1183,23 +1258,28 @@ namespace
// sort edges by angle
std::multimap< double, Edge* > edgeByAngle;
int i, iBase = -1, nbConvexAngles = 0, nbSharpAngles = 0;
int i, nbConvexAngles = 0, nbSharpAngles = 0;
const SMDS_MeshNode* vertNode = 0;
gp_Vec faceNormal;
const double angTol = 5. / 180 * M_PI;
const double sharpAngle = 0.5 * M_PI - angTol;
Edge* e = edge0;
for ( i = 0; i < nbEdges; ++i, e = e->myNext )
{
e->my1stVertex = SMESH_MesherHelper::IthVertex( 0, e->myEdge );
if ( e->my1stVertex.IsSame( theBaseVertex ))
iBase = e->myIndex;
e->myIsCorner = theFixedVertices.Contains( e->my1stVertex );
e->myAngle = -2 * M_PI;
if ( !theConsiderMesh || theFaceSide.VertexNode( e->myIndex ))
if ( !theConsiderMesh || ( vertNode = theFaceSide.VertexNode( e->myIndex )))
{
e->myAngle = SMESH_MesherHelper::GetAngle( e->myPrev->myEdge, e->myEdge,
theFaceSide.Face(), e->my1stVertex );
theFaceSide.Face(), e->my1stVertex,
&faceNormal );
if ( e->myAngle > 2 * M_PI ) // GetAngle() failed
e->myAngle *= -1.;
else if ( vertNode && ( 0. <= e->myAngle ) && ( e->myAngle <= angTol ))
e->myAngle = getAngleByNodes( e->myPrev->myIndex, e->myIndex,
vertNode, theFaceSide, faceNormal );
}
edgeByAngle.insert( std::make_pair( e->myAngle, e ));
nbConvexAngles += ( e->myAngle > angTol );
@ -1227,8 +1307,10 @@ namespace
// return corners with maximal angles
std::set< int > cornerIndices;
if ( iBase != -1 )
cornerIndices.insert( iBase );
if ( !theFixedVertices.IsEmpty() )
for ( i = 0, e = edge0; i < nbEdges; ++i, e = e->myNext )
if ( e->myIsCorner )
cornerIndices.insert( e->myIndex );
std::multimap< double, Edge* >::reverse_iterator a2e = edgeByAngle.rbegin();
for (; (int) cornerIndices.size() < theNbCorners; ++a2e )
@ -1444,7 +1526,20 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
myCheckOri = false;
if ( theVertices.size() > 3 )
{
uniteEdges( nbCorners, theConsiderMesh, faceSide, triaVertex, theVertices, myCheckOri );
TopTools_MapOfShape fixedVertices;
if ( !triaVertex.IsNull() )
fixedVertices.Add( triaVertex );
if ( myParams )
{
const std::vector< int >& vIDs = myParams->GetCorners();
for ( size_t i = 0; i < vIDs.size(); ++i )
{
const TopoDS_Shape& vertex = helper.GetMeshDS()->IndexToShape( vIDs[ i ]);
if ( !vertex.IsNull() )
fixedVertices.Add( vertex );
}
}
uniteEdges( nbCorners, theConsiderMesh, faceSide, fixedVertices, theVertices, myCheckOri );
}
if ( nbCorners == 3 && !triaVertex.IsSame( theVertices[0] ))

View File

@ -86,8 +86,7 @@ StdMeshers_Hexa_3D_i::~StdMeshers_Hexa_3D_i()
*/
//=============================================================================
CORBA::Boolean StdMeshers_Hexa_3D_i::IsApplicable( const TopoDS_Shape &S,
CORBA::Boolean toCheckAll )
bool StdMeshers_Hexa_3D_i::IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return ::StdMeshers_Hexa_3D::IsApplicable( S, toCheckAll );
}

View File

@ -58,7 +58,7 @@ public:
::StdMeshers_Hexa_3D* GetImpl();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int dim);
};
#endif

View File

@ -63,8 +63,7 @@ StdMeshers_Prism_3D_i::~StdMeshers_Prism_3D_i()
}
//-----------------------------------------------------------------------------
CORBA::Boolean StdMeshers_Prism_3D_i::IsApplicable( const TopoDS_Shape &S,
CORBA::Boolean toCheckAll )
bool StdMeshers_Prism_3D_i::IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return ::StdMeshers_Prism_3D::IsApplicable( S, toCheckAll );
}
@ -99,8 +98,7 @@ StdMeshers_RadialPrism_3D_i::~StdMeshers_RadialPrism_3D_i()
}
//-----------------------------------------------------------------------------
CORBA::Boolean StdMeshers_RadialPrism_3D_i::IsApplicable( const TopoDS_Shape &S,
CORBA::Boolean toCheckAll )
bool StdMeshers_RadialPrism_3D_i::IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int )
{
return ::StdMeshers_RadialPrism_3D::IsApplicable( S, toCheckAll );
}

View File

@ -57,7 +57,7 @@ public:
::StdMeshers_Prism_3D* GetImpl();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int dim);
};
// ======================================================
@ -79,7 +79,7 @@ public:
::StdMeshers_RadialPrism_3D* GetImpl();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int dim);
};

View File

@ -67,8 +67,7 @@ StdMeshers_Projection_3D_i::~StdMeshers_Projection_3D_i()
*/
//================================================================================
CORBA::Boolean StdMeshers_Projection_3D_i::IsApplicable(const TopoDS_Shape &S,
CORBA::Boolean toCheckAll)
bool StdMeshers_Projection_3D_i::IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return ::StdMeshers_Projection_3D::IsApplicable( S, toCheckAll );
}

View File

@ -59,7 +59,7 @@ public:
::StdMeshers_Projection_3D* GetImpl();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int dim);
};
// ======================================================

View File

@ -293,6 +293,43 @@ SMESH::string_array* StdMeshers_QuadrangleParams_i::GetEnfVertices()
return arr._retn();
}
//=============================================================================
/*!
* Set corner vertices
*/
//=============================================================================
void StdMeshers_QuadrangleParams_i::SetCorners(const SMESH::long_array& theVertexIDs )
{
std::vector< int > ids;
for ( CORBA::ULong i = 0; i < theVertexIDs.length(); ++i )
ids.push_back( theVertexIDs[i] );
if ( ids != GetImpl()->GetCorners() )
{
GetImpl()->SetCorners( ids );
SMESH::TPythonDump() << _this() << ".SetCorners( " << theVertexIDs << " )";
}
}
//=============================================================================
/*!
* Return IDs of corner vertices
*/
//=============================================================================
SMESH::long_array* StdMeshers_QuadrangleParams_i::GetCorners()
{
const std::vector< int >& ids = GetImpl()->GetCorners();
SMESH::long_array_var result = new SMESH::long_array;
result->length( ids.size() );
for ( size_t i = 0; i < ids.size(); ++i )
result[ i ] = ids[ i ];
return result._retn();
}
//=============================================================================
/*!
* StdMeshers_QuadrangleParams_i::GetImpl

View File

@ -73,6 +73,11 @@ public:
// Returns entries of shapes defining enforced nodes
SMESH::string_array* GetEnfVertices();
// Set corner vertices
void SetCorners( const SMESH::long_array& vertexIDs );
// Return IDs of corner vertices
SMESH::long_array* GetCorners();
// Get implementation
::StdMeshers_QuadrangleParams* GetImpl();

View File

@ -89,8 +89,7 @@ StdMeshers_Quadrangle_2D_i::~StdMeshers_Quadrangle_2D_i()
*/
//=============================================================================
CORBA::Boolean StdMeshers_Quadrangle_2D_i::IsApplicable( const TopoDS_Shape &S,
CORBA::Boolean toCheckAll )
bool StdMeshers_Quadrangle_2D_i::IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return ::StdMeshers_Quadrangle_2D::IsApplicable( S, toCheckAll );
}
@ -134,8 +133,8 @@ StdMeshers_QuadFromMedialAxis_1D2D_i::~StdMeshers_QuadFromMedialAxis_1D2D_i()
*/
//================================================================================
CORBA::Boolean StdMeshers_QuadFromMedialAxis_1D2D_i::IsApplicable( const TopoDS_Shape &S,
CORBA::Boolean toCheckAll )
bool StdMeshers_QuadFromMedialAxis_1D2D_i::IsApplicable( const TopoDS_Shape &S,
bool toCheckAll, int algoDim )
{
return ::StdMeshers_QuadFromMedialAxis_1D2D::IsApplicable( S, toCheckAll );
}

View File

@ -58,7 +58,7 @@ class STDMESHERS_I_EXPORT StdMeshers_Quadrangle_2D_i:
::StdMeshers_Quadrangle_2D* GetImpl();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int );
};
// ======================================================
@ -77,7 +77,7 @@ class STDMESHERS_I_EXPORT StdMeshers_QuadFromMedialAxis_1D2D_i:
virtual ~StdMeshers_QuadFromMedialAxis_1D2D_i();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int dim);
};
#endif

View File

@ -63,7 +63,7 @@ StdMeshers_RadialQuadrangle_1D2D_i::~StdMeshers_RadialQuadrangle_1D2D_i()
//-----------------------------------------------------------------------------
CORBA::Boolean StdMeshers_RadialQuadrangle_1D2D_i::IsApplicable( const TopoDS_Shape &S, CORBA::Boolean toCheckAll )
bool StdMeshers_RadialQuadrangle_1D2D_i::IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return ::StdMeshers_RadialQuadrangle_1D2D::IsApplicable( S, toCheckAll );
}

View File

@ -48,7 +48,7 @@ public:
::StdMeshers_RadialQuadrangle_1D2D* GetImpl();
// Return true if the algorithm is applicable to a shape
static CORBA::Boolean IsApplicable(const TopoDS_Shape &S, CORBA::Boolean toCheckAll);
static bool IsApplicable(const TopoDS_Shape &S, bool toCheckAll, int dim);
};

View File

@ -83,21 +83,22 @@ namespace SMESH {
class ApplicableToAny
{
public:
static CORBA::Boolean IsApplicable( const TopoDS_Shape &S, CORBA::Boolean toCheckAll )
static bool IsApplicable( const TopoDS_Shape &S, bool toCheckAll, int algoDim )
{
return true;
return GenericHypothesisCreator_i::IsShapeOfDim( S, algoDim );
}
};
};
template <class T, class TIsApplicable = SMESH::ApplicableToAny>
class StdHypothesisCreator_i : public HypothesisCreator_i< T >
{
public:
// as we have 'module StdMeshers' in SMESH_BasicHypothesis.idl
virtual std::string GetModuleName() { return "StdMeshers"; }
virtual CORBA::Boolean IsApplicable( const TopoDS_Shape & S, CORBA::Boolean toCheckAll )
virtual bool IsApplicable( const TopoDS_Shape & S, bool toCheckAll, int algoDim )
{
return TIsApplicable::IsApplicable( S, toCheckAll );
return TIsApplicable::IsApplicable( S, toCheckAll, algoDim );
}
};