From: eap Date: Mon, 5 Aug 2019 17:02:26 +0000 (+0300) Subject: IPAL54425: Quadrangle mapping fails on a quadrangle face with a seam X-Git-Tag: V9_4_0a1~18 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=f65b9b8b24acedada2383fe274f330c8d8630468 IPAL54425: Quadrangle mapping fails on a quadrangle face with a seam Issue reported in https://www.salome-platform.org/forum/forum_10/984373499 + 1) Fix a bug in Python dump 2) Expose corners in Quadrangle Param gui --- 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. ENF_NODES Enforced nodes + + CORNERS + Corner Vertices + StdMeshersGUI_LayerDistributionParamWdg