diff --git a/resources/StdMeshers.xml.in b/resources/StdMeshers.xml.in
index 7d480e690..a765bbc7a 100644
--- a/resources/StdMeshers.xml.in
+++ b/resources/StdMeshers.xml.in
@@ -334,7 +334,7 @@
dim ="2">
Quadrangle_2D=Quadrangle(algo=smeshBuilder.QUADRANGLE)
- QuadrangleParams=QuadrangleParameters(SetQuadType(),SetTriaVertex(),SetEnforcedNodes(1),SetEnforcedNodes(2))
+ QuadrangleParams=QuadrangleParameters(SetQuadType(),SetTriaVertex(),SetEnforcedNodes(1),SetEnforcedNodes(2),SetCorners())
ViscousLayers2D=ViscousLayers2D(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetIgnoreEdges())
diff --git a/src/SMESH/SMESH_MesherHelper.hxx b/src/SMESH/SMESH_MesherHelper.hxx
index 08d504ebc..e0a4eb7aa 100644
--- a/src/SMESH/SMESH_MesherHelper.hxx
+++ b/src/SMESH/SMESH_MesherHelper.hxx
@@ -635,6 +635,10 @@ public:
* \retval int - 1 for U, 2 for V direction
*/
int GetPeriodicIndex() const { return myParIndex; }
+ /*!
+ * \brief Return period in given direction [1,2]
+ */
+ double GetPeriod(int perioIndex) const { return myPar2[ perioIndex-1 ] - myPar1[ perioIndex-1 ]; }
/*!
* \brief Return an alternative parameter for a node on seam
*/
diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx
index 45540d510..b22af73eb 100644
--- a/src/SMESH_I/SMESH_2smeshpy.cxx
+++ b/src/SMESH_I/SMESH_2smeshpy.cxx
@@ -1971,7 +1971,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
if ( !obj->CanClear() )
allGroupsRemoved = false;
}
- if ( nbGroupsBefore == myGroups.size() ) // no new _pyGroup created
+ if ( nbGroupsBefore == myGroups.size() && !obj.IsNull() ) // no new _pyGroup created
obj->AddProcessedCmd( theCommand ); // to clear theCommand if all groups are removed
if ( !allGroupsRemoved && !theGen->IsToKeepAllCommands() )
diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.cxx b/src/StdMeshers/StdMeshers_Hexa_3D.cxx
index 7dadb9c25..86f77bbd1 100644
--- a/src/StdMeshers/StdMeshers_Hexa_3D.cxx
+++ b/src/StdMeshers/StdMeshers_Hexa_3D.cxx
@@ -77,6 +77,7 @@ StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, SMESH_Gen * gen)
_shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID); // 1 bit /shape type
_requireShape = false;
_compatibleHypothesis.push_back("ViscousLayers");
+ _quadAlgo = new StdMeshers_Quadrangle_2D( gen->GetANewId(), _gen );
}
//=============================================================================
@@ -87,6 +88,8 @@ StdMeshers_Hexa_3D::StdMeshers_Hexa_3D(int hypId, SMESH_Gen * gen)
StdMeshers_Hexa_3D::~StdMeshers_Hexa_3D()
{
+ delete _quadAlgo;
+ _quadAlgo = 0;
}
//=============================================================================
@@ -231,7 +234,7 @@ namespace
for ( int i = 1; i < 6; ++i )
{
if ( !quad[i] ) continue;
- for ( unsigned iS = 0; iS < quad[i]->side.size(); ++iS )
+ for ( size_t iS = 0; iS < quad[i]->side.size(); ++iS )
{
const StdMeshers_FaceSidePtr side2 = quad[i]->side[iS];
if (( side->FirstVertex().IsSame( side2->FirstVertex() ) ||
@@ -244,9 +247,9 @@ namespace
if ( iS != Q_BOTTOM )
{
vector< FaceQuadStruct::Side > newSides;
- for ( unsigned j = iS; j < quad[i]->side.size(); ++j )
+ for ( size_t j = iS; j < quad[i]->side.size(); ++j )
newSides.push_back( quad[i]->side[j] );
- for ( unsigned j = 0; j < iS; ++j )
+ for ( size_t j = 0; j < iS; ++j )
newSides.push_back( quad[i]->side[j] );
quad[i]->side.swap( newSides );
}
@@ -363,7 +366,7 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
if ( exp.Next(), exp.More() )
return error(COMPERR_BAD_SHAPE, "More than one SHELL in the geometry");
- TopTools_IndexedMapOfShape FF;
+ TopTools_IndexedMapOfShape FF, EE;
TopExp::MapShapes( aShape, TopAbs_FACE, FF);
if ( FF.Extent() != 6)
{
@@ -375,14 +378,23 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
// Find sides of a cube
// ---------------------
-
+
+ // tool creating quadratic elements if needed
+ SMESH_MesherHelper helper (aMesh);
+ _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
+
+ TopExp::MapShapes( aShape, TopAbs_EDGE, EE );
+ SMESH_MesherHelper* faceHelper = ( EE.Size() == 12 ) ? 0 : &helper;
+
FaceQuadStructPtr quad[ 6 ];
- StdMeshers_Quadrangle_2D quadAlgo( _gen->GetANewId(), _gen);
for ( int i = 0; i < 6; ++i )
{
- if ( !( quad[i] = FaceQuadStructPtr( quadAlgo.CheckNbEdges( aMesh, FF( i+1 ),
- /*considerMesh=*/true))))
- return error( quadAlgo.GetComputeError() );
+ if ( faceHelper )
+ faceHelper->SetSubShape( FF( i+1 ));
+ if ( !( quad[i] = FaceQuadStructPtr( _quadAlgo->CheckNbEdges( aMesh, FF( i+1 ),
+ /*considerMesh=*/true,
+ faceHelper))))
+ return error( _quadAlgo->GetComputeError() );
if ( quad[i]->side.size() != 4 )
return error( COMPERR_BAD_SHAPE, "Not a quadrangular box side" );
}
@@ -437,10 +449,6 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
// Check presence of regular grid mesh on FACEs of the cube
// ------------------------------------------------------------
- // tool creating quadratic elements if needed
- SMESH_MesherHelper helper (aMesh);
- _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
-
for ( int i = 0; i < 6; ++i )
{
const TopoDS_Face& F = aCubeSide[i]._quad->face;
@@ -513,8 +521,8 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh,
if ( proxymesh )
for ( int i = 0; i < 6; ++i )
- for ( unsigned j = 0; j < aCubeSide[i]._columns.size(); ++j)
- for ( unsigned k = 0; k < aCubeSide[i]._columns[j].size(); ++k)
+ for ( size_t j = 0; j < aCubeSide[i]._columns.size(); ++j)
+ for ( size_t k = 0; k < aCubeSide[i]._columns[j].size(); ++k)
{
const SMDS_MeshNode* & n = aCubeSide[i]._columns[j][k];
n = proxymesh->GetProxyNode( n );
diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.hxx b/src/StdMeshers/StdMeshers_Hexa_3D.hxx
index 49046302e..00ff85cf5 100644
--- a/src/StdMeshers/StdMeshers_Hexa_3D.hxx
+++ b/src/StdMeshers/StdMeshers_Hexa_3D.hxx
@@ -34,8 +34,9 @@
#include "SMESH_Algo.hxx"
-class StdMeshers_ViscousLayers;
class SMESH_MesherHelper;
+class StdMeshers_Quadrangle_2D;
+class StdMeshers_ViscousLayers;
class STDMESHERS_EXPORT StdMeshers_Hexa_3D : public SMESH_3D_Algo
{
@@ -63,6 +64,7 @@ public:
protected:
const StdMeshers_ViscousLayers* _viscousLayersHyp;
+ StdMeshers_Quadrangle_2D* _quadAlgo;
};
#endif
diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
index 6173866f4..6f087bfa2 100644
--- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
+++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx
@@ -51,6 +51,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1221,7 +1222,9 @@ namespace
* \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 [in] theFixedVertices - VERTEXes to be used as corners
* \param [out] theVertices - the found corner vertices
+ * \param [out] theHaveConcaveVertices - return if there are concave vertices
*/
//================================================================================
@@ -1432,6 +1435,39 @@ namespace
return;
}
+ //================================================================================
+ /*!
+ * \brief Remove a seam and degenerated edge from a wire if the shape is
+ * a quadrangle with a seam inside.
+ */
+ //================================================================================
+
+ bool removeInternalSeam( std::list& theWire,
+ SMESH_MesherHelper& theHelper)
+ {
+ if ( !theHelper.HasRealSeam() ||
+ theHelper.NbDegeneratedEdges() != 2 ) // 1 EDGE + 1 VERTEX
+ return false;
+
+ typedef std::list::iterator TEdgeIter;
+ std::vector< TEdgeIter > edgesToRemove;
+ edgesToRemove.reserve( 5 );
+ for ( TEdgeIter eIt = theWire.begin(); eIt != theWire.end(); ++eIt )
+ {
+ int eID = theHelper.ShapeToIndex( *eIt );
+ if ( theHelper.IsRealSeam( eID ) || theHelper.IsDegenShape( eID ))
+ edgesToRemove.push_back( eIt );
+ }
+
+ if ( theWire.size() - edgesToRemove.size() < 4 )
+ return false; // cone e.g.
+
+ for ( size_t i = 0; i < edgesToRemove.size(); ++i )
+ theWire.erase( edgesToRemove[ i ]);
+
+ return true;
+ }
+
} // namespace
//================================================================================
@@ -1462,6 +1498,9 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face& theFace,
if ( myHelper )
helper.CopySubShapeInfo( *myHelper );
+ if ( removeInternalSeam( theWire, helper ))
+ theNbDegenEdges = 1;
+
StdMeshers_FaceSide faceSide( theFace, theWire, &theMesh,
/*isFwd=*/true, /*skipMedium=*/true, &helper );
@@ -4774,20 +4813,35 @@ bool StdMeshers_Quadrangle_2D::check()
default:;
}
- // if ( isBad && myHelper->HasRealSeam() )
- // {
- // // detect a case where a face intersects the seam
- // for ( int iPar = 1; iPar < 3; ++iPar )
- // if ( iPar & myHelper->GetPeriodicIndex() )
- // {
- // double min = uv[0].Coord( iPar ), max = uv[0].Coord( iPar );
- // for ( int i = 1; i < nbN; ++i )
- // {
- // min = Min( min, uv[i].Coord( iPar ));
- // max = Max( max, uv[i].Coord( iPar ));
- // }
- // }
- // }
+ if ( isBad && myHelper->HasRealSeam() )
+ {
+ // fix uv for a case where a face intersects the seam
+ for ( int iPar = 1; iPar < 3; ++iPar )
+ if ( iPar & myHelper->GetPeriodicIndex() )
+ {
+ double max = uv[0].Coord( iPar );
+ for ( int i = 1; i < nbN; ++i )
+ max = Max( max, uv[i].Coord( iPar ));
+
+ for ( int i = 0; i < nbN; ++i )
+ {
+ double par = uv[i].Coord( iPar );
+ double shift = ShapeAnalysis::AdjustByPeriod( par, max, myHelper->GetPeriod( iPar ));
+ uv[i].SetCoord( iPar, par + shift );
+ }
+ }
+ double sign1 = getArea( uv[0], uv[1], uv[2] );
+ double sign2 = getArea( uv[0], uv[2], uv[3] );
+ if ( sign1 * sign2 < 0 )
+ {
+ sign2 = getArea( uv[1], uv[2], uv[3] );
+ sign1 = getArea( uv[1], uv[3], uv[0] );
+ if ( sign1 * sign2 < 0 )
+ continue; // this should not happen
+ }
+ isBad = ( sign1 * okSign < 0 );
+ }
+
if ( isBad )
badFaces.push_back ( f );
}
diff --git a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx
index 7df2045bd..dda529a3f 100644
--- a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx
+++ b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.cxx
@@ -55,7 +55,7 @@
#define SPACING 6
#define MARGIN 11
-enum { TAB_TRANSITION, TAB_VERTEX, TAB_ENF_POINTS };
+enum { TAB_TRANSITION, TAB_VERTEX, TAB_CORNERS, TAB_ENF_POINTS };
//================================================================================
// function : Constructor
@@ -153,11 +153,17 @@ QFrame* StdMeshersGUI_QuadrangleParamCreator::buildFrame()
pointsLay->addWidget( shapesGroup );
pointsLay->addWidget( coordsGroup );
+ // Corners
+
+ myCornersSelWdg = new StdMeshersGUI_SubShapeSelectorWdg( fr, TopAbs_VERTEX );
+ myCornersSelWdg->layout()->setMargin( MARGIN );
+
// Tabs
myTabs = new QTabWidget( fr );
- myTabs->addTab( myTypeWdg, tr("TRANSITION"));
- myTabs->addTab( myVertexSelWdg, tr("SMESH_BASE_VERTEX"));
- myTabs->addTab( pointsFrame, tr("ENF_NODES"));
+ myTabs->addTab( myTypeWdg, tr("TRANSITION"));
+ myTabs->addTab( myVertexSelWdg, tr("SMESH_BASE_VERTEX"));
+ myTabs->addTab( myCornersSelWdg, tr("CORNERS"));
+ myTabs->addTab( pointsFrame, tr("ENF_NODES"));
lay->addWidget( myTabs, row, 0, 2, 3 );
@@ -196,6 +202,7 @@ void StdMeshersGUI_QuadrangleParamCreator::retrieveParams() const
if ( anEntry.isEmpty() )
anEntry = h->GetObjectEntry();
myVertexSelWdg->SetGeomShapeEntry(anEntry,aMainEntry);
+ myCornersSelWdg->SetGeomShapeEntry(anEntry,aMainEntry);
if ( !isCreation())
{
@@ -211,6 +218,10 @@ void StdMeshersGUI_QuadrangleParamCreator::retrieveParams() const
myVertexSelWdg->SetListOfIDs(aVec);
}
+ // corners
+ SMESH::long_array_var aVec = h->GetCorners();
+ myCornersSelWdg->SetListOfIDs( aVec );
+
// enforced nodes
GEOM::ListOfGO_var shapes;
SMESH::nodes_array_var points;
@@ -265,6 +276,9 @@ QString StdMeshersGUI_QuadrangleParamCreator::storeParams() const
h->SetTriaVertex( -1 );
}
+ // corners
+ h->SetCorners( myCornersSelWdg->GetListOfIDs() );
+
// enfored nodes
GEOM::ListOfGO_var goList = new GEOM::ListOfGO;
@@ -408,6 +422,7 @@ void StdMeshersGUI_QuadrangleParamCreator::onSelectionChanged()
void StdMeshersGUI_QuadrangleParamCreator::onTabChanged(int i)
{
myVertexSelWdg->ShowPreview( i == TAB_VERTEX );
+ myCornersSelWdg->ShowPreview( i == TAB_CORNERS );
}
//================================================================================
diff --git a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h
index 5264f1942..5aa4b74cb 100644
--- a/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h
+++ b/src/StdMeshersGUI/StdMeshersGUI_QuadrangleParamWdg.h
@@ -78,6 +78,7 @@ class STDMESHERSGUI_EXPORT StdMeshersGUI_QuadrangleParamCreator : public StdMesh
QLineEdit* myName;
StdMeshersGUI_QuadrangleParamWdg* myTypeWdg;
StdMeshersGUI_SubShapeSelectorWdg* myVertexSelWdg;
+ StdMeshersGUI_SubShapeSelectorWdg* myCornersSelWdg;
QListWidget* myShapesList;
QPushButton* myAddShapeBut;
QTreeWidget* myCoordsTreeWdg;
diff --git a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h
index 437da33cb..a3e986a88 100644
--- a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h
+++ b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h
@@ -53,7 +53,7 @@ public:
StdMeshersGUI_SubShapeSelectorWdg( QWidget* parent = 0,
TopAbs_ShapeEnum subShType = TopAbs_EDGE,
const bool toShowList = true,
- const bool toShowActivateBtn = false);
+ const bool toShowSelectBtn = false);
~StdMeshersGUI_SubShapeSelectorWdg();
SMESH::long_array_var GetListOfIDs();
diff --git a/src/StdMeshersGUI/StdMeshers_msg_en.ts b/src/StdMeshersGUI/StdMeshers_msg_en.ts
index 91a1b3ca6..351aed8f4 100644
--- a/src/StdMeshersGUI/StdMeshers_msg_en.ts
+++ b/src/StdMeshersGUI/StdMeshers_msg_en.ts
@@ -542,6 +542,10 @@ this one for this mesh/sub-mesh.
Enforced nodes
+
+
+ Corner Vertices
+
StdMeshersGUI_LayerDistributionParamWdg