diff --git a/idl/SMESH_Filter.idl b/idl/SMESH_Filter.idl index b44845316..01cf9f2f8 100644 --- a/idl/SMESH_Filter.idl +++ b/idl/SMESH_Filter.idl @@ -151,6 +151,11 @@ module SMESH void SetGeom( in GEOM::GEOM_Object theGeom ); void SetElementType( in ElementType theType ); + /*! The tolerance is used only if there is no submesh on the shape + */ + void SetTolerance( in double theToler ); + double GetTolerance(); + void SetShapeName( in string theName ); void SetShape( in string theID, in string theName ); string GetShapeName(); @@ -214,6 +219,11 @@ module SMESH void SetGeom( in GEOM::GEOM_Object theGeom ); void SetElementType( in ElementType theType ); + /*! The tolerance is used only if there is no submesh on the shape + */ + void SetTolerance( in double theToler ); + double GetTolerance(); + void SetShapeName( in string theName ); void SetShape( in string theID, in string theName ); string GetShapeName(); diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 2f25357cd..aeb348b05 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -2681,3 +2684,250 @@ bool ElementsOnSurface::isOnSurface( const SMDS_MeshNode* theNode ) return isOn; } + + +/* + ElementsOnShape +*/ + +ElementsOnShape::ElementsOnShape() + : myMesh(0), + myType(SMDSAbs_All), + myToler(Precision::Confusion()), + myAllNodesFlag(false) +{ + myCurShapeType = TopAbs_SHAPE; +} + +ElementsOnShape::~ElementsOnShape() +{ +} + +void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh) +{ + if (myMesh != theMesh) { + myMesh = theMesh; + SetShape(myShape, myType); + } +} + +bool ElementsOnShape::IsSatisfy (long theElementId) +{ + return myIds.Contains(theElementId); +} + +SMDSAbs_ElementType ElementsOnShape::GetType() const +{ + return myType; +} + +void ElementsOnShape::SetTolerance (const double theToler) +{ + if (myToler != theToler) { + myToler = theToler; + SetShape(myShape, myType); + } +} + +double ElementsOnShape::GetTolerance() const +{ + return myToler; +} + +void ElementsOnShape::SetAllNodes (bool theAllNodes) +{ + if (myAllNodesFlag != theAllNodes) { + myAllNodesFlag = theAllNodes; + SetShape(myShape, myType); + } +} + +void ElementsOnShape::SetShape (const TopoDS_Shape& theShape, + const SMDSAbs_ElementType theType) +{ + myType = theType; + myShape = theShape; + myIds.Clear(); + + if (myMesh == 0) return; + + switch (myType) + { + case SMDSAbs_All: + myIds.ReSize(myMesh->NbEdges() + myMesh->NbFaces() + myMesh->NbVolumes()); + break; + case SMDSAbs_Node: + myIds.ReSize(myMesh->NbNodes()); + break; + case SMDSAbs_Edge: + myIds.ReSize(myMesh->NbEdges()); + break; + case SMDSAbs_Face: + myIds.ReSize(myMesh->NbFaces()); + break; + case SMDSAbs_Volume: + myIds.ReSize(myMesh->NbVolumes()); + break; + default: + break; + } + + myShapesMap.Clear(); + addShape(myShape); +} + +void ElementsOnShape::addShape (const TopoDS_Shape& theShape) +{ + if (theShape.IsNull() || myMesh == 0) + return; + + if (!myShapesMap.Add(theShape)) return; + + myCurShapeType = theShape.ShapeType(); + switch (myCurShapeType) + { + case TopAbs_COMPOUND: + case TopAbs_COMPSOLID: + case TopAbs_SHELL: + case TopAbs_WIRE: + { + TopoDS_Iterator anIt (theShape, Standard_True, Standard_True); + for (; anIt.More(); anIt.Next()) addShape(anIt.Value()); + } + break; + case TopAbs_SOLID: + { + myCurSC.Load(theShape); + process(); + } + break; + case TopAbs_FACE: + { + TopoDS_Face aFace = TopoDS::Face(theShape); + BRepAdaptor_Surface SA (aFace, true); + Standard_Real + u1 = SA.FirstUParameter(), + u2 = SA.LastUParameter(), + v1 = SA.FirstVParameter(), + v2 = SA.LastVParameter(); + Handle(Geom_Surface) surf = BRep_Tool::Surface(aFace); + myCurProjFace.Init(surf, u1,u2, v1,v2); + myCurFace = aFace; + process(); + } + break; + case TopAbs_EDGE: + { + TopoDS_Edge anEdge = TopoDS::Edge(theShape); + Standard_Real u1, u2; + Handle(Geom_Curve) curve = BRep_Tool::Curve(anEdge, u1, u2); + myCurProjEdge.Init(curve, u1, u2); + process(); + } + break; + case TopAbs_VERTEX: + { + TopoDS_Vertex aV = TopoDS::Vertex(theShape); + myCurPnt = BRep_Tool::Pnt(aV); + process(); + } + break; + default: + break; + } +} + +void ElementsOnShape::process() +{ + if (myShape.IsNull() || myMesh == 0) + return; + + if (myType == SMDSAbs_Node) + { + SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator(); + while (anIter->more()) + process(anIter->next()); + } + else + { + if (myType == SMDSAbs_Edge || myType == SMDSAbs_All) + { + SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator(); + while (anIter->more()) + process(anIter->next()); + } + + if (myType == SMDSAbs_Face || myType == SMDSAbs_All) + { + SMDS_FaceIteratorPtr anIter = myMesh->facesIterator(); + while (anIter->more()) { + process(anIter->next()); + } + } + + if (myType == SMDSAbs_Volume || myType == SMDSAbs_All) + { + SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator(); + while (anIter->more()) + process(anIter->next()); + } + } +} + +void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr) +{ + if (myShape.IsNull()) + return; + + SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator(); + bool isSatisfy = myAllNodesFlag; + + while (aNodeItr->more() && (isSatisfy == myAllNodesFlag)) + { + SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next(); + gp_Pnt aPnt (aNode->X(), aNode->Y(), aNode->Z()); + + switch (myCurShapeType) + { + case TopAbs_SOLID: + { + myCurSC.Perform(aPnt, myToler); + isSatisfy = (myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON); + } + break; + case TopAbs_FACE: + { + myCurProjFace.Perform(aPnt); + isSatisfy = (myCurProjFace.IsDone() && myCurProjFace.LowerDistance() <= myToler); + if (isSatisfy) + { + // check relatively the face + Quantity_Parameter u, v; + myCurProjFace.LowerDistanceParameters(u, v); + gp_Pnt2d aProjPnt (u, v); + BRepClass_FaceClassifier aClsf (myCurFace, aProjPnt, myToler); + isSatisfy = (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON); + } + } + break; + case TopAbs_EDGE: + { + myCurProjEdge.Perform(aPnt); + isSatisfy = (myCurProjEdge.NbPoints() > 0 && myCurProjEdge.LowerDistance() <= myToler); + } + break; + case TopAbs_VERTEX: + { + isSatisfy = (aPnt.Distance(myCurPnt) <= myToler); + } + break; + default: + { + isSatisfy = false; + } + } + } + + if (isSatisfy) + myIds.Add(theElemPtr->GetID()); +} diff --git a/src/Controls/SMESH_ControlsDef.hxx b/src/Controls/SMESH_ControlsDef.hxx index dba235958..8fb0cd63f 100644 --- a/src/Controls/SMESH_ControlsDef.hxx +++ b/src/Controls/SMESH_ControlsDef.hxx @@ -29,10 +29,13 @@ #include //#include #include +#include #include #include #include #include +#include +#include #include "SMDSAbs_ElementType.hxx" #include "SMDS_MeshNode.hxx" @@ -645,6 +648,52 @@ namespace SMESH{ }; typedef boost::shared_ptr ElementsOnSurfacePtr; + + /* + Class : ElementsOnShape + Description : Predicate elements that lying on indicated shape + (1D, 2D or 3D) + */ + class SMESHCONTROLS_EXPORT ElementsOnShape : public virtual Predicate + { + public: + ElementsOnShape(); + ~ElementsOnShape(); + + virtual void SetMesh (const SMDS_Mesh* theMesh); + virtual bool IsSatisfy (long theElementId); + virtual SMDSAbs_ElementType GetType() const; + + void SetTolerance (const double theToler); + double GetTolerance() const; + void SetAllNodes (bool theAllNodes); + bool GetAllNodes() const { return myAllNodesFlag; } + void SetShape (const TopoDS_Shape& theShape, + const SMDSAbs_ElementType theType); + + private: + void addShape (const TopoDS_Shape& theShape); + void process(); + void process (const SMDS_MeshElement* theElem); + + private: + const SMDS_Mesh* myMesh; + TColStd_MapOfInteger myIds; + SMDSAbs_ElementType myType; + TopoDS_Shape myShape; + double myToler; + bool myAllNodesFlag; + + TopTools_MapOfShape myShapesMap; + TopAbs_ShapeEnum myCurShapeType; // type of current sub-shape + BRepClass3d_SolidClassifier myCurSC; // current SOLID + GeomAPI_ProjectPointOnSurf myCurProjFace; // current FACE + TopoDS_Face myCurFace; // current FACE + GeomAPI_ProjectPointOnCurve myCurProjEdge; // current EDGE + gp_Pnt myCurPnt; // current VERTEX + }; + + typedef boost::shared_ptr ElementsOnShapePtr; /* diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index baf6c82a6..c91babf31 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -853,7 +853,9 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow, if (theCriterion.Compare == FT_EqualTo || theCriterion.Type == FT_BelongToPlane || theCriterion.Type == FT_BelongToCylinder || - theCriterion.Type == FT_BelongToGenSurface) + theCriterion.Type == FT_BelongToGenSurface || + theCriterion.Type == FT_BelongToGeom || + theCriterion.Type == FT_LyingOnGeom) { QTableItem* anItem = aTable->item(theRow, 0); if (!myAddWidgets.contains(anItem)) @@ -996,8 +998,6 @@ void SMESHGUI_FilterTable::updateAdditionalWidget() ComboItem* anItem = ((ComboItem*)aTable->item(aRow, 0)); bool toEnable = ((ComboItem*)aTable->item(aRow, 1))->GetValue() == FT_EqualTo && - GetCriterionType(aRow) != FT_BelongToGeom && - GetCriterionType(aRow) != FT_LyingOnGeom && GetCriterionType(aRow) != FT_RangeOfIds && GetCriterionType(aRow) != FT_FreeEdges && GetCriterionType(aRow) != FT_BadOrientedVolume; diff --git a/src/SMESH_I/SMESH_Filter_i.cxx b/src/SMESH_I/SMESH_Filter_i.cxx index 68ad197b6..a11e6336f 100644 --- a/src/SMESH_I/SMESH_Filter_i.cxx +++ b/src/SMESH_I/SMESH_Filter_i.cxx @@ -181,6 +181,64 @@ GetMeshDS() const return myMeshDS; } +static bool IsSubShape (const TopTools_IndexedMapOfShape& theMap, + const TopoDS_Shape& theShape) +{ + if (theMap.Contains(theShape)) return true; + + if (theShape.ShapeType() == TopAbs_COMPOUND || + theShape.ShapeType() == TopAbs_COMPSOLID) + { + TopoDS_Iterator anIt (theShape, Standard_True, Standard_True); + for (; anIt.More(); anIt.Next()) + { + if (!IsSubShape(theMap, anIt.Value())) { + return false; + } + } + return true; + } + + return false; +} + +void Controls::BelongToGeom::init() +{ + if (!myMeshDS || myShape.IsNull()) return; + + // is subshape of main shape? + TopoDS_Shape aMainShape = myMeshDS->ShapeToMesh(); + if (aMainShape.IsNull()) { + myIsSubshape = false; + } + else { + TopTools_IndexedMapOfShape aMap; + TopExp::MapShapes(aMainShape, aMap); + myIsSubshape = IsSubShape(aMap, myShape); + } + + if (!myIsSubshape) + { + myElementsOnShapePtr.reset(new Controls::ElementsOnShape()); + myElementsOnShapePtr->SetTolerance(myTolerance); + myElementsOnShapePtr->SetAllNodes(true); // belong, while false means "lays on" + myElementsOnShapePtr->SetMesh(myMeshDS); + myElementsOnShapePtr->SetShape(myShape, myType); + } +} + +void Controls::BelongToGeom::SetTolerance (double theTolerance) +{ + myTolerance = theTolerance; + if (!myIsSubshape) + init(); +} + +double Controls::BelongToGeom::GetTolerance() +{ + return myTolerance; +} + /* Class : LyingOnGeom Description : Predicate for verifying whether entiy lying or partially lying on @@ -271,6 +329,43 @@ GetMeshDS() const return myMeshDS; } +void Controls::LyingOnGeom::init() +{ + if (!myMeshDS || myShape.IsNull()) return; + + // is subshape of main shape? + TopoDS_Shape aMainShape = myMeshDS->ShapeToMesh(); + if (aMainShape.IsNull()) { + myIsSubshape = false; + } + else { + TopTools_IndexedMapOfShape aMap; + TopExp::MapShapes(aMainShape, aMap); + myIsSubshape = IsSubShape(aMap, myShape); + } + + if (!myIsSubshape) + { + myElementsOnShapePtr.reset(new Controls::ElementsOnShape()); + myElementsOnShapePtr->SetTolerance(myTolerance); + myElementsOnShapePtr->SetAllNodes(false); // lays on, while true means "belong" + myElementsOnShapePtr->SetMesh(myMeshDS); + myElementsOnShapePtr->SetShape(myShape, myType); + } +} + +void Controls::LyingOnGeom::SetTolerance (double theTolerance) +{ + myTolerance = theTolerance; + if (!myIsSubshape) + init(); +} + +double Controls::LyingOnGeom::GetTolerance() +{ + return myTolerance; +} + bool Controls::LyingOnGeom::Contains( const SMESHDS_Mesh* theMeshDS, const TopoDS_Shape& theShape, const SMDS_MeshElement* theElem, @@ -845,6 +940,17 @@ char* BelongToGeom_i::GetShapeID() return CORBA::string_dup( myShapeID ); } +void BelongToGeom_i::SetTolerance( CORBA::Double theToler ) +{ + myBelongToGeomPtr->SetTolerance( theToler ); + TPythonDump()<GetTolerance(); +} + /* Class : BelongToSurface_i Description : Predicate for selection on geometrical support @@ -1089,6 +1195,17 @@ char* LyingOnGeom_i::GetShapeID() return CORBA::string_dup( myShapeID ); } +void LyingOnGeom_i::SetTolerance( CORBA::Double theToler ) +{ + myLyingOnGeomPtr->SetTolerance( theToler ); + TPythonDump()<GetTolerance(); +} + /* Class : FreeBorders_i Description : Predicate for free borders @@ -1896,6 +2013,7 @@ static inline bool getCriteria( Predicate_i* thePred, theCriteria[ i ].ThresholdStr = aPred->GetShapeName(); theCriteria[ i ].ThresholdID = aPred->GetShapeID(); theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + theCriteria[ i ].Tolerance = aPred->GetTolerance(); return true; } @@ -1931,6 +2049,7 @@ static inline bool getCriteria( Predicate_i* thePred, theCriteria[ i ].ThresholdStr = aPred->GetShapeName(); theCriteria[ i ].ThresholdID = aPred->GetShapeID(); theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + theCriteria[ i ].Tolerance = aPred->GetTolerance(); return true; } @@ -2124,6 +2243,7 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria SMESH::BelongToGeom_ptr tmpPred = aFilterMgr->CreateBelongToGeom(); tmpPred->SetElementType( aTypeOfElem ); tmpPred->SetShape( aThresholdID, aThresholdStr ); + tmpPred->SetTolerance( aTolerance ); aPredicate = tmpPred; } break; @@ -2150,6 +2270,7 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria SMESH::LyingOnGeom_ptr tmpPred = aFilterMgr->CreateLyingOnGeom(); tmpPred->SetElementType( aTypeOfElem ); tmpPred->SetShape( aThresholdID, aThresholdStr ); + tmpPred->SetTolerance( aTolerance ); aPredicate = tmpPred; } break; diff --git a/src/SMESH_I/SMESH_Filter_i.hxx b/src/SMESH_I/SMESH_Filter_i.hxx index 71e942fc3..da6ee482c 100644 --- a/src/SMESH_I/SMESH_Filter_i.hxx +++ b/src/SMESH_I/SMESH_Filter_i.hxx @@ -66,11 +66,20 @@ namespace SMESH TopoDS_Shape GetShape(); const SMESHDS_Mesh* GetMeshDS() const; + + void SetTolerance( double ); + double GetTolerance(); + + private: + virtual void init(); private: TopoDS_Shape myShape; const SMESHDS_Mesh* myMeshDS; SMDSAbs_ElementType myType; + bool myIsSubshape; + double myTolerance; // only if myIsSubshape == false + Controls::ElementsOnShapePtr myElementsOnShapePtr; // only if myIsSubshape == false }; typedef boost::shared_ptr BelongToGeomPtr; @@ -94,16 +103,26 @@ namespace SMESH TopoDS_Shape GetShape(); const SMESHDS_Mesh* GetMeshDS() const; - + + void SetTolerance( double ); + double GetTolerance(); + virtual bool Contains( const SMESHDS_Mesh* theMeshDS, const TopoDS_Shape& theShape, const SMDS_MeshElement* theElem, TopAbs_ShapeEnum theFindShapeEnum, TopAbs_ShapeEnum theAvoidShapeEnum = TopAbs_SHAPE ); + + private: + virtual void init(); + private: TopoDS_Shape myShape; const SMESHDS_Mesh* myMeshDS; SMDSAbs_ElementType myType; + bool myIsSubshape; + double myTolerance; // only if myIsSubshape == false + Controls::ElementsOnShapePtr myElementsOnShapePtr; // only if myIsSubshape == false }; typedef boost::shared_ptr LyingOnGeomPtr; } @@ -364,6 +383,9 @@ namespace SMESH void SetShape( const char* theID, const char* theName ); char* GetShapeName(); char* GetShapeID(); + + void SetTolerance( CORBA::Double ); + CORBA::Double GetTolerance(); protected: Controls::BelongToGeomPtr myBelongToGeomPtr; @@ -462,6 +484,9 @@ namespace SMESH void SetShape( const char* theID, const char* theName ); char* GetShapeName(); char* GetShapeID(); + + void SetTolerance( CORBA::Double ); + CORBA::Double GetTolerance(); protected: Controls::LyingOnGeomPtr myLyingOnGeomPtr;