From b4be5729e0123836415ee5e8689f332809788a17 Mon Sep 17 00:00:00 2001 From: vsr Date: Tue, 19 May 2020 13:29:55 +0300 Subject: [PATCH 01/25] Increment version: 9.5.0 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2434f379..2dd08cb40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,11 +27,11 @@ INCLUDE(CMakeDependentOption) STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC) SET(${PROJECT_NAME_UC}_MAJOR_VERSION 9) -SET(${PROJECT_NAME_UC}_MINOR_VERSION 4) +SET(${PROJECT_NAME_UC}_MINOR_VERSION 5) SET(${PROJECT_NAME_UC}_PATCH_VERSION 0) SET(${PROJECT_NAME_UC}_VERSION ${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION}) -SET(${PROJECT_NAME_UC}_VERSION_DEV 1) +SET(${PROJECT_NAME_UC}_VERSION_DEV 0) # Common CMake macros # =================== From 1cc4f6c5a964109ef5e09beb10fc4f7c3f06f8b9 Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 20 May 2020 20:04:42 +0300 Subject: [PATCH 02/25] IPAL54676: TC-9.5.0: Problem with "Radial Quadrangle 1D-2D" algo and "Local Lenght" hypo --- src/StdMeshers/StdMeshers_LayerDistribution.cxx | 1 + .../StdMeshersGUI_LayerDistributionParamWdg.cxx | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/StdMeshers/StdMeshers_LayerDistribution.cxx b/src/StdMeshers/StdMeshers_LayerDistribution.cxx index 6304e6dc5..8212547e9 100644 --- a/src/StdMeshers/StdMeshers_LayerDistribution.cxx +++ b/src/StdMeshers/StdMeshers_LayerDistribution.cxx @@ -94,6 +94,7 @@ void StdMeshers_LayerDistribution::SetLayerDistribution(SMESH_Hypothesis* hyp1D) ostream & StdMeshers_LayerDistribution::SaveTo(ostream & save) { + save << "StdMeshers_LayerDistribution"; // just to enable "Edit" in pop-up menu return save; } diff --git a/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx index 6c7e9b18b..5317368ea 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_LayerDistributionParamWdg.cxx @@ -207,7 +207,11 @@ void StdMeshersGUI_LayerDistributionParamWdg::onEdit() if ( !editor ) return; if ( myDlg ) - myDlg->hide(); + { + //myDlg->hide(); -- pb: show() does not work + myDlg->setWindowTitle( tr( "SMESH_HYPOTHESIS" )); + myDlg->setEnabled(false); + } try { QWidget* parent = this; @@ -223,5 +227,8 @@ void StdMeshersGUI_LayerDistributionParamWdg::onEdit() void StdMeshersGUI_LayerDistributionParamWdg::onEdited( int result ) { if ( myDlg ) - myDlg->show(); + { + //myDlg->show(); does not work + myDlg->setEnabled(true); + } } From bba8dbd724830208d6c47f89c5a3a117a9489970 Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 26 May 2020 17:46:38 +0300 Subject: [PATCH 03/25] IPAL54678: TC-9.5.0: Sub-mesh priority: not all sub-meshes are displayed in the dialog --- src/SMESH_I/SMESH_Mesh_i.cxx | 42 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 52f7e9e9c..470ca6587 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -568,7 +568,7 @@ namespace //================================================================================ /*! - * \brief Import data from a GMF file and Return an error description + * \brief Import data from a GMF file and return an error description */ //================================================================================ @@ -4972,7 +4972,7 @@ SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID) //============================================================================= /*! * Return ID of nodes for given sub-mesh - * If param all==true - Return all nodes, else - + * If param all==true - return all nodes, else - * Return only nodes on shapes. */ //============================================================================= @@ -5079,7 +5079,7 @@ CORBA::LongLong SMESH_Mesh_i::GetMeshPtr() //============================================================================= /*! * Get XYZ coordinates of node as list of double - * If there is not node for given ID - Return empty list + * If there is not node for given ID - return empty list */ //============================================================================= @@ -5109,8 +5109,8 @@ SMESH::double_array* SMESH_Mesh_i::GetNodeXYZ(const CORBA::Long id) //============================================================================= /*! - * For given node Return list of IDs of inverse elements - * If there is not node for given ID - Return empty list + * For given node return list of IDs of inverse elements + * If there is not node for given ID - return empty list */ //============================================================================= @@ -5243,8 +5243,8 @@ SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID) //============================================================================= /*! - * If given element is node Return IDs of shape from position - * If there is not node for given ID - Return -1 + * If given element is node return IDs of shape from position + * If there is not node for given ID - return -1 */ //============================================================================= @@ -5271,7 +5271,7 @@ CORBA::Long SMESH_Mesh_i::GetShapeID(const CORBA::Long id) /*! * For given element return ID of result shape after * ::FindShape() from SMESH_MeshEditor - * If there is not element for given ID - Return -1 + * If there is not element for given ID - return -1 */ //============================================================================= @@ -5301,7 +5301,7 @@ CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id) //============================================================================= /*! * Return number of nodes for given element - * If there is not element for given ID - Return -1 + * If there is not element for given ID - return -1 */ //============================================================================= @@ -5322,8 +5322,8 @@ CORBA::Long SMESH_Mesh_i::GetElemNbNodes(const CORBA::Long id) //============================================================================= /*! * Return ID of node by given index for given element - * If there is not element for given ID - Return -1 - * If there is not node for given index - Return -2 + * If there is not element for given ID - return -1 + * If there is not node for given index - return -2 */ //============================================================================= @@ -6045,7 +6045,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Mesh_i::GetMesh() //================================================================================ /*! - * \brief Return false if GetMeshInfo() Return incorrect information that may + * \brief Return false if GetMeshInfo() return incorrect information that may * happen if mesh data is not yet fully loaded from the file of study. * * @@ -6425,7 +6425,7 @@ class SMESH_DimHyp //! fields int _dim; //!< a dimension the algo can build (concurrent dimension) int _ownDim; //!< dimension of shape of _subMesh (>=_dim) - TopTools_MapOfShape _shapeMap; + TopTools_MapOfShape _shapeMap; //!< [sub-]shapes of dimension == _dim SMESH_subMesh* _subMesh; list _hypotheses; //!< algo is first, then its parameters @@ -6522,9 +6522,11 @@ class SMESH_DimHyp bool isSame = checkAlgo( a1, a2 ); if ( !isSame ) { - if ( !a1 || !a2 ) - return false; // pb? - return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency ! + return true; + // commented for IPAL54678 + // if ( !a1 || !a2 ) + // return false; // pb? + // return a1->GetDim() == a2->GetDim(); // different algorithms of same dim -> concurrency ! } // check hypothesises for concurrence (skip first as algorithm) @@ -6565,6 +6567,9 @@ void addDimHypInstance(const int theDim, const list & theHypList, TDimHypList* theDimHypListArr ) { + if ( !theAlgo->NeedDiscreteBoundary() && + theAlgo->NeedLowerHyps( theDim )) // IPAL54678 + return; TDimHypList& listOfdimHyp = theDimHypListArr[theDim]; if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) { SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape ); @@ -6707,7 +6712,7 @@ CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID) //============================================================================= /*! - * \brief Return submesh objects list in meshing order + * \brief Return sub-mesh objects list in meshing order */ //============================================================================= @@ -6776,7 +6781,8 @@ TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes() continue; // no algorithm assigned to a current submesh int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp) - // the submesh can concurrent at (or lower dims if !anAlgo->NeedDiscreteBoundary()) + // the submesh can concurrent at (or lower dims if !anAlgo->NeedDiscreteBoundary() + // and !anAlgo->NeedLowerHyps( dim )) // create instance of dimension-hypothesis for found concurrent dimension(s) and algorithm for ( int j = anAlgo->NeedDiscreteBoundary() ? dim : 1, jn = dim; j <= jn; j++ ) From 2a5ef76d25b4416b4abcd7e968586423b06b3eb4 Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 27 May 2020 15:46:46 +0300 Subject: [PATCH 04/25] Fix failure of HEXOTIC/doc/salome/examples/hexoticdemo.py --- src/SMESHUtils/SMESH_ControlPnt.cxx | 93 ++++++++++++++--------------- src/SMESHUtils/SMESH_ControlPnt.hxx | 28 ++++----- 2 files changed, 57 insertions(+), 64 deletions(-) diff --git a/src/SMESHUtils/SMESH_ControlPnt.cxx b/src/SMESHUtils/SMESH_ControlPnt.cxx index 16ab68651..2e644c135 100644 --- a/src/SMESHUtils/SMESH_ControlPnt.cxx +++ b/src/SMESHUtils/SMESH_ControlPnt.cxx @@ -58,9 +58,10 @@ namespace SMESHUtils const double& theSize, std::vector& thePoints ); - std::vector computePointsForSplitting( const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pnt& p3 ); + void computePointsForSplitting( const gp_Pnt& p1, + const gp_Pnt& p2, + const gp_Pnt& p3, + gp_Pnt midPoints[3]); gp_Pnt tangencyPoint(const gp_Pnt& p1, const gp_Pnt& p2, const gp_Pnt& Center); @@ -164,8 +165,7 @@ void SMESHUtils::createPointsSampleFromFace( const TopoDS_Face& theFace, // Get triangles int nbTriangles = aTri->NbTriangles(); - Poly_Array1OfTriangle triangles(1,nbTriangles); - triangles=aTri->Triangles(); + const Poly_Array1OfTriangle& triangles = aTri->Triangles(); // GetNodes int nbNodes = aTri->NbNodes(); @@ -173,9 +173,10 @@ void SMESHUtils::createPointsSampleFromFace( const TopoDS_Face& theFace, nodes = aTri->Nodes(); // Iterate on triangles and subdivide them - for(int i=1; i<=nbTriangles; i++) + thePoints.reserve( thePoints.size() + nbTriangles ); + for ( int i = 1; i <= nbTriangles; i++ ) { - Poly_Triangle aTriangle = triangles.Value(i); + const Poly_Triangle& aTriangle = triangles.Value(i); gp_Pnt p1 = nodes.Value(aTriangle.Value(1)); gp_Pnt p2 = nodes.Value(aTriangle.Value(2)); gp_Pnt p3 = nodes.Value(aTriangle.Value(3)); @@ -184,7 +185,7 @@ void SMESHUtils::createPointsSampleFromFace( const TopoDS_Face& theFace, p2.Transform(aTrsf); p3.Transform(aTrsf); - subdivideTriangle(p1, p2, p3, theSize, thePoints); + subdivideTriangle( p1, p2, p3, theSize, thePoints ); } } @@ -221,10 +222,8 @@ void SMESHUtils::createPointsSampleFromSolid( const TopoDS_Solid& theSolid, // Step2 : for each face of theSolid: std::set intersections; - std::set::iterator it = intersections.begin(); - TopExp_Explorer Ex; - for (Ex.Init(theSolid,TopAbs_FACE); Ex.More(); Ex.Next()) + for ( TopExp_Explorer Ex( theSolid, TopAbs_FACE ); Ex.More(); Ex.Next() ) { // check if there is an intersection IntCurvesFace_Intersector anIntersector(TopoDS::Face(Ex.Current()), Precision::Confusion()); @@ -232,13 +231,13 @@ void SMESHUtils::createPointsSampleFromSolid( const TopoDS_Solid& theSolid, // get the intersection's parameter and store it int nbPoints = anIntersector.NbPnt(); - for(int i = 0 ; i < nbPoints ; i++ ) + for ( int i = 0 ; i < nbPoints; i++ ) { - it = intersections.insert( it, anIntersector.WParameter(i+1) ); + intersections.insert( anIntersector.WParameter(i+1) ); } } // Step3 : go through the line chunk by chunk - if ( intersections.begin() != intersections.end() ) + if ( intersections.size() > 1 ) { std::set::iterator intersectionsIterator=intersections.begin(); double first = *intersectionsIterator; @@ -254,9 +253,9 @@ void SMESHUtils::createPointsSampleFromSolid( const TopoDS_Solid& theSolid, double localStep = (second -first) / ceil( (second - first) / step ); for ( double z = Zmin + first; z < Zmin + second; z = z + localStep ) { - thePoints.push_back(ControlPnt( x, y, z, theSize )); + thePoints.emplace_back( x, y, z, theSize ); } - thePoints.push_back(ControlPnt( x, y, Zmin + second, theSize )); + thePoints.emplace_back( x, y, Zmin + second, theSize ); } first = second; innerPoints = !innerPoints; @@ -288,45 +287,45 @@ void SMESHUtils::subdivideTriangle( const gp_Pnt& p1, // and the distance between two mass centers of two neighbouring triangles // sharing an edge is < 2 * 1/2 * S = S // If the traingles share a Vertex and no Edge the distance of the mass centers - // to the Vertices is 2*D < S so the mass centers are distant of less than 2*S + // to the Vertices is 2*D < S so the mass centers are distant of less than 2*S double threshold = sqrt( 3. ) * theSize; - if ( (p1.Distance(p2) > threshold || - p2.Distance(p3) > threshold || - p3.Distance(p1) > threshold)) - { - std::vector midPoints = computePointsForSplitting(p1, p2, p3); + if ( p1.Distance(p2) > threshold || + p2.Distance(p3) > threshold || + p3.Distance(p1) > threshold ) + try + { + gp_Pnt midPoints[3]; + computePointsForSplitting( p1, p2, p3, midPoints ); - subdivideTriangle( midPoints[0], midPoints[1], midPoints[2], theSize, thePoints ); - subdivideTriangle( midPoints[0], p2, midPoints[1], theSize, thePoints ); - subdivideTriangle( midPoints[2], midPoints[1], p3, theSize, thePoints ); - subdivideTriangle( p1, midPoints[0], midPoints[2], theSize, thePoints ); - } - else - { - double x = (p1.X() + p2.X() + p3.X()) / 3 ; - double y = (p1.Y() + p2.Y() + p3.Y()) / 3 ; - double z = (p1.Z() + p2.Z() + p3.Z()) / 3 ; + subdivideTriangle( midPoints[0], midPoints[1], midPoints[2], theSize, thePoints ); + subdivideTriangle( midPoints[0], p2, midPoints[1], theSize, thePoints ); + subdivideTriangle( midPoints[2], midPoints[1], p3, theSize, thePoints ); + subdivideTriangle( p1, midPoints[0], midPoints[2], theSize, thePoints ); + return; + } + catch (...) + { + } - ControlPnt massCenter( x ,y ,z, theSize ); - thePoints.push_back( massCenter ); - } + gp_Pnt massCenter = ( p1.XYZ() + p2.XYZ() + p3.XYZ() ) / 3.; + thePoints.emplace_back( massCenter, theSize ); } //================================================================================ /*! * \brief Returns the appropriate points for splitting a triangle - * \brief the tangency points of the incircle are used in order to have mostly - * \brief well-shaped sub-triangles + * the tangency points of the incircle are used in order to have mostly + * well-shaped sub-triangles */ //================================================================================ -std::vector SMESHUtils::computePointsForSplitting( const gp_Pnt& p1, - const gp_Pnt& p2, - const gp_Pnt& p3 ) +void SMESHUtils::computePointsForSplitting( const gp_Pnt& p1, + const gp_Pnt& p2, + const gp_Pnt& p3, + gp_Pnt midPoints[3]) { - std::vector midPoints; //Change coordinates gp_Trsf Trsf_1; // Identity transformation gp_Ax3 reference_system(gp::Origin(), gp::DZ(), gp::DX()); // OXY @@ -359,15 +358,11 @@ std::vector SMESHUtils::computePointsForSplitting( const gp_Pnt& p1, gp_Pnt T2 = tangencyPoint( B, C, Center); gp_Pnt T3 = tangencyPoint( C, A, Center); - gp_Pnt p1_2 = T1.Transformed(Trsf_1.Inverted()); - gp_Pnt p2_3 = T2.Transformed(Trsf_1.Inverted()); - gp_Pnt p3_1 = T3.Transformed(Trsf_1.Inverted()); + midPoints[0] = T1.Transformed(Trsf_1.Inverted()); + midPoints[1] = T2.Transformed(Trsf_1.Inverted()); + midPoints[2] = T3.Transformed(Trsf_1.Inverted()); - midPoints.push_back(p1_2); - midPoints.push_back(p2_3); - midPoints.push_back(p3_1); - - return midPoints; + return; } //================================================================================ diff --git a/src/SMESHUtils/SMESH_ControlPnt.hxx b/src/SMESHUtils/SMESH_ControlPnt.hxx index 9ebdd909a..f19da4aa9 100644 --- a/src/SMESHUtils/SMESH_ControlPnt.hxx +++ b/src/SMESHUtils/SMESH_ControlPnt.hxx @@ -42,11 +42,9 @@ namespace SMESHUtils { ControlPnt() : gp_Pnt(), size(0) {} - ControlPnt( const gp_Pnt& aPnt, double theSize) + ControlPnt( const gp_Pnt& aPnt, double theSize=0) : gp_Pnt( aPnt ), size( theSize ) {} - ControlPnt(double theX,double theY,double theZ) - : gp_Pnt(theX, theY, theZ), size(0) {} - ControlPnt(double theX,double theY,double theZ, double theSize) + ControlPnt(double theX,double theY,double theZ, double theSize=0) : gp_Pnt(theX, theY, theZ), size( theSize ) {} double Size() const { return size; }; @@ -57,20 +55,20 @@ namespace SMESHUtils // Functions to get sample point from shapes SMESHUtils_EXPORT void createControlPoints( const TopoDS_Shape& theShape, - const double& theSize, - std::vector< ControlPnt >& thePoints ); + const double& theSize, + std::vector< ControlPnt >& thePoints ); - SMESHUtils_EXPORT void createPointsSampleFromEdge( const TopoDS_Edge& theEdge, - const double& theSize, - std::vector& thePoints ); + SMESHUtils_EXPORT void createPointsSampleFromEdge( const TopoDS_Edge& theEdge, + const double& theSize, + std::vector& thePoints ); - SMESHUtils_EXPORT void createPointsSampleFromFace( const TopoDS_Face& theFace, - const double& theSize, - std::vector& thePoints ); + SMESHUtils_EXPORT void createPointsSampleFromFace( const TopoDS_Face& theFace, + const double& theSize, + std::vector& thePoints ); - SMESHUtils_EXPORT void createPointsSampleFromSolid( const TopoDS_Solid& theSolid, - const double& theSize, - std::vector& thePoints ); + SMESHUtils_EXPORT void createPointsSampleFromSolid( const TopoDS_Solid& theSolid, + const double& theSize, + std::vector& thePoints ); } #endif From 67c4262d23fd530aa1511fb482858a7880d41d6f Mon Sep 17 00:00:00 2001 From: rnv Date: Wed, 27 May 2020 23:56:31 +0300 Subject: [PATCH 05/25] Fix for '54677: TC-9.5.0: SMESH: ball visualization failed' --- src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx b/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx index e4654aa62..165b1487c 100644 --- a/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_AddMeshElementDlg.cxx @@ -217,6 +217,7 @@ namespace SMESH void SetBallPosition(SMESH_Actor* theActor,TVTKIds& theIds, double theDiameter) { vtkUnstructuredGrid *aGrid = theActor->GetUnstructuredGrid(); + myBallPolyData->SetPoints(NULL); myBallPolyData->Reset(); myBallPolyData->DeleteCells(); myBallPolyData->SetPoints(aGrid->GetPoints()); From 593c663f2d8d9d874b2b0301d601c2e01818337b Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 28 May 2020 16:44:33 +0300 Subject: [PATCH 06/25] Fix for #19201: Can't select a SHAPER result to create a group on geometry --- src/SMESHGUI/SMESHGUI_GroupDlg.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx index 5d33b4793..21b33c443 100644 --- a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx @@ -1402,9 +1402,11 @@ void SMESHGUI_GroupDlg::onObjectSelectionChanged() SALOME_ListIteratorOfListIO anIt (aList); for (; anIt.More(); anIt.Next()) { - aGeomGroup = GEOMBase::ConvertIOinGEOMObject(anIt.Value()); - + CORBA::Object_var aGroupObj = SMESH::IObjectToObject(anIt.Value()); + if (CORBA::is_nil(aGroupObj)) + continue; // Check if the object is a geometry group + aGeomGroup = GEOM::GEOM_Object::_narrow(aGroupObj); if (CORBA::is_nil(aGeomGroup)) continue; From b9ebe1deb0b108912e76dcfa187525dcd9392847 Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 3 Jun 2020 17:10:45 +0300 Subject: [PATCH 07/25] A quick-fix for the #19221 smeshBuilder Mesh.Group(group) does not work on SHAPERSTUDY groups --- src/SMESH_SWIG/smeshBuilder.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index cb0191fcc..3cb09bd0e 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -2636,7 +2636,15 @@ class Mesh(metaclass = MeshMeta): elif tgeo == "SOLID" or tgeo == "COMPSOLID": typ = VOLUME elif tgeo == "COMPOUND": - sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"]) + try: + sub = self.geompyD.SubShapeAll( shape, self.geompyD.ShapeType["SHAPE"]) + except: + # try to get the SHAPERSTUDY engine directly, because GetGen does not work because of + # simplification of access in geomBuilder: omniORB.registerObjref + from SHAPERSTUDY_utils import getEngine + gen = getEngine() + if gen: + sub = gen.GetIShapesOperations().ExtractSubShapes(shape, self.geompyD.ShapeType["SHAPE"], False) if not sub: raise ValueError("_groupTypeFromShape(): empty geometric group or compound '%s'" % GetName(shape)) return self._groupTypeFromShape( sub[0] ) From cc893fddd47e00b1d78dc1816dcdac316357e6c8 Mon Sep 17 00:00:00 2001 From: mpv Date: Fri, 5 Jun 2020 11:59:23 +0300 Subject: [PATCH 08/25] Fix for the issue #19226 : ViscousLayers2D can't be created on a group from SHAPERSTUDY in python --- src/SMESH_SWIG/smesh_algorithm.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/SMESH_SWIG/smesh_algorithm.py b/src/SMESH_SWIG/smesh_algorithm.py index e7003b509..768900eb0 100644 --- a/src/SMESH_SWIG/smesh_algorithm.py +++ b/src/SMESH_SWIG/smesh_algorithm.py @@ -340,9 +340,17 @@ class Mesh_Algorithm: if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ): faceIDs = [] for shape in faces: - ff = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["FACE"] ) - for f in ff: + try: + ff = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["FACE"] ) + for f in ff: faceIDs.append( self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f)) + except: + # try to get the SHAPERSTUDY engine directly, because GetGen does not work because of + # simplification of access in geomBuilder: omniORB.registerObjref + from SHAPERSTUDY_utils import getEngine + gen = getEngine() + if gen: + faceIDs = gen.GetIShapesOperations().GetAllSubShapesIDs(shape, self.mesh.geompyD.ShapeType["FACE"], False) faces = faceIDs hyp = self.Hypothesis("ViscousLayers", [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore], @@ -392,9 +400,17 @@ class Mesh_Algorithm: if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ): edgeIDs = [] for shape in edges: + try: ee = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["EDGE"]) for e in ee: - edgeIDs.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, e )) + edgeIDs.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, e )) + except: + # try to get the SHAPERSTUDY engine directly, because GetGen does not work because of + # simplification of access in geomBuilder: omniORB.registerObjref + from SHAPERSTUDY_utils import getEngine + gen = getEngine() + if gen: + edgeIDs = gen.GetIShapesOperations().GetAllSubShapesIDs(shape, self.mesh.geompyD.ShapeType["EDGE"], False) edges = edgeIDs hyp = self.Hypothesis("ViscousLayers2D", [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore], From a18dd5f05c809336926702c6e157386a48966b75 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 9 Jun 2020 14:01:07 +0300 Subject: [PATCH 09/25] Fix for #19226 : ViscousLayers2D can't be created on a group from SHAPERSTUDY in python --- src/SMESH_SWIG/smesh_algorithm.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/SMESH_SWIG/smesh_algorithm.py b/src/SMESH_SWIG/smesh_algorithm.py index 768900eb0..8ee3718a3 100644 --- a/src/SMESH_SWIG/smesh_algorithm.py +++ b/src/SMESH_SWIG/smesh_algorithm.py @@ -350,7 +350,10 @@ class Mesh_Algorithm: from SHAPERSTUDY_utils import getEngine gen = getEngine() if gen: - faceIDs = gen.GetIShapesOperations().GetAllSubShapesIDs(shape, self.mesh.geompyD.ShapeType["FACE"], False) + aShapeOp = gen.GetIShapesOperations() + ff = aShapeOp.ExtractSubShapes( shape, self.mesh.geompyD.ShapeType["FACE"], False) + for f in ff: + faceIDs.append( aShapeOp.GetSubShapeIndex( self.mesh.geom, f )) faces = faceIDs hyp = self.Hypothesis("ViscousLayers", [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore], @@ -410,7 +413,10 @@ class Mesh_Algorithm: from SHAPERSTUDY_utils import getEngine gen = getEngine() if gen: - edgeIDs = gen.GetIShapesOperations().GetAllSubShapesIDs(shape, self.mesh.geompyD.ShapeType["EDGE"], False) + aShapeOp = gen.GetIShapesOperations() + ee = aShapeOp.ExtractSubShapes( shape, self.mesh.geompyD.ShapeType["EDGE"], False) + for e in ee: + edgeIDs.append( aShapeOp.GetSubShapeIndex( self.mesh.geom, e )) edges = edgeIDs hyp = self.Hypothesis("ViscousLayers2D", [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore], From 1a39b08ad98ef275f4b75e220cc4fb390381f757 Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 9 Jun 2020 15:09:07 +0300 Subject: [PATCH 10/25] #19232 [CEA] overal Mesh quality crash on imported MED Bug reason: the med file includes polygons based on none of nodes. Solution: forbid creating such polygons --- src/SMDS/SMDS_Mesh.cxx | 4 ++++ src/SMESH_I/SMESH_MeshEditor_i.cxx | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/SMDS/SMDS_Mesh.cxx b/src/SMDS/SMDS_Mesh.cxx index a5af798e5..353d07893 100644 --- a/src/SMDS/SMDS_Mesh.cxx +++ b/src/SMDS/SMDS_Mesh.cxx @@ -831,6 +831,8 @@ SMDS_Mesh::AddPolygonalFaceWithID (const std::vector & nod { if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); + if ( nodes.empty() ) + throw std::invalid_argument("Polygon without nodes is forbidden"); if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID )) { cell->init( SMDSEntity_Polygon, nodes ); @@ -874,6 +876,8 @@ SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector & const int ID) { if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory(); + if ( nodes.empty() ) + throw std::invalid_argument("Polygon without nodes is forbidden"); if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID )) { cell->init( SMDSEntity_Quad_Polygon, nodes ); diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 5ae3c6a6e..16cc20053 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -1069,6 +1069,12 @@ CORBA::Long SMESH_MeshEditor_i::AddPolygonalFace (const SMESH::long_array & IDsO if ( ! ( nodes[i] = getMeshDS()->FindNode( IDsOfNodes[i] ))) return 0; + if ( NbNodes == 0 ) + { + INFOS("Polygon without nodes is forbidden"); + return 0; + } + const SMDS_MeshElement* elem = getMeshDS()->AddPolygonalFace(nodes); // Update Python script @@ -1098,6 +1104,12 @@ CORBA::Long SMESH_MeshEditor_i::AddQuadPolygonalFace (const SMESH::long_array & for (int i = 0; i < NbNodes; i++) nodes[i] = getMeshDS()->FindNode(IDsOfNodes[i]); + if ( NbNodes == 0 ) + { + INFOS("Polygon without nodes is forbidden"); + return 0; + } + const SMDS_MeshElement* elem = getMeshDS()->AddQuadPolygonalFace(nodes); // Update Python script From 9beb8d27644a2b0e2585bea7f990457a3d80d643 Mon Sep 17 00:00:00 2001 From: vsr Date: Mon, 15 Jun 2020 18:44:50 +0300 Subject: [PATCH 11/25] bos #19219 [CEA] SIGSEGV when right-click in the view in 3D layers dialog box --- src/SMESHGUI/SMESHGUI_Selection.cxx | 34 ++++++++++++++--------------- src/SMESHGUI/SMESHGUI_Selection.h | 2 -- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/SMESHGUI/SMESHGUI_Selection.cxx b/src/SMESHGUI/SMESHGUI_Selection.cxx index 6f59abd8c..5abe5c5be 100644 --- a/src/SMESHGUI/SMESHGUI_Selection.cxx +++ b/src/SMESHGUI/SMESHGUI_Selection.cxx @@ -43,8 +43,6 @@ #include #include #include -#include -#include // IDL includes #include @@ -79,8 +77,6 @@ void SMESHGUI_Selection::init( const QString& client, LightApp_SelectionMgr* mgr if( mgr ) { - myOwners.clear(); - mgr->selected(myOwners, client); for( int i=0, n=count(); i= 0 && ind < myTypes.count()) { - if (isReference(ind)) { - SUIT_DataOwner* aOwn = myOwners.at(ind); - LightApp_DataOwner* sowner = dynamic_cast(aOwn); - QString aEntry = sowner->entry(); - _PTR(SObject) aSObject = SMESH::getStudy()->FindObjectID(aEntry.toStdString()); - _PTR(SObject) aFatherObj = aSObject->GetFather(); - _PTR(SComponent) aComponent = aFatherObj->GetFatherComponent(); - if (aComponent->ComponentDataType() == "SMESH") { - QString aObjEntry = entry(ind); - _PTR(SObject) aGeomSObject = SMESH::getStudy()->FindObjectID(aObjEntry.toStdString()); - GEOM::GEOM_Object_var aObject = SMESH::SObjectToInterface(aGeomSObject); - if (!aObject->_is_nil()) - return aObject->IsParametrical(); + if ( ind >= 0 && isReference(ind) ) { + QString aEntry = objectInfo(ind, OI_RefEntry).toString(); + if (!aEntry.isEmpty()) { + _PTR(SObject) aSObject = SMESH::getStudy()->FindObjectID( aEntry.toStdString()); + if (aSObject) { + _PTR(SObject) aFatherObj = aSObject->GetFather(); + if (aFatherObj) { + _PTR(SComponent) aComponent = aFatherObj->GetFatherComponent(); + if (aComponent && aComponent->ComponentDataType() == "SMESH") { + QString aObjEntry = entry(ind); + _PTR(SObject) aGeomSObject = SMESH::getStudy()->FindObjectID(aObjEntry.toStdString()); + GEOM::GEOM_Object_var aObject = SMESH::SObjectToInterface(aGeomSObject); + if (!aObject->_is_nil()) + return aObject->IsParametrical(); + } + } } } } diff --git a/src/SMESHGUI/SMESHGUI_Selection.h b/src/SMESHGUI/SMESHGUI_Selection.h index 5d23e768f..e4b0641e0 100644 --- a/src/SMESHGUI/SMESHGUI_Selection.h +++ b/src/SMESHGUI/SMESHGUI_Selection.h @@ -32,7 +32,6 @@ // SALOME GUI includes #include -#include // SALOME KERNEL includes #include @@ -97,7 +96,6 @@ private: QStringList myTypes; QStringList myControls; QList myActors; - SUIT_DataOwnerPtrList myOwners; }; #endif // SMESHGUI_SELECTION_H From 29c693b1c362e8045aaab556ec5d8c612294e22e Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 8 Jul 2020 12:46:18 +0300 Subject: [PATCH 12/25] #18708 EDF 20746 - Strange behaviors after loading YACS Pb was in clashing class names (chrono.hxx) in SMESH and YACS --- src/SMDS/chrono.cxx | 1 + src/SMDS/chrono.hxx | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/SMDS/chrono.cxx b/src/SMDS/chrono.cxx index ae198d95f..c4ad47ec4 100644 --- a/src/SMDS/chrono.cxx +++ b/src/SMDS/chrono.cxx @@ -21,6 +21,7 @@ #include "utilities.h" using namespace std; +using namespace SMDS; cntStruct* counters::_ctrs = 0; int counters::_nbChrono = 0; diff --git a/src/SMDS/chrono.hxx b/src/SMDS/chrono.hxx index 3fdae2eb2..032ac935c 100644 --- a/src/SMDS/chrono.hxx +++ b/src/SMDS/chrono.hxx @@ -27,6 +27,8 @@ #include #include +namespace SMDS +{ typedef struct acnt { char* _ctrNames; @@ -57,9 +59,11 @@ protected: int _ctr; clock_t _start, _end; }; - +} #ifdef CHRONODEF -#define CHRONO(i) counters::_ctrs[i]._ctrNames = (char *)__FILE__; \ +#define CHRONO(i) + using namespace SMDS; \ + counters::_ctrs[i]._ctrNames = (char *)__FILE__; \ counters::_ctrs[i]._ctrLines = __LINE__; \ salome_chrono aChrono##i(i); @@ -67,7 +71,7 @@ protected: #else // CHRONODEF -#define CHRONO(i) +#define CHRONO(i) using namespace SMDS; #define CHRONOSTOP(i) #endif // CHRONODEF From e85e13ee2a8e2484050471ff8e4dea298abe481a Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 20 Jul 2020 10:13:03 +0300 Subject: [PATCH 13/25] #19765 EDF 21730 - long time to load med file file with huge amount of groups --- src/SMESHGUI/SMESHGUI_GroupDlg.cxx | 51 +++++++++++++++++++++-------- src/SMESHGUI/SMESHGUI_Selection.cxx | 18 +++++----- src/SMESH_I/SMESH_Mesh_i.cxx | 16 ++++++--- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx index 21b33c443..2313c768c 100644 --- a/src/SMESHGUI/SMESHGUI_GroupDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_GroupDlg.cxx @@ -74,6 +74,7 @@ #include // OCCT includes +#include #include // Qt includes @@ -522,19 +523,38 @@ QString SMESHGUI_GroupDlg::GetDefaultName(const QString& theOperation) return aName; } +//======================================================================= +//function : setDefaultName +//purpose : +//======================================================================= + void SMESHGUI_GroupDlg::setDefaultName() const { QString aResName; - int i=1; - QString aPrefix ="Group_"; - _PTR(SObject) anObj; - do + const QString aPrefix ="Group_"; + + if ( myMesh->_is_nil() ) { - aResName = aPrefix + QString::number( i++ ); - anObj = SMESH::getStudy()->FindObject( aResName.toUtf8().constData() ); + aResName = aPrefix + "1"; } - while ( anObj ); - myName->setText(aResName); + else + { + SMESH::ListOfGroups_var allGroups = myMesh->GetGroups(); + TColStd_MapOfAsciiString allNames( allGroups->length() ); + for ( CORBA::ULong i = 0; i < allGroups->length(); ++i ) + { + CORBA::String_var name = allGroups[i]->GetName(); + allNames.Add( name.in() ); + } + int i = 1; + while ( true ) + { + aResName = aPrefix + QString::number( i++ ); + if ( !allNames.Contains( aResName.toUtf8().constData() )) + break; + } + } + myName->setText(aResName); } //================================================================================= @@ -944,7 +964,8 @@ bool SMESHGUI_GroupDlg::onApply() if (myGroup->_is_nil()) { // creation or conversion // check if group on geometry is not null - if (!myGroupOnGeom->_is_nil() || !myGroupOnFilter->_is_nil()) { + if (!myGroupOnGeom->_is_nil() || !myGroupOnFilter->_is_nil()) + { if (myMesh->_is_nil()) return false; if ( myGroupOnGeom->_is_nil() ) @@ -958,7 +979,8 @@ bool SMESHGUI_GroupDlg::onApply() } } - if (myGroup->_is_nil()) { // creation + if (myGroup->_is_nil()) // creation + { if (myMesh->_is_nil()) return false; @@ -990,10 +1012,10 @@ bool SMESHGUI_GroupDlg::onApply() myGroup->Add(anIdList.inout()); } } + } - - } else { // edition - + else // edition + { resultGroup = SMESH::SMESH_GroupBase::_narrow( myGroup ); isCreation = false; @@ -1111,6 +1133,7 @@ bool SMESHGUI_GroupDlg::onApply() } anIsOk = true; } + if (myGrpTypeId == 2) // group on filter { if ( myFilter->_is_nil() ) return false; @@ -1170,7 +1193,7 @@ bool SMESHGUI_GroupDlg::onApply() Handle(SALOME_InteractiveObject) anIO = anActor->getIO(); if ( isConversion ) { // need to reset TVisualObj and actor SMESH::RemoveVisualObjectWithActors( anIO->getEntry(), true ); - SMESH::Update( anIO,true); + SMESH::Update( anIO, true ); myActorsList.clear(); anActor = SMESH::FindActorByEntry( anIO->getEntry() ); if ( !anActor ) return false; diff --git a/src/SMESHGUI/SMESHGUI_Selection.cxx b/src/SMESHGUI/SMESHGUI_Selection.cxx index 3a32c569b..77d5abaa2 100644 --- a/src/SMESHGUI/SMESHGUI_Selection.cxx +++ b/src/SMESHGUI/SMESHGUI_Selection.cxx @@ -660,15 +660,15 @@ bool SMESHGUI_Selection::canBreakLink( int ind ) const if (!aEntry.isEmpty()) { _PTR(SObject) aSObject = SMESH::getStudy()->FindObjectID( aEntry.toStdString()); if (aSObject) { - _PTR(SObject) aFatherObj = aSObject->GetFather(); - if (aFatherObj) { - _PTR(SComponent) aComponent = aFatherObj->GetFatherComponent(); - if (aComponent && aComponent->ComponentDataType() == "SMESH") { - QString aObjEntry = entry(ind); - _PTR(SObject) aGeomSObject = SMESH::getStudy()->FindObjectID(aObjEntry.toStdString()); - GEOM::GEOM_Object_var aObject = SMESH::SObjectToInterface(aGeomSObject); - if (!aObject->_is_nil()) - return aObject->IsParametrical(); + _PTR(SObject) aFatherObj = aSObject->GetFather(); + if (aFatherObj) { + _PTR(SComponent) aComponent = aFatherObj->GetFatherComponent(); + if (aComponent && aComponent->ComponentDataType() == "SMESH") { + QString aObjEntry = entry(ind); + _PTR(SObject) aGeomSObject = SMESH::getStudy()->FindObjectID(aObjEntry.toStdString()); + GEOM::GEOM_Object_var aObject = SMESH::SObjectToInterface(aGeomSObject); + if (!aObject->_is_nil()) + return aObject->IsParametrical(); } } } diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 9c00cb31e..0f827b054 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -5821,15 +5821,21 @@ void SMESH_Mesh_i::CreateGroupServants() GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape ); _gen_i->PublishGroup( aMesh, groupVar, shapeVar, group->GetName()); } + if ( !addedIDs.empty() ) { // python dump - set::iterator id = addedIDs.begin(); - for ( ; id != addedIDs.end(); ++id ) + map::iterator i_grp = _mapGroups.begin(); + for ( int index = 0; i_grp != _mapGroups.end(); ++index, ++i_grp ) { - map::iterator it = _mapGroups.find(*id); - int i = std::distance( _mapGroups.begin(), it ); - TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]"; + set::iterator it = addedIDs.find( i_grp->first ); + if ( it != addedIDs.end() ) + { + TPythonDump() << i_grp->second << " = " << aMesh << ".GetGroups()[ "<< index << " ]"; + addedIDs.erase( it ); + if ( addedIDs.empty() ) + break; + } } } } From dbbd8a2dbee2a8ad0a41f0d01d280c25ab6a7e9f Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 31 Jul 2020 20:27:23 +0300 Subject: [PATCH 14/25] Protection for the case of python command wrapped over several lines --- src/SMESH_I/SMESH_2smeshpy.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 9ad385290..b36b31c13 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -3939,7 +3939,7 @@ int _pyCommand::GetArgBeginning() const if ( pos == UNKNOWN ) { pos = GetBegPos( METHOD_IND ) + myMeth.Length(); - if ( pos < 1 ) + if ( pos < 1 && Length() >= 4 ) pos = myString.Location( "(", 4, Length() ); // 4 = strlen("b.c(") } return pos; @@ -4024,6 +4024,11 @@ TCollection_AsciiString _pyCommand::GetWord( const _AString & theString, } theStartPos = beg; //cout << theString << " ---- " << beg << " - " << end << endl; + if ( end > theString.Length() ) + { + theStartPos = EMPTY; + return theEmptyString; + } return theString.SubString( beg, end ); } From f435fe5c8210fd6b1f0c4e1ab62e91babc0cfd28 Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 7 Aug 2020 12:14:55 +0300 Subject: [PATCH 15/25] Enable simultaneous usage of several StdMeshersGUI_SubShapeSelectorWdg's Add SMESH_Gen_i::CountInPyDump(text) which is useful for defining uniquely named variables in dump python scripts --- src/SMESH_I/SMESH_Gen_i.hxx | 2 + src/SMESH_I/SMESH_PythonDump.cxx | 56 ++++++++++++++++++- .../StdMeshersGUI_SubShapeSelectorWdg.cxx | 26 +++++++-- .../StdMeshersGUI_SubShapeSelectorWdg.h | 14 ++++- 4 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index 895f745fc..d6cb5b130 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -494,6 +494,8 @@ public: void CleanPythonTrace(); + static int CountInPyDump(const TCollection_AsciiString& text); + // ***************************************** // Internal methods // ***************************************** diff --git a/src/SMESH_I/SMESH_PythonDump.cxx b/src/SMESH_I/SMESH_PythonDump.cxx index 04a0fc9a8..e1c3002c0 100644 --- a/src/SMESH_I/SMESH_PythonDump.cxx +++ b/src/SMESH_I/SMESH_PythonDump.cxx @@ -40,6 +40,8 @@ #include #include +#include + #ifdef _DEBUG_ static int MYDEBUG = 0; #else @@ -77,7 +79,7 @@ namespace SMESH TCollection_AsciiString aCollection(Standard_CString(aString.c_str())); if(!aCollection.IsEmpty()) { - const std::string & objEntry = SMESH_Gen_i::GetSMESHGen()->GetLastObjEntry(); + const std::string & objEntry = aSMESHGen->GetLastObjEntry(); if ( !objEntry.empty() ) aCollection += (TVar::ObjPrefix() + objEntry ).c_str(); aSMESHGen->AddToPythonScript(aCollection); @@ -1388,3 +1390,55 @@ void SMESH_Gen_i::CleanPythonTrace() myPythonScript->Clear(); } } + +//================================================================================ +/*! + * \brief Count inclusions of a string in a raw Python dump script + */ +//================================================================================ + +int SMESH_Gen_i::CountInPyDump(const TCollection_AsciiString& theText) +{ + int count = 0; + + SALOMEDS::Study_var aStudy = getStudyServant(); + if ( CORBA::is_nil( aStudy )) + return count; + + SMESH_Gen_i* me = GetSMESHGen(); + CORBA::String_var compDataType = me->ComponentDataType(); + SALOMEDS::SObject_wrap aSO = aStudy->FindComponent( compDataType.in() ); + if ( CORBA::is_nil( aSO )) + return count; + + // Trace saved in the study + SALOMEDS::GenericAttribute_wrap attr; + if ( aSO->FindAttribute( attr.inout(), "AttributePythonObject" )) + { + SALOMEDS::AttributePythonObject_var pyAttr = + SALOMEDS::AttributePythonObject::_narrow( attr ); + CORBA::String_var script = pyAttr->GetObject(); + for ( const char * scriptPos = script.in(); true; ++scriptPos ) + if (( scriptPos = strstr( scriptPos, theText.ToCString() ))) + ++count; + else + break; + } + + // New python commands + if ( !me->myPythonScript.IsNull() ) + { + const int nbLines = me->myPythonScript->Length(); + for ( int i = 1; i <= nbLines; ++i ) + { + const TCollection_AsciiString& line = me->myPythonScript->Value( i ); + for ( int loc = 1; loc <= line.Length(); ++loc ) + if (( loc = line.Location( theText, loc, line.Length() ))) + ++count; + else + break; + } + } + + return count; +} diff --git a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx index 54560d8fc..31db0a7be 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.cxx @@ -74,7 +74,8 @@ StdMeshersGUI_SubShapeSelectorWdg ::StdMeshersGUI_SubShapeSelectorWdg( QWidget * parent, TopAbs_ShapeEnum subShType, const bool toShowList, - const bool toShowActivateBtn ): + const bool toShowActivateBtn, + const int minListWidth ): QWidget( parent ), myMaxSize( -1 ), myPreviewActor( 0 ) @@ -93,8 +94,8 @@ StdMeshersGUI_SubShapeSelectorWdg myAddButton = new QPushButton( tr( "SMESH_BUT_ADD" ), this ); myRemoveButton = new QPushButton( tr( "SMESH_BUT_REMOVE" ), this ); myListWidget->setSelectionMode( QListWidget::ExtendedSelection ); - myListWidget->setMinimumWidth(300); - myListWidget->setWrapping(true); + myListWidget->setMinimumWidth( minListWidth ); + myListWidget->setWrapping( true ); myActivateButton->setCheckable( true ); } else @@ -254,6 +255,20 @@ void StdMeshersGUI_SubShapeSelectorWdg::ShowPreview( bool visible) } } +//================================================================================ +/*! + * \brief Connect selection slots + * \param other - another StdMeshersGUI_ObjectReferenceParamWdg + */ +//================================================================================ + +void StdMeshersGUI_SubShapeSelectorWdg:: +AvoidSimultaneousSelection ( StdMeshersGUI_SubShapeSelectorWdg* other) +{ + connect(other, SIGNAL(selectionActivated()), this, SLOT(deactivateSelection())); + connect(this, SIGNAL(selectionActivated()), other, SLOT(deactivateSelection())); +} + //================================================================================ /*! * \brief Connect/disconnect to change of selection @@ -275,7 +290,7 @@ void StdMeshersGUI_SubShapeSelectorWdg::ActivateSelection( bool toActivate ) if ( toActivate ) { - connect( mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(selectionIntoArgument())); + connect( mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(selectionIntoArgument())); } else { @@ -284,6 +299,9 @@ void StdMeshersGUI_SubShapeSelectorWdg::ActivateSelection( bool toActivate ) if ( sender() == myActivateButton ) ShowPreview( toActivate ); + + if ( toActivate ) + emit selectionActivated(); } //================================================================================ diff --git a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h index 3f3d3bf12..9c4f14b35 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h +++ b/src/StdMeshersGUI/StdMeshersGUI_SubShapeSelectorWdg.h @@ -53,7 +53,8 @@ public: StdMeshersGUI_SubShapeSelectorWdg( QWidget* parent = 0, TopAbs_ShapeEnum subShType = TopAbs_EDGE, const bool toShowList = true, - const bool toShowSelectBtn = false); + const bool toShowSelectBtn = false, + const int minListWidth=300); ~StdMeshersGUI_SubShapeSelectorWdg(); SMESH::long_array_var GetListOfIDs(); @@ -82,12 +83,23 @@ public: SMESH_PreviewActorsCollection* GetActorCollection() { return myPreviewActor; } void ClearSelected(); + void AvoidSimultaneousSelection( StdMeshersGUI_SubShapeSelectorWdg* other); + public slots: + void ActivateSelection( bool ); + void deactivateSelection() { ActivateSelection( false ); } signals: void selectionChanged(); // in the list void shapeSelected(); // globally + /*! + * \brief Emitted when selection is activated + * + * Useful to deactivate one Object Reference param widget when an other + * one is activated + */ + void selectionActivated(); private: void updateState(); From 9d1d5827c693a4fc98a6597a4179be1196689c30 Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 10 Aug 2020 17:02:53 +0300 Subject: [PATCH 16/25] #19887 [CEA] Body fitting missing some faces and generates not-wanted splitted elements fix missing faces --- src/StdMeshers/StdMeshers_Cartesian_3D.cxx | 6 +++--- src/StdMeshers/StdMeshers_Cartesian_3D.hxx | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index ab129db36..4d47b2144 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -4958,7 +4958,7 @@ namespace /*! * \brief Return created volumes and volumes that can have free facet because of * skipped small volume. Also create mesh faces on free facets - * of adjacent not-cut volumes id the result volume is too small. + * of adjacent not-cut volumes if the result volume is too small. */ void Hexahedron::getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryElems ) { @@ -5005,8 +5005,8 @@ namespace if ( !faceID ) break; if ( _grid->IsInternal( faceID ) || - _grid->IsShared( faceID ) || - _grid->IsBoundaryFace( faceID )) + _grid->IsShared( faceID ) /*|| + _grid->IsBoundaryFace( faceID )*/) break; // create only if a new face will be used by other 3D algo } diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.hxx b/src/StdMeshers/StdMeshers_Cartesian_3D.hxx index 593646a74..18797e278 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.hxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.hxx @@ -35,6 +35,8 @@ * internal part of a solid shape and polyhedral volumes near the shape boundary. * * Issue 0021336 + * Issue #16523: Treatment of internal faces + * Issue #17237: Body fitting on sub-mesh */ class StdMeshers_CartesianParameters3D; From 6c91402a6fe67b9c815fe64b9aee625dd21d0ef1 Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 10 Aug 2020 17:16:36 +0300 Subject: [PATCH 17/25] Fix memory leaks in SMESHGUI_Displayer::canBeDisplayed() --- src/SMESHGUI/SMESHGUI_Displayer.cxx | 32 ++++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/SMESHGUI/SMESHGUI_Displayer.cxx b/src/SMESHGUI/SMESHGUI_Displayer.cxx index bfd048dc8..adeb2d736 100644 --- a/src/SMESHGUI/SMESHGUI_Displayer.cxx +++ b/src/SMESHGUI/SMESHGUI_Displayer.cxx @@ -89,7 +89,8 @@ SalomeApp_Study* SMESHGUI_Displayer::study() const return dynamic_cast( myApp->activeStudy() ); } -bool SMESHGUI_Displayer::canBeDisplayed( const QString& entry, const QString& viewer_type ) const { +bool SMESHGUI_Displayer::canBeDisplayed( const QString& entry, const QString& viewer_type ) const +{ bool res = false; if(viewer_type != SVTK_Viewer::Type()) return res; @@ -97,25 +98,18 @@ bool SMESHGUI_Displayer::canBeDisplayed( const QString& entry, const QString& vi _PTR(SObject) obj = SMESH::getStudy()->FindObjectID( (const char*)entry.toUtf8() ); CORBA::Object_var anObj = SMESH::SObjectToObject( obj ); - /* - if( !CORBA::is_nil( anObj ) ) { + if ( !CORBA::is_nil( anObj ) ) + { SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( anObj ); - if ( ! mesh->_is_nil() ) - res = (mesh->NbNodes() > 0); - - SMESH::SMESH_subMesh_var aSubMeshObj = SMESH::SMESH_subMesh::_narrow( anObj ); - if ( !aSubMeshObj->_is_nil() ) - res = (aSubMeshObj->GetNumberOfNodes(true) > 0); - - SMESH::SMESH_GroupBase_var aGroupObj = SMESH::SMESH_GroupBase::_narrow( anObj ); - if ( !aGroupObj->_is_nil() ) - res = !aGroupObj->IsEmpty(); - }*/ - if( !CORBA::is_nil( anObj ) ) { - if(!SMESH::SMESH_Mesh::_narrow( anObj )->_is_nil() || - !SMESH::SMESH_subMesh::_narrow( anObj )->_is_nil() || - !SMESH::SMESH_GroupBase::_narrow( anObj )->_is_nil()) - res = true; + if ( ! ( res = !mesh->_is_nil() )) + { + SMESH::SMESH_subMesh_var aSubMeshObj = SMESH::SMESH_subMesh::_narrow( anObj ); + if ( ! ( res = !aSubMeshObj->_is_nil() )) + { + SMESH::SMESH_GroupBase_var aGroupObj = SMESH::SMESH_GroupBase::_narrow( anObj ); + res = !aGroupObj->_is_nil(); + } + } } return res; } From c85f79dfcae99e7d2e339251ff51e07585bc52e4 Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 10 Aug 2020 17:42:16 +0300 Subject: [PATCH 18/25] Operation Show Meshing Errors does not work --- src/SMESHGUI/SMESHGUI.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index f638d0391..80211ac67 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -4694,7 +4694,7 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->insert( separator(), -1, 0 ); createPopupItem( SMESHOp::OpFileInformation, OB, mesh, "&& selcount=1 && isImported" ); createPopupItem( SMESHOp::OpMeshInformation, OB, mesh_part ); - createPopupItem( SMESHOp::OpFindElementByPoint,OB, mesh_group, "&& selcount=1" ); + createPopupItem( SMESHOp::OpFindElementByPoint,OB, mesh_group, "&& selcount=1 && " + hasElems ); createPopupItem( SMESHOp::OpOverallMeshQuality,OB, mesh_part ); popupMgr()->insert( separator(), -1, 0 ); createPopupItem( SMESHOp::OpCreateGroup, OB, mesh, "&& selcount=1" ); @@ -4704,7 +4704,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createPopupItem( SMESHOp::OpEditHypothesis, OB, hypo, "&& isEditableHyp"); createPopupItem( SMESHOp::OpUnassign, OB, hyp_alg ); popupMgr()->insert( separator(), -1, 0 ); - createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh_submesh ); + createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh_submesh, "&& " + hasElems ); createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh_group, "&& selcount=1 && dim>=2"); //popupMgr()->insert( separator(), -1, 0 ); @@ -4750,7 +4750,7 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->insert( separator(), -1, 0 ); createPopupItem( SMESHOp::OpMeshInformation, View, mesh_part ); createPopupItem( SMESHOp::OpOverallMeshQuality, View, mesh_part ); - createPopupItem( SMESHOp::OpFindElementByPoint, View, mesh ); + createPopupItem( SMESHOp::OpFindElementByPoint, View, mesh, "&& " + hasElems); popupMgr()->insert( separator(), -1, 0 ); createPopupItem( SMESHOp::OpUpdate, OB + " " + View, mesh_part ); @@ -5881,6 +5881,9 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const case SMESHOp::OpComputeSubMesh: op = new SMESHGUI_ComputeOp(); break; + case SMESHOp::OpShowErrors: + op = new SMESHGUI_ShowErrorsOp(); + break; case SMESHOp::OpPreCompute: op = new SMESHGUI_PrecomputeOp(); break; From eac64fdf48ad45a008fb7d48b1ff0e7633c04dfa Mon Sep 17 00:00:00 2001 From: eap Date: Mon, 10 Aug 2020 17:43:45 +0300 Subject: [PATCH 19/25] In dump script avoid removing missing geom objects --- src/SMESH_I/SMESH_PythonDump.cxx | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/SMESH_I/SMESH_PythonDump.cxx b/src/SMESH_I/SMESH_PythonDump.cxx index e1c3002c0..a09766949 100644 --- a/src/SMESH_I/SMESH_PythonDump.cxx +++ b/src/SMESH_I/SMESH_PythonDump.cxx @@ -1080,10 +1080,15 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl TCollection_AsciiString anUpdatedScript; Resource_DataMapOfAsciiStringAsciiString mapRemoved; - Resource_DataMapOfAsciiStringAsciiString mapEntries; // names and entries present in anUpdatedScript + Resource_DataMapOfAsciiStringAsciiString mapEntries; // { entry: name } present in anUpdatedScript Standard_Integer objectCounter = 0; TCollection_AsciiString anEntry, aName, aGUIName, aBaseName("smeshObj_"); + std::string compDataType = ComponentDataType(); // SMESH module's data type + SALOMEDS::SComponent_var smeshSO = getStudyServant()->FindComponent( compDataType.c_str() ); + CORBA::String_var smeshID = smeshSO->GetID(); + TCollection_AsciiString smeshEntry = smeshID.in(); + // Treat every script line and add it to anUpdatedScript for ( linesIt = lines.begin(); linesIt != lines.end(); ++linesIt ) { @@ -1135,15 +1140,22 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl } else { - // Removed Object - do { - aName = aBaseName + (++objectCounter); - } while (theObjectNames.IsBound(aName)); + if ( !anEntry.StartsWith( smeshEntry )) // not SMESH object + { + aName = SMESH::TPythonDump::NotPublishedObjectName(); + } + else + { + // Removed Object + do { + aName = aBaseName + (++objectCounter); + } while (theObjectNames.IsBound(aName)); - if ( !aRemovedObjIDs.count( anEntry ) && aLine.Value(1) != '#') - mapRemoved.Bind(anEntry, aName); + if ( !aRemovedObjIDs.count( anEntry ) && aLine.Value(1) != '#') + mapRemoved.Bind(anEntry, aName); - theObjectNames.Bind(anEntry, aName); + theObjectNames.Bind(anEntry, aName); + } } theObjectNames.Bind(aName, anEntry); // to detect same name of diff objects } From 14662b2361b82e89ae0e28b69da148128c3516de Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 12 Aug 2020 21:45:23 +0300 Subject: [PATCH 20/25] #19887 [CEA] Body fitting missing some faces and generates not-wanted splitted elements Excess edges removed (nodes still remain) --- src/StdMeshers/StdMeshers_Cartesian_3D.cxx | 315 ++++++++++++++++++--- 1 file changed, 273 insertions(+), 42 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index 4d47b2144..b26d2419c 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -362,6 +362,9 @@ namespace gp_XYZ _origin; gp_Mat _invB; // inverted basis of _axes + // index shift within _nodes of nodes of a cell from the 1st node + int _nodeShift[8]; + vector< const SMDS_MeshNode* > _nodes; // mesh nodes at grid nodes vector< const F_IntersectPoint* > _gridIntP; // grid node intersection with geometry ObjectPool< E_IntersectPoint > _edgeIntPool; // intersections with EDGEs @@ -427,6 +430,7 @@ namespace bool IsBoundaryFace( TGeomID face ) const { return _geometry._boundaryFaces.Contains( face ); } void SetOnShape( const SMDS_MeshNode* n, const F_IntersectPoint& ip, bool unset=false ); bool IsToCheckNodePos() const { return !_toAddEdges && _toCreateFaces; } + bool IsToRemoveExcessEntities() const { return !_toAddEdges; } void SetCoordinates(const vector& xCoords, const vector& yCoords, @@ -759,9 +763,13 @@ namespace // -------------------------------------------------------------------------------- struct _Face { + SMESH_Block::TShapeID _name; vector< _OrientedLink > _links; // links on GridLine's vector< _Link > _polyLinks; // links added to close a polygonal face vector< _Node* > _eIntNodes; // nodes at intersection with EDGEs + + _Face():_name( SMESH_Block::ID_NONE ) + {} bool IsPolyLink( const _OrientedLink& ol ) { return _polyLinks.empty() ? false : @@ -789,41 +797,72 @@ namespace // -------------------------------------------------------------------------------- struct _volumeDef // holder of nodes of a volume mesh element { + typedef void* _ptr; + struct _nodeDef { const SMDS_MeshNode* _node; // mesh node at hexahedron corner const B_IntersectPoint* _intPoint; + _nodeDef(): _node(0), _intPoint(0) {} _nodeDef( _Node* n ): _node( n->_node), _intPoint( n->_intPoint ) {} const SMDS_MeshNode* Node() const { return ( _intPoint && _intPoint->_node ) ? _intPoint->_node : _node; } const E_IntersectPoint* EdgeIntPnt() const { return static_cast< const E_IntersectPoint* >( _intPoint ); } + _ptr Ptr() const { return Node() ? (_ptr) Node() : (_ptr) EdgeIntPnt(); } }; + vector< _nodeDef > _nodes; vector< int > _quantities; _volumeDef* _next; // to store several _volumeDefs in a chain TGeomID _solidID; const SMDS_MeshElement* _volume; // new volume + vector< SMESH_Block::TShapeID > _names; // name of side a polygon originates from + _volumeDef(): _next(0), _solidID(0), _volume(0) {} ~_volumeDef() { delete _next; } _volumeDef( _volumeDef& other ): _next(0), _solidID( other._solidID ), _volume( other._volume ) - { _nodes.swap( other._nodes ); _quantities.swap( other._quantities ); other._volume = 0; } - - void Set( const vector< _Node* >& nodes, const vector< int >& quant = vector< int >() ) - { _nodes.assign( nodes.begin(), nodes.end() ); _quantities = quant; } + { _nodes.swap( other._nodes ); _quantities.swap( other._quantities ); other._volume = 0; + _names.swap( other._names ); } void Set( _Node** nodes, int nb ) { _nodes.assign( nodes, nodes + nb ); } void SetNext( _volumeDef* vd ) { if ( _next ) { _next->SetNext( vd ); } else { _next = vd; }} + + bool IsEmpty() const { return (( _nodes.empty() ) && + ( !_next || _next->IsEmpty() )); } + + + struct _linkDef: public std::pair<_ptr,_ptr> // to join polygons in removeExcessSideDivision() + { + _nodeDef _node1;//, _node2; + mutable /*const */_linkDef *_prev, *_next; + size_t _loopIndex; + + _linkDef():_prev(0), _next(0) {} + + void init( const _nodeDef& n1, const _nodeDef& n2, size_t iLoop ) + { + _node1 = n1; //_node2 = n2; + _loopIndex = iLoop; + first = n1.Ptr(); + second = n2.Ptr(); + if ( first > second ) std::swap( first, second ); + } + void setNext( _linkDef* next ) + { + _next = next; + next->_prev = this; + } + }; }; // topology of a hexahedron - int _nodeShift[8]; _Node _hexNodes [8]; _Link _hexLinks [12]; _Face _hexQuads [6]; @@ -837,7 +876,7 @@ namespace // additional nodes created at intersection points vector< _Node > _intNodes; - // nodes inside the hexahedron (at VERTEXes) + // nodes inside the hexahedron (at VERTEXes) refer to _intNodes vector< _Node* > _vIntNodes; // computed volume elements @@ -858,7 +897,7 @@ namespace Hexahedron(Grid* grid); int MakeElements(SMESH_MesherHelper& helper, const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap); - void ComputeElements( const Solid* solid = 0, int solidIndex = -1 ); + void computeElements( const Solid* solid = 0, int solidIndex = -1 ); private: Hexahedron(const Hexahedron& other, size_t i, size_t j, size_t k, int cellID ); @@ -893,6 +932,7 @@ namespace const map< TGeomID, vector< TGeomID > >& edge2faceIDsMap ); void getVolumes( vector< const SMDS_MeshElement* > & volumes ); void getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryVolumes ); + void removeExcessSideDivision(const vector< Hexahedron* >& allHexa); TGeomID getAnyFace() const; void cutByExtendedInternal( std::vector< Hexahedron* >& hexes, const TColStd_MapOfInteger& intEdgeIDs ); @@ -927,7 +967,7 @@ namespace TID2Nb::iterator id2nb = id2nbMap.insert( s0 ).first; id2nb->second++; } - }; + }; // class Hexahedron #ifdef WITH_TBB // -------------------------------------------------------------------------- @@ -942,7 +982,7 @@ namespace { for ( size_t i = r.begin(); i != r.end(); ++i ) if ( Hexahedron* hex = _hexVec[ i ] ) - hex->ComputeElements(); + hex->computeElements(); } }; // -------------------------------------------------------------------------- @@ -2089,14 +2129,14 @@ namespace size_t i101 = i100 + dz; size_t i011 = i010 + dz; size_t i111 = i110 + dz; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V000 )] = i000; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V100 )] = i100; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V010 )] = i010; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V110 )] = i110; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V001 )] = i001; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V101 )] = i101; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V011 )] = i011; - _nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V111 )] = i111; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V000 )] = i000; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V100 )] = i100; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V010 )] = i010; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V110 )] = i110; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V001 )] = i001; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V101 )] = i101; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V011 )] = i011; + grid->_nodeShift[ SMESH_Block::ShapeIndex( SMESH_Block::ID_V111 )] = i111; vector< int > idVec; // set nodes to links @@ -2112,8 +2152,10 @@ namespace int interlace[4] = { 0, 3, 1, 2 }; // to walk by links around a face: { u0, 1v, u1, 0v } for ( int faceID = SMESH_Block::ID_Fxy0; faceID <= SMESH_Block::ID_F1yz; ++faceID ) { - SMESH_Block::GetFaceEdgesIDs( faceID, idVec ); _Face& quad = _hexQuads[ SMESH_Block::ShapeIndex( faceID )]; + quad._name = (SMESH_Block::TShapeID) faceID; + + SMESH_Block::GetFaceEdgesIDs( faceID, idVec ); bool revFace = ( faceID == SMESH_Block::ID_Fxy0 || faceID == SMESH_Block::ID_Fx1z || faceID == SMESH_Block::ID_F0yz ); @@ -2141,9 +2183,6 @@ namespace _polygons.reserve(100); // to avoid reallocation; // copy topology - for ( int i = 0; i < 8; ++i ) - _nodeShift[i] = other._nodeShift[i]; - for ( int i = 0; i < 12; ++i ) { const _Link& srcLink = other._hexLinks[ i ]; @@ -2156,6 +2195,7 @@ namespace { const _Face& srcQuad = other._hexQuads[ i ]; _Face& tgtQuad = this->_hexQuads[ i ]; + tgtQuad._name = srcQuad._name; tgtQuad._links.resize(4); for ( int j = 0; j < 4; ++j ) { @@ -2188,8 +2228,8 @@ namespace _origNodeInd = _grid->NodeIndex( _i,_j,_k ); for ( int iN = 0; iN < 8; ++iN ) { - _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ]; - _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ]; + _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _grid->_nodeShift[iN] ]; + _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _grid->_nodeShift[iN] ]; if ( _hexNodes[iN]._intPoint ) // intersection with a FACE { @@ -2348,8 +2388,8 @@ namespace { _hexNodes[iN]._isInternalFlags = 0; - _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ]; - _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ]; + _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _grid->_nodeShift[iN] ]; + _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _grid->_nodeShift[iN] ]; if ( _hexNodes[iN]._node && !solid->Contains( _hexNodes[iN]._node->GetShapeID() )) _hexNodes[iN]._node = 0; @@ -2569,7 +2609,7 @@ namespace /*! * \brief Compute mesh volumes resulted from intersection of the Hexahedron */ - void Hexahedron::ComputeElements( const Solid* solid, int solidIndex ) + void Hexahedron::computeElements( const Solid* solid, int solidIndex ) { if ( !solid ) { @@ -2583,7 +2623,7 @@ namespace for ( size_t i = 0; i < nbSolids; ++i ) { solid = _grid->GetSolid( solidIDs[i] ); - ComputeElements( solid, i ); + computeElements( solid, i ); if ( !_volumeDefs._nodes.empty() && i < nbSolids - 1 ) _volumeDefs.SetNext( new _volumeDef( _volumeDefs )); } @@ -2648,6 +2688,7 @@ namespace _polygons.resize( _polygons.size() + 1 ); _Face* polygon = &_polygons.back(); polygon->_polyLinks.reserve( 20 ); + polygon->_name = quad._name; splits.clear(); for ( int iE = 0; iE < 4; ++iE ) // loop on 4 sides of a quadrangle @@ -2682,6 +2723,7 @@ namespace _polygons.resize( _polygons.size() + 1 ); polygon = &_polygons.back(); polygon->_polyLinks.reserve( 20 ); + polygon->_name = quad._name; } polygon->_links.push_back( splits[ iS ] ); splits[ iS++ ]._link = 0; @@ -3148,6 +3190,40 @@ namespace if ( _hasTooSmall ) return false; // too small volume + + // Try to find out names of no-name polygons (issue # 19887) + if ( _grid->IsToRemoveExcessEntities() && _polygons.back()._name == SMESH_Block::ID_NONE ) + { + gp_XYZ uvwCenter = + 0.5 * ( _grid->_coords[0][_i] + _grid->_coords[0][_i+1] ) * _grid->_axes[0] + + 0.5 * ( _grid->_coords[1][_j] + _grid->_coords[1][_j+1] ) * _grid->_axes[1] + + 0.5 * ( _grid->_coords[2][_k] + _grid->_coords[2][_k+1] ) * _grid->_axes[2]; + for ( size_t i = _polygons.size() - 1; _polygons[i]._name == SMESH_Block::ID_NONE; --i ) + { + _Face& face = _polygons[ i ]; + Bnd_Box bb; + gp_Pnt uvw; + for ( size_t iL = 0; iL < face._links.size(); ++iL ) + { + _Node* n = face._links[ iL ].FirstNode(); + gp_XYZ p = SMESH_NodeXYZ( n->Node() ); + _grid->ComputeUVW( p, uvw.ChangeCoord().ChangeData() ); + bb.Add( uvw ); + } + gp_Pnt pMin = bb.CornerMin(); + if ( bb.IsXThin( _grid->_tol )) + face._name = pMin.X() < uvwCenter.X() ? SMESH_Block::ID_F0yz : SMESH_Block::ID_F1yz; + else if ( bb.IsYThin( _grid->_tol )) + face._name = pMin.Y() < uvwCenter.Y() ? SMESH_Block::ID_Fx0z : SMESH_Block::ID_Fx1z; + else if ( bb.IsZThin( _grid->_tol )) + face._name = pMin.Z() < uvwCenter.Z() ? SMESH_Block::ID_Fxy0 : SMESH_Block::ID_Fxy1; + } + } + + _volumeDefs._nodes.clear(); + _volumeDefs._quantities.clear(); + _volumeDefs._names.clear(); + // create a classic cell if possible int nbPolygons = 0; @@ -3168,14 +3244,12 @@ namespace else if ( nbNodes == 5 && nbPolygons == 5 ) isClassicElem = addPyra (); if ( !isClassicElem ) { - _volumeDefs._nodes.clear(); - _volumeDefs._quantities.clear(); - for ( size_t iF = 0; iF < _polygons.size(); ++iF ) { const size_t nbLinks = _polygons[ iF ]._links.size(); if ( nbLinks == 0 ) continue; _volumeDefs._quantities.push_back( nbLinks ); + _volumeDefs._names.push_back( _polygons[ iF ]._name ); for ( size_t iL = 0; iL < nbLinks; ++iL ) _volumeDefs._nodes.push_back( _polygons[ iF ]._links[ iL ].FirstNode() ); } @@ -3294,22 +3368,24 @@ namespace } } - // add elements resulted from hexadron intersection + // compute definitions of volumes resulted from hexadron intersection #ifdef WITH_TBB tbb::parallel_for ( tbb::blocked_range( 0, intHexa.size() ), ParallelHexahedron( intHexa ), - tbb::simple_partitioner()); // ComputeElements() is called here - for ( size_t i = 0; i < intHexa.size(); ++i ) - if ( Hexahedron * hex = intHexa[ i ] ) - nbAdded += hex->addVolumes( helper ); + tbb::simple_partitioner()); // computeElements() is called here #else + for ( size_t i = 0; i < intHexa.size(); ++i ) + if ( Hexahedron * hex = intHexa[ i ] ) + hex->computeElements(); +#endif + + // add volumes for ( size_t i = 0; i < intHexa.size(); ++i ) if ( Hexahedron * hex = intHexa[ i ] ) { - hex->ComputeElements(); + hex->removeExcessSideDivision( allHexa ); nbAdded += hex->addVolumes( helper ); } -#endif // fill boundaryVolumes with volumes neighboring too small skipped volumes if ( _grid->_toCreateFaces ) @@ -3604,7 +3680,8 @@ namespace int i = ! ( u < _grid->_tol ); // [0,1] int iN = link._nodes[ i ] - hex->_hexNodes; // [0-7] - const F_IntersectPoint * & ip = _grid->_gridIntP[ hex->_origNodeInd + _nodeShift[iN] ]; + const F_IntersectPoint * & ip = _grid->_gridIntP[ hex->_origNodeInd + + _grid->_nodeShift[iN] ]; if ( !ip ) { ip = _grid->_extIntPool.getNew(); @@ -3698,8 +3775,8 @@ namespace for ( size_t iN = 0; iN < 8; ++iN ) // check corners { - _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _nodeShift[iN] ]; - _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _nodeShift[iN] ]; + _hexNodes[iN]._node = _grid->_nodes [ _origNodeInd + _grid->_nodeShift[iN] ]; + _hexNodes[iN]._intPoint = _grid->_gridIntP[ _origNodeInd + _grid->_nodeShift[iN] ]; if ( _hexNodes[iN]._intPoint ) for ( size_t iF = 0; iF < _hexNodes[iN]._intPoint->_faceIDs.size(); ++iF ) { @@ -5005,8 +5082,9 @@ namespace if ( !faceID ) break; if ( _grid->IsInternal( faceID ) || - _grid->IsShared( faceID ) /*|| - _grid->IsBoundaryFace( faceID )*/) + _grid->IsShared( faceID ) //|| + //_grid->IsBoundaryFace( faceID ) -- commented for #19887 + ) break; // create only if a new face will be used by other 3D algo } @@ -5035,6 +5113,159 @@ namespace } } + //================================================================================ + /*! + * \brief Remove edges and nodes dividing a hexa side in the case if an adjacent + * volume also sharing the dividing edge is missing due to its small side. + * Issue #19887. + */ + //================================================================================ + + void Hexahedron::removeExcessSideDivision(const vector< Hexahedron* >& allHexa) + { + if ( !_grid->IsToRemoveExcessEntities() || _volumeDefs.IsEmpty() ) + return; + if (( _volumeDefs._quantities.empty() ) && + ( !_volumeDefs._next || _volumeDefs._next->_quantities.empty() )) + return; // not a polyhedron + + // look for a divided side adjacent to a small hexahedron + + int di[6] = { 0, 0, 0, 0,-1, 1 }; + int dj[6] = { 0, 0,-1, 1, 0, 0 }; + int dk[6] = {-1, 1, 0, 0, 0, 0 }; + + for ( int iF = 0; iF < 6; ++iF ) // loop on 6 sides of a hexahedron + { + size_t neighborIndex = _grid->CellIndex( _i + di[iF], + _j + dj[iF], + _k + dk[iF] ); + if ( neighborIndex >= allHexa.size() || + !allHexa[ neighborIndex ] || + !allHexa[ neighborIndex ]->_hasTooSmall ) + continue; + + // check if a side is divided into several polygons + for ( _volumeDef* volDef = &_volumeDefs; volDef; volDef = volDef->_next ) + { + int nbPolygons = 0, nbNodes = 0; + for ( size_t i = 0; i < volDef->_names.size(); ++i ) + if ( volDef->_names[ i ] == _hexQuads[ iF ]._name ) + { + ++nbPolygons; + nbNodes += volDef->_quantities[ i ]; + } + if ( nbPolygons < 2 ) + continue; + + // construct loops from polygons + typedef _volumeDef::_linkDef TLinkDef; + std::vector< TLinkDef* > loops; + std::vector< TLinkDef > links( nbNodes ); + for ( size_t i = 0, iN = 0, iLoop = 0; iLoop < volDef->_quantities.size(); ++iLoop ) + { + size_t nbLinks = volDef->_quantities[ iLoop ]; + if ( volDef->_names[ iLoop ] != _hexQuads[ iF ]._name ) + { + iN += nbLinks; + continue; + } + loops.push_back( & links[i] ); + for ( size_t n = 0; n < nbLinks-1; ++n, ++i, ++iN ) + { + links[i].init( volDef->_nodes[iN], volDef->_nodes[iN+1], iLoop ); + links[i].setNext( &links[i+1] ); + } + links[i].init( volDef->_nodes[iN], volDef->_nodes[iN-nbLinks+1], iLoop ); + links[i].setNext( &links[i-nbLinks+1] ); + ++i; ++iN; + } + + // look for equal links in different loops and join such loops + bool loopsJoined = false; + std::set< TLinkDef > linkSet; + for ( size_t iLoop = 0; iLoop < loops.size(); ++iLoop ) + { + bool joined = false; + TLinkDef* beg = 0; + for ( TLinkDef* l = loops[ iLoop ]; l != beg; l = l->_next ) // walk around the iLoop + { + std::pair< std::set< TLinkDef >::iterator, bool > it2new = linkSet.insert( *l ); + if ( !it2new.second ) // equal found, join loops + { + const TLinkDef* equal = &(*it2new.first); + if ( equal->_loopIndex == l->_loopIndex ) + continue; // error? + + // exclude l and equal and join two loops + if ( l->_prev != equal ) + l->_prev->setNext( equal->_next ); + if ( equal->_prev != l ) + equal->_prev->setNext( l->_next ); + + joined = true; + if ( volDef->_quantities[ l->_loopIndex ] > 0 ) + volDef->_quantities[ l->_loopIndex ] *= -1; + if ( volDef->_quantities[ equal->_loopIndex ] > 0 ) + volDef->_quantities[ equal->_loopIndex ] *= -1; + + if ( loops[ iLoop ] == l ) + loops[ iLoop ] = l->_prev->_next; + } + beg = loops[ iLoop ]; + } + if ( joined ) + { + loops[ iLoop ] = 0; + loopsJoined = true; + } + } + // update volDef + if ( loopsJoined ) + { + // set unchanged polygons + std::vector< int > newQuantities; newQuantities.reserve( volDef->_quantities.size() ); + std::vector< _volumeDef::_nodeDef > newNodes; newNodes.reserve( volDef->_nodes.size() ); + vector< SMESH_Block::TShapeID > newNames; newNames.reserve( volDef->_names.size() ); + for ( size_t i = 0, iLoop = 0; iLoop < volDef->_quantities.size(); ++iLoop ) + { + if ( volDef->_quantities[ iLoop ] < 0 ) + { + i -= volDef->_quantities[ iLoop ]; + continue; + } + newQuantities.push_back( volDef->_quantities[ iLoop ]); + newNodes.insert( newNodes.end(), + volDef->_nodes.begin() + i, + volDef->_nodes.begin() + i + newQuantities.back() ); + newNames.push_back( volDef->_names[ iLoop ]); + i += volDef->_quantities[ iLoop ]; + } + + // set joined loops + for ( size_t iLoop = 0; iLoop < loops.size(); ++iLoop ) + { + if ( !loops[ iLoop ] ) + continue; + newQuantities.push_back( 0 ); + TLinkDef* beg = 0; + for ( TLinkDef* l = loops[ iLoop ]; l != beg; l = l->_next, ++newQuantities.back() ) + { + newNodes.push_back( l->_node1 ); + beg = loops[ iLoop ]; + } + newNames.push_back( _hexQuads[ iF ]._name ); + } + volDef->_quantities.swap( newQuantities ); + volDef->_nodes.swap( newNodes ); + volDef->_names.swap( newNames ); + } + } // loop on volDef's + } // loop on hex sides + + return; + } // removeExcessSideDivision() + //================================================================================ /*! * \brief Set to _hexLinks a next portion of splits located on one side of INTERNAL FACEs From 951dd4234ec84d147b1756bc04b6464c5332091c Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 14 Aug 2020 15:58:50 +0300 Subject: [PATCH 21/25] #19887 [CEA] Body fitting missing some faces and generates not-wanted splitted elements Remove excess nodes --- src/StdMeshers/StdMeshers_Cartesian_3D.cxx | 248 ++++++++++++++++++--- 1 file changed, 222 insertions(+), 26 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index b26d2419c..7e444be89 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -446,12 +446,14 @@ namespace */ struct CellsAroundLink { + int _iDir; int _dInd[4][3]; size_t _nbCells[3]; int _i,_j,_k; Grid* _grid; CellsAroundLink( Grid* grid, int iDir ): + _iDir( iDir ), _dInd{ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }, _nbCells{ grid->_coords[0].size() - 1, grid->_coords[1].size() - 1, @@ -470,7 +472,7 @@ namespace _j = j - _dInd[iL][1]; _k = k - _dInd[iL][2]; } - bool GetCell( int iL, int& i, int& j, int& k, int& cellIndex ) + bool GetCell( int iL, int& i, int& j, int& k, int& cellIndex, int& linkIndex ) { i = _i + _dInd[iL][0]; j = _j + _dInd[iL][1]; @@ -480,6 +482,7 @@ namespace k < 0 || k >= (int)_nbCells[2] ) return false; cellIndex = _grid->CellIndex( i,j,k ); + linkIndex = iL + _iDir * 4; return true; } }; @@ -811,6 +814,7 @@ namespace const E_IntersectPoint* EdgeIntPnt() const { return static_cast< const E_IntersectPoint* >( _intPoint ); } _ptr Ptr() const { return Node() ? (_ptr) Node() : (_ptr) EdgeIntPnt(); } + bool operator==(const _nodeDef& other ) const { return Ptr() == other.Ptr(); } }; vector< _nodeDef > _nodes; @@ -828,6 +832,10 @@ namespace { _nodes.swap( other._nodes ); _quantities.swap( other._quantities ); other._volume = 0; _names.swap( other._names ); } + size_t size() const { return 1 + ( _next ? _next->size() : 0 ); } + _volumeDef* at(int index) + { return index == 0 ? this : ( _next ? _next->at(index-1) : _next ); } + void Set( _Node** nodes, int nb ) { _nodes.assign( nodes, nodes + nb ); } @@ -836,6 +844,8 @@ namespace bool IsEmpty() const { return (( _nodes.empty() ) && ( !_next || _next->IsEmpty() )); } + bool IsPolyhedron() const { return ( !_quantities.empty() || + ( _next && !_next->_quantities.empty() )); } struct _linkDef: public std::pair<_ptr,_ptr> // to join polygons in removeExcessSideDivision() @@ -933,6 +943,7 @@ namespace void getVolumes( vector< const SMDS_MeshElement* > & volumes ); void getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryVolumes ); void removeExcessSideDivision(const vector< Hexahedron* >& allHexa); + void removeExcessNodes(vector< Hexahedron* >& allHexa); TGeomID getAnyFace() const; void cutByExtendedInternal( std::vector< Hexahedron* >& hexes, const TColStd_MapOfInteger& intEdgeIDs ); @@ -3273,7 +3284,7 @@ namespace int nbIntHex = 0; // set intersection nodes from GridLine's to links of allHexa - int i,j,k, cellIndex; + int i,j,k, cellIndex, iLink; for ( int iDir = 0; iDir < 3; ++iDir ) { // loop on GridLine's parallel to iDir @@ -3290,7 +3301,7 @@ namespace fourCells.Init( lineInd.I(), lineInd.J(), lineInd.K() ); for ( int iL = 0; iL < 4; ++iL ) // loop on 4 cells sharing a link { - if ( !fourCells.GetCell( iL, i,j,k, cellIndex )) + if ( !fourCells.GetCell( iL, i,j,k, cellIndex, iLink )) continue; Hexahedron *& hex = allHexa[ cellIndex ]; if ( !hex) @@ -3298,7 +3309,6 @@ namespace hex = new Hexahedron( *this, i, j, k, cellIndex ); ++nbIntHex; } - const int iLink = iL + iDir * 4; hex->_hexLinks[iLink]._fIntPoints.push_back( &(*ip) ); hex->_nbFaceIntNodes += bool( ip->_node ); } @@ -3379,13 +3389,22 @@ namespace hex->computeElements(); #endif + // simplify polyhedrons + if ( _grid->IsToRemoveExcessEntities() ) + { + for ( size_t i = 0; i < intHexa.size(); ++i ) + if ( Hexahedron * hex = intHexa[ i ] ) + hex->removeExcessSideDivision( allHexa ); + + for ( size_t i = 0; i < intHexa.size(); ++i ) + if ( Hexahedron * hex = intHexa[ i ] ) + hex->removeExcessNodes( allHexa ); + } + // add volumes for ( size_t i = 0; i < intHexa.size(); ++i ) if ( Hexahedron * hex = intHexa[ i ] ) - { - hex->removeExcessSideDivision( allHexa ); nbAdded += hex->addVolumes( helper ); - } // fill boundaryVolumes with volumes neighboring too small skipped volumes if ( _grid->_toCreateFaces ) @@ -3709,13 +3728,12 @@ namespace int i,j,k, cellIndex; for ( int iC = 0; iC < 4; ++iC ) // loop on 4 cells sharing the link { - if ( !fourCells.GetCell( iC, i,j,k, cellIndex )) + if ( !fourCells.GetCell( iC, i,j,k, cellIndex, iLink )) continue; Hexahedron * h = hexes[ cellIndex ]; if ( !h ) h = hexes[ cellIndex ] = new Hexahedron( *this, i, j, k, cellIndex ); - const int iL = iC + iDir * 4; - h->_hexLinks[iL]._fIntPoints.push_back( ip ); + h->_hexLinks[iLink]._fIntPoints.push_back( ip ); h->_nbFaceIntNodes++; //isCut = true; } @@ -5123,10 +5141,7 @@ namespace void Hexahedron::removeExcessSideDivision(const vector< Hexahedron* >& allHexa) { - if ( !_grid->IsToRemoveExcessEntities() || _volumeDefs.IsEmpty() ) - return; - if (( _volumeDefs._quantities.empty() ) && - ( !_volumeDefs._next || _volumeDefs._next->_quantities.empty() )) + if ( ! _volumeDefs.IsPolyhedron() ) return; // not a polyhedron // look for a divided side adjacent to a small hexahedron @@ -5186,7 +5201,6 @@ namespace std::set< TLinkDef > linkSet; for ( size_t iLoop = 0; iLoop < loops.size(); ++iLoop ) { - bool joined = false; TLinkDef* beg = 0; for ( TLinkDef* l = loops[ iLoop ]; l != beg; l = l->_next ) // walk around the iLoop { @@ -5197,13 +5211,18 @@ namespace if ( equal->_loopIndex == l->_loopIndex ) continue; // error? + loopsJoined = true; + + for ( size_t i = iLoop - 1; i < loops.size(); --i ) + if ( loops[ i ] && loops[ i ]->_loopIndex == equal->_loopIndex ) + loops[ i ] = 0; + // exclude l and equal and join two loops if ( l->_prev != equal ) l->_prev->setNext( equal->_next ); if ( equal->_prev != l ) equal->_prev->setNext( l->_next ); - joined = true; if ( volDef->_quantities[ l->_loopIndex ] > 0 ) volDef->_quantities[ l->_loopIndex ] *= -1; if ( volDef->_quantities[ equal->_loopIndex ] > 0 ) @@ -5214,19 +5233,17 @@ namespace } beg = loops[ iLoop ]; } - if ( joined ) - { - loops[ iLoop ] = 0; - loopsJoined = true; - } } // update volDef if ( loopsJoined ) { // set unchanged polygons - std::vector< int > newQuantities; newQuantities.reserve( volDef->_quantities.size() ); - std::vector< _volumeDef::_nodeDef > newNodes; newNodes.reserve( volDef->_nodes.size() ); - vector< SMESH_Block::TShapeID > newNames; newNames.reserve( volDef->_names.size() ); + std::vector< int > newQuantities; + std::vector< _volumeDef::_nodeDef > newNodes; + vector< SMESH_Block::TShapeID > newNames; + newQuantities.reserve( volDef->_quantities.size() ); + newNodes.reserve ( volDef->_nodes.size() ); + newNames.reserve ( volDef->_names.size() ); for ( size_t i = 0, iLoop = 0; iLoop < volDef->_quantities.size(); ++iLoop ) { if ( volDef->_quantities[ iLoop ] < 0 ) @@ -5238,7 +5255,7 @@ namespace newNodes.insert( newNodes.end(), volDef->_nodes.begin() + i, volDef->_nodes.begin() + i + newQuantities.back() ); - newNames.push_back( volDef->_names[ iLoop ]); + newNames.push_back( volDef->_names[ iLoop ]); i += volDef->_quantities[ iLoop ]; } @@ -5254,7 +5271,7 @@ namespace newNodes.push_back( l->_node1 ); beg = loops[ iLoop ]; } - newNames.push_back( _hexQuads[ iF ]._name ); + newNames.push_back( _hexQuads[ iF ]._name ); } volDef->_quantities.swap( newQuantities ); volDef->_nodes.swap( newNodes ); @@ -5266,6 +5283,185 @@ namespace return; } // removeExcessSideDivision() + + //================================================================================ + /*! + * \brief Remove nodes splitting Cartesian cell edges in the case if a node + * is used in every cells only by two polygons sharing the edge + * Issue #19887. + */ + //================================================================================ + + void Hexahedron::removeExcessNodes(vector< Hexahedron* >& allHexa) + { + if ( ! _volumeDefs.IsPolyhedron() ) + return; // not a polyhedron + + typedef vector< _volumeDef::_nodeDef >::iterator TNodeIt; + vector< int > nodesInPoly[ 4 ]; // node index in _volumeDefs._nodes + vector< int > volDefInd [ 4 ]; // index of a _volumeDefs + Hexahedron* hexa [ 4 ]; + int i,j,k, cellIndex, iLink = 0, iCellLink; + for ( int iDir = 0; iDir < 3; ++iDir ) + { + CellsAroundLink fourCells( _grid, iDir ); + for ( int iL = 0; iL < 4; ++iL, ++iLink ) // 4 links in a direction + { + _Link& link = _hexLinks[ iLink ]; + fourCells.Init( _i, _j, _k, iLink ); + + for ( size_t iP = 0; iP < link._fIntPoints.size(); ++iP ) // loop on nodes on the link + { + bool nodeRemoved = true; + _volumeDef::_nodeDef node; node._intPoint = link._fIntPoints[iP]; + + for ( size_t i = 0, nb = _volumeDefs.size(); i < nb && nodeRemoved; ++i ) + if ( _volumeDef* vol = _volumeDefs.at( i )) + nodeRemoved = + ( std::find( vol->_nodes.begin(), vol->_nodes.end(), node ) == vol->_nodes.end() ); + if ( nodeRemoved ) + continue; // node already removed + + // check if a node encounters zero or two times in 4 cells sharing iLink + // if so, the node can be removed from the cells + bool nodeIsOnEdge = true; + int nbPolyhedraWithNode = 0; + for ( int iC = 0; iC < 4; ++iC ) // loop on 4 cells sharing a link + { + nodesInPoly[ iC ].clear(); + volDefInd [ iC ].clear(); + hexa [ iC ] = 0; + if ( !fourCells.GetCell( iC, i,j,k, cellIndex, iCellLink )) + continue; + hexa[ iC ] = allHexa[ cellIndex ]; + if ( !hexa[ iC ]) + continue; + for ( size_t i = 0, nb = hexa[ iC ]->_volumeDefs.size(); i < nb; ++i ) + if ( _volumeDef* vol = hexa[ iC ]->_volumeDefs.at( i )) + { + for ( TNodeIt nIt = vol->_nodes.begin(); nIt != vol->_nodes.end(); ++nIt ) + { + nIt = std::find( nIt, vol->_nodes.end(), node ); + if ( nIt != vol->_nodes.end() ) + { + nodesInPoly[ iC ].push_back( std::distance( vol->_nodes.begin(), nIt )); + volDefInd [ iC ].push_back( i ); + } + else + break; + } + nbPolyhedraWithNode += ( !nodesInPoly[ iC ].empty() ); + } + if ( nodesInPoly[ iC ].size() != 0 && + nodesInPoly[ iC ].size() != 2 ) + { + nodeIsOnEdge = false; + break; + } + } // loop on 4 cells + + // remove nodes from polyhedra + if ( nbPolyhedraWithNode > 0 && nodeIsOnEdge ) + { + for ( int iC = 0; iC < 4; ++iC ) // loop on 4 cells sharing the link + { + if ( nodesInPoly[ iC ].empty() ) + continue; + for ( int i = volDefInd[ iC ].size() - 1; i >= 0; --i ) + { + _volumeDef* vol = hexa[ iC ]->_volumeDefs.at( volDefInd[ iC ][ i ]); + int nIndex = nodesInPoly[ iC ][ i ]; + // decrement _quantities + for ( size_t iQ = 0; iQ < vol->_quantities.size(); ++iQ ) + if ( nIndex < vol->_quantities[ iQ ]) + { + vol->_quantities[ iQ ]--; + break; + } + else + { + nIndex -= vol->_quantities[ iQ ]; + } + vol->_nodes.erase( vol->_nodes.begin() + nodesInPoly[ iC ][ i ]); + + if ( i == 0 && + vol->_nodes.size() == 6 * 4 && + vol->_quantities.size() == 6 ) // polyhedron becomes hexahedron? + { + bool allQuads = true; + for ( size_t iQ = 0; iQ < vol->_quantities.size() && allQuads; ++iQ ) + allQuads = ( vol->_quantities[ iQ ] == 4 ); + if ( allQuads ) + { + // set side nodes as this: bottom, top, top, ... + int iTop, iBot; // side indices + for ( int iS = 0; iS < 6; ++iS ) + { + if ( vol->_names[ iS ] == SMESH_Block::ID_Fxy0 ) + iBot = iS; + if ( vol->_names[ iS ] == SMESH_Block::ID_Fxy1 ) + iTop = iS; + } + if ( iBot != 0 ) + { + if ( iTop == 0 ) + { + std::copy( vol->_nodes.begin(), + vol->_nodes.begin() + 4, + vol->_nodes.begin() + 4 ); + iTop = 1; + } + std::copy( vol->_nodes.begin() + 4 * iBot, + vol->_nodes.begin() + 4 * ( iBot + 1), + vol->_nodes.begin() ); + } + if ( iTop != 1 ) + std::copy( vol->_nodes.begin() + 4 * iTop, + vol->_nodes.begin() + 4 * ( iTop + 1), + vol->_nodes.begin() + 4 ); + + std::copy( vol->_nodes.begin() + 4, + vol->_nodes.begin() + 8, + vol->_nodes.begin() + 8 ); + // set up top facet nodes by comparing their uvw with bottom nodes + E_IntersectPoint ip[8]; + for ( int iN = 0; iN < 8; ++iN ) + { + SMESH_NodeXYZ p = vol->_nodes[ iN ].Node(); + _grid->ComputeUVW( p, ip[ iN ]._uvw ); + } + const double tol2 = _grid->_tol * _grid->_tol; + for ( int iN = 0; iN < 4; ++iN ) + { + gp_Pnt2d pBot( ip[ iN ]._uvw[0], ip[ iN ]._uvw[1] ); + for ( int iT = 4; iT < 8; ++iT ) + { + gp_Pnt2d pTop( ip[ iT ]._uvw[0], ip[ iT ]._uvw[1] ); + if ( pBot.SquareDistance( pTop ) < tol2 ) + { + // vol->_nodes[ iN + 4 ]._node = ip[ iT ]._node; + // vol->_nodes[ iN + 4 ]._intPoint = 0; + vol->_nodes[ iN + 4 ] = vol->_nodes[ iT + 4 ]; + break; + } + } + } + vol->_nodes.resize( 8 ); + vol->_quantities.clear(); + //vol->_names.clear(); + } + } + } // loop on _volumeDefs + } // loop on 4 cell abound a link + } // if ( nodeIsOnEdge ) + } // loop on intersection points of a link + } // loop on 4 links of a direction + } // loop on 3 directions + + return; + + } // removeExcessNodes() + //================================================================================ /*! * \brief Set to _hexLinks a next portion of splits located on one side of INTERNAL FACEs From 66de7ed40f01db7bc27e197078720481fcdc5210 Mon Sep 17 00:00:00 2001 From: eap Date: Wed, 19 Aug 2020 11:56:22 +0300 Subject: [PATCH 22/25] #19913 [CEA] Crash when compute mesh with body fitting and shared faces 1) fix the crash 2) fix missing volumes when taking shared faces into account overlapping volumes remain to fix --- src/StdMeshers/StdMeshers_Cartesian_3D.cxx | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index 7e444be89..e0c8ec025 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -2388,6 +2388,7 @@ namespace { _i = i; _j = j; _k = k; + bool isCompute = solid; if ( !solid ) solid = _grid->GetSolid(); @@ -2417,6 +2418,9 @@ namespace _intNodes.clear(); _vIntNodes.clear(); + if ( !isCompute ) + return; + if ( _nbFaceIntNodes + _eIntPoints.size() > 0 && _nbFaceIntNodes + _eIntPoints.size() + _nbCornerNodes > 3) { @@ -2596,7 +2600,8 @@ namespace } // loop on _eIntPoints } - else if ( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) // _nbFaceIntNodes == 0 + else if (( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) || // _nbFaceIntNodes == 0 + ( !_grid->_geometry.IsOneSolid() )) { _Link split; // create sub-links (_splits) of whole links @@ -3331,7 +3336,9 @@ namespace if ( hex ) // split hexahedron { intHexa.push_back( hex ); - if ( hex->_nbFaceIntNodes > 0 || hex->_eIntPoints.size() > 0 ) + if ( hex->_nbFaceIntNodes > 0 || + hex->_eIntPoints.size() > 0 || + hex->getSolids( solidIDs ) > 1 ) continue; // treat intersected hex later in parallel this->init( hex->_i, hex->_j, hex->_k ); } @@ -4464,10 +4471,13 @@ namespace { curIntPnt._paramOnLine = coords[ ijk[ iDir ]] - coords[0] + _grid->_tol; const GridLine& line = _grid->_lines[ iDir ][ lineIndex[ iL ]]; - multiset< F_IntersectPoint >::const_iterator ip = - line._intPoints.upper_bound( curIntPnt ); - --ip; - firstIntPnt = &(*ip); + if ( !line._intPoints.empty() ) + { + multiset< F_IntersectPoint >::const_iterator ip = + line._intPoints.upper_bound( curIntPnt ); + --ip; + firstIntPnt = &(*ip); + } } else if ( !link._fIntPoints.empty() ) { From 3d87656309c14522ac02fa8ba23270b6d762a795 Mon Sep 17 00:00:00 2001 From: eap Date: Thu, 20 Aug 2020 20:05:57 +0300 Subject: [PATCH 23/25] #19913 [CEA] Crash when compute mesh with body fitting and shared faces fix elements on top of cylinder --- src/StdMeshers/StdMeshers_Cartesian_3D.cxx | 76 ++++++++++++++++++++-- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx index e0c8ec025..6f284e4ba 100644 --- a/src/StdMeshers/StdMeshers_Cartesian_3D.cxx +++ b/src/StdMeshers/StdMeshers_Cartesian_3D.cxx @@ -731,11 +731,11 @@ namespace { struct _Split // data of a link split { - int _linkID; // hex link ID + int _linkID; // hex link ID _Node* _nodes[2]; int _iCheckIteration; // iteration where split is tried as Hexahedron split _Link* _checkedSplit; // split set to hex links - bool _isUsed; // used in a volume + bool _isUsed; // used in a volume _Split( _Link & split, int iLink ): _linkID( iLink ), _nodes{ split._nodes[0], split._nodes[1] }, @@ -944,6 +944,7 @@ namespace void getBoundaryElems( vector< const SMDS_MeshElement* > & boundaryVolumes ); void removeExcessSideDivision(const vector< Hexahedron* >& allHexa); void removeExcessNodes(vector< Hexahedron* >& allHexa); + void preventVolumesOverlapping(); TGeomID getAnyFace() const; void cutByExtendedInternal( std::vector< Hexahedron* >& hexes, const TColStd_MapOfInteger& intEdgeIDs ); @@ -2688,6 +2689,9 @@ namespace for ( int iN = 0; iN < 8; ++iN ) _hexNodes[iN]._usedInFace = 0; + if ( intFlag & IS_CUT_BY_INTERNAL_FACE && !_grid->_toAddEdges ) // Issue #19913 + preventVolumesOverlapping(); + // Create polygons from quadrangles // -------------------------------- @@ -2695,7 +2699,8 @@ namespace vector<_Node*> chainNodes; _Face* coplanarPolyg; - bool hasEdgeIntersections = !_eIntPoints.empty(); + const bool hasEdgeIntersections = !_eIntPoints.empty(); + const bool toCheckSideDivision = isImplementEdges() || intFlag & IS_CUT_BY_INTERNAL_FACE; for ( int iF = 0; iF < 6; ++iF ) // loop on 6 sides of a hexahedron { @@ -2755,7 +2760,7 @@ namespace n1 = split.FirstNode(); if ( n1 == n2 && n1->_intPoint && - (( n1->_intPoint->_faceIDs.size() > 1 && isImplementEdges() ) || + (( n1->_intPoint->_faceIDs.size() > 1 && toCheckSideDivision ) || ( n1->_isInternalFlags ))) { // n1 is at intersection with EDGE @@ -5472,6 +5477,69 @@ namespace } // removeExcessNodes() + //================================================================================ + /*! + * \brief [Issue #19913] Modify _hexLinks._splits to prevent creating overlapping volumes + */ + //================================================================================ + + void Hexahedron::preventVolumesOverlapping() + { + // Cut off a quadrangle corner if two links sharing the corner + // are shared by same two solids, in this case each of solids gets + // a triangle for it-self. + std::vector< TGeomID > soIDs[4]; + for ( int iF = 0; iF < 6; ++iF ) // loop on 6 sides of a hexahedron + { + _Face& quad = _hexQuads[ iF ] ; + + int iFOpposite = iF + ( iF % 2 ? -1 : 1 ); + _Face& quadOpp = _hexQuads[ iFOpposite ] ; + + int nbSides = 0, nbSidesOpp = 0; + for ( int iE = 0; iE < 4; ++iE ) // loop on 4 sides of a quadrangle + { + nbSides += ( quad._links [ iE ].NbResultLinks() > 0 ); + nbSidesOpp += ( quadOpp._links[ iE ].NbResultLinks() > 0 ); + } + if ( nbSides < 4 || nbSidesOpp != 2 ) + continue; + + for ( int iE = 0; iE < 4; ++iE ) + { + soIDs[ iE ].clear(); + _Node* n = quad._links[ iE ].FirstNode(); + if ( n->_intPoint && n->_intPoint->_faceIDs.size() ) + soIDs[ iE ] = _grid->GetSolidIDs( n->_intPoint->_faceIDs[0] ); + } + if ((( soIDs[0].size() >= 2 ) + + ( soIDs[1].size() >= 2 ) + + ( soIDs[2].size() >= 2 ) + + ( soIDs[3].size() >= 2 ) ) < 3 ) + continue; + + bool done = false; + for ( int i = 0; i < 4; ++i ) + { + int i1 = _grid->_helper->WrapIndex( i + 1, 4 ); + int i2 = _grid->_helper->WrapIndex( i + 2, 4 ); + int i3 = _grid->_helper->WrapIndex( i + 3, 4 ); + if ( soIDs[i1].size() == 2 && soIDs[i ] != soIDs[i1] && + soIDs[i2].size() == 2 && soIDs[i1] == soIDs[i2] && + soIDs[i3].size() == 2 && soIDs[i2] == soIDs[i3] ) + { + quad._links[ i1 ]._link->_splits.clear(); + quad._links[ i2 ]._link->_splits.clear(); + done = true; + break; + } + } + if ( done ) + break; + } + return; + } // preventVolumesOverlapping() + //================================================================================ /*! * \brief Set to _hexLinks a next portion of splits located on one side of INTERNAL FACEs From 338d12a959f4872ad89c95884aa4999e262718ea Mon Sep 17 00:00:00 2001 From: mpv Date: Mon, 24 Aug 2020 16:38:41 +0300 Subject: [PATCH 24/25] #19919 [CEA] Group of Edges reported as empty Clear shapes-cash in GEOMClient also for sub-meshes objects. --- src/SMESH_I/SMESH_Mesh_i.cxx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/SMESH_I/SMESH_Mesh_i.cxx b/src/SMESH_I/SMESH_Mesh_i.cxx index 0f827b054..4c2ca27c3 100644 --- a/src/SMESH_I/SMESH_Mesh_i.cxx +++ b/src/SMESH_I/SMESH_Mesh_i.cxx @@ -2058,12 +2058,12 @@ void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom) TopoDS_Shape S = _impl->GetShapeToMesh(); GEOM_Client* geomClient = _gen_i->GetShapeReader(); TCollection_AsciiString aIOR; - CORBA::String_var ior; if ( geomClient->Find( S, aIOR )) geomClient->RemoveShapeFromBuffer( aIOR ); // clear buffer also for sub-groups - const std::set& groups = _impl->GetMeshDS()->GetGroups(); + SMESHDS_Mesh* meshDS = _impl->GetMeshDS(); + const std::set& groups = meshDS->GetGroups(); std::set::const_iterator g = groups.begin(); for (; g != groups.end(); ++g) if (const SMESHDS_GroupOnGeom* group = dynamic_cast(*g)) @@ -2073,12 +2073,21 @@ void SMESH_Mesh_i::ReplaceShape(GEOM::GEOM_Object_ptr theNewGeom) geomClient->RemoveShapeFromBuffer( aIOR ); } + // clear buffer also for sub-meshes + std::map::const_iterator aSubMeshIter = _mapSubMesh_i.cbegin(); + for(; aSubMeshIter != _mapSubMesh_i.cend(); aSubMeshIter++) { + int aShapeID = aSubMeshIter->first; + const TopoDS_Shape& aSubShape = meshDS->IndexToShape(aShapeID); + TCollection_AsciiString aShapeIOR; + if ( geomClient->Find( aSubShape, aShapeIOR )) + geomClient->RemoveShapeFromBuffer( aShapeIOR ); + } + typedef struct { int shapeID, fromID, toID; // indices of elements of a sub-mesh } TRange; std::vector< TRange > elemRanges, nodeRanges; // elements of sub-meshes std::vector< SMDS_PositionPtr > positions; // node positions - SMESHDS_Mesh* meshDS = _impl->GetMeshDS(); if ( !geomChanged ) { // store positions of elements on geometry From dd1c96d8ede3a65908f8d509820d4aa4215cea5b Mon Sep 17 00:00:00 2001 From: eap Date: Thu, 27 Aug 2020 14:03:34 +0300 Subject: [PATCH 25/25] Fix error of unreachable code --- src/SMESHFiltersSelection/SMESH_NumberFilter.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SMESHFiltersSelection/SMESH_NumberFilter.cxx b/src/SMESHFiltersSelection/SMESH_NumberFilter.cxx index e5d480e35..78eed3a23 100644 --- a/src/SMESHFiltersSelection/SMESH_NumberFilter.cxx +++ b/src/SMESHFiltersSelection/SMESH_NumberFilter.cxx @@ -135,7 +135,7 @@ bool SMESH_NumberFilter::isOk (const SUIT_DataOwner* theDataOwner) const } // Verify number of sub-shapes - if (mySubShapeType == TopAbs_SHAPE); + if (mySubShapeType == TopAbs_SHAPE) return true; TopTools_IndexedMapOfShape aMap;