myToler(Precision::Confusion()),
myAllNodesFlag(false)
{
- myCurShapeType = TopAbs_SHAPE;
}
ElementsOnShape::~ElementsOnShape()
{
-}
-
-void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
-{
- myMeshModifTracer.SetMesh( theMesh );
- if ( myMeshModifTracer.IsMeshModified())
- SetShape(myShape, myType);
-}
-
-bool ElementsOnShape::IsSatisfy (long theElementId)
-{
- return myIds.Contains(theElementId);
+ clearClassifiers();
}
SMDSAbs_ElementType ElementsOnShape::GetType() const
void ElementsOnShape::SetAllNodes (bool theAllNodes)
{
- if (myAllNodesFlag != theAllNodes) {
- myAllNodesFlag = theAllNodes;
- SetShape(myShape, myType);
- }
+ myAllNodesFlag = theAllNodes;
+}
+
+void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
+{
+ myMesh = theMesh;
}
void ElementsOnShape::SetShape (const TopoDS_Shape& theShape,
const SMDSAbs_ElementType theType)
{
- myType = theType;
+ myType = theType;
myShape = theShape;
- myIds.Clear();
-
- const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
+ if ( myShape.IsNull() ) return;
- if ( !myMesh ) return;
-
- myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType ));
+ TopTools_IndexedMapOfShape shapesMap;
+ TopAbs_ShapeEnum shapeTypes[4] = { TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX };
+ TopExp_Explorer sub;
+ for ( int i = 0; i < 4; ++i )
+ {
+ if ( shapesMap.IsEmpty() )
+ for ( sub.Init( myShape, shapeTypes[i] ); sub.More(); sub.Next() )
+ shapesMap.Add( sub.Current() );
+ if ( i > 0 )
+ for ( sub.Init( myShape, shapeTypes[i], shapeTypes[i-1] ); sub.More(); sub.Next() )
+ shapesMap.Add( sub.Current() );
+ }
- myShapesMap.Clear();
- addShape(myShape);
+ clearClassifiers();
+ myClassifiers.resize( shapesMap.Extent() );
+ for ( int i = 0; i < shapesMap.Extent(); ++i )
+ myClassifiers[ i ] = new TClassifier( shapesMap( i+1 ), myToler );
}
-void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
+void ElementsOnShape::clearClassifiers()
{
- if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0)
- return;
+ for ( size_t i = 0; i < myClassifiers.size(); ++i )
+ delete myClassifiers[ i ];
+ myClassifiers.clear();
+}
- if (!myShapesMap.Add(theShape)) return;
+bool ElementsOnShape::IsSatisfy (long elemId)
+{
+ const SMDS_MeshElement* elem =
+ ( myType == SMDSAbs_Node ? myMesh->FindNode( elemId ) : myMesh->FindElement( elemId ));
+ if ( !elem || myClassifiers.empty() )
+ return false;
- myCurShapeType = theShape.ShapeType();
- switch (myCurShapeType)
+ for ( size_t i = 0; i < myClassifiers.size(); ++i )
{
- case TopAbs_COMPOUND:
- case TopAbs_COMPSOLID:
- case TopAbs_SHELL:
- case TopAbs_WIRE:
+ SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
+ bool isSatisfy = myAllNodesFlag;
+
+ gp_XYZ centerXYZ (0, 0, 0);
+
+ while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
{
- TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
- for (; anIt.More(); anIt.Next()) addShape(anIt.Value());
+ SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
+ centerXYZ += aPnt;
+ isSatisfy = ! myClassifiers[i]->IsOut( aPnt );
}
- break;
- case TopAbs_SOLID:
+
+ // Check the center point for volumes MantisBug 0020168
+ if (isSatisfy && myClassifiers[i]->ShapeType() == TopAbs_SOLID)
{
- myCurSC.Load(theShape);
- process();
+ centerXYZ /= elem->NbNodes();
+ isSatisfy = ! myClassifiers[i]->IsOut( centerXYZ );
}
+ if ( isSatisfy )
+ return true;
+ }
+
+ return false;
+}
+
+TopAbs_ShapeEnum ElementsOnShape::TClassifier::ShapeType() const
+{
+ return myShape.ShapeType();
+}
+
+bool ElementsOnShape::TClassifier::IsOut(const gp_Pnt& p)
+{
+ return (this->*myIsOutFun)( p );
+}
+
+void ElementsOnShape::TClassifier::Init (const TopoDS_Shape& theShape, double theTol)
+{
+ myShape = theShape;
+ myTol = theTol;
+ switch ( myShape.ShapeType() )
+ {
+ case TopAbs_SOLID: {
+ mySolidClfr.Load(theShape);
+ myIsOutFun = & ElementsOnShape::TClassifier::isOutOfSolid;
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();
- }
+ }
+ case TopAbs_FACE: {
+ Standard_Real u1,u2,v1,v2;
+ Handle(Geom_Surface) surf = BRep_Tool::Surface( TopoDS::Face( theShape ));
+ surf->Bounds( u1,u2,v1,v2 );
+ myProjFace.Init(surf, u1,u2, v1,v2, myTol );
+ myIsOutFun = & ElementsOnShape::TClassifier::isOutOfFace;
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();
- }
+ }
+ case TopAbs_EDGE: {
+ Standard_Real u1, u2;
+ Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge(theShape), u1, u2);
+ myProjEdge.Init(curve, u1, u2);
+ myIsOutFun = & ElementsOnShape::TClassifier::isOutOfEdge;
break;
- case TopAbs_VERTEX:
- {
- TopoDS_Vertex aV = TopoDS::Vertex(theShape);
- myCurPnt = BRep_Tool::Pnt(aV);
- process();
- }
+ }
+ case TopAbs_VERTEX:{
+ myVertexXYZ = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) );
+ myIsOutFun = & ElementsOnShape::TClassifier::isOutOfVertex;
break;
+ }
default:
- break;
+ throw SALOME_Exception("Programmer error in usage of ElementsOnShape::TClassifier");
}
}
-void ElementsOnShape::process()
+bool ElementsOnShape::TClassifier::isOutOfSolid (const gp_Pnt& p)
{
- const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
- if (myShape.IsNull() || myMesh == 0)
- return;
-
- SMDS_ElemIteratorPtr anIter = myMesh->elementsIterator(myType);
- while (anIter->more())
- process(anIter->next());
+ mySolidClfr.Perform( p, myTol );
+ return ( mySolidClfr.State() != TopAbs_IN && mySolidClfr.State() != TopAbs_ON );
}
-void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
+bool ElementsOnShape::TClassifier::isOutOfFace (const gp_Pnt& p)
{
- if (myShape.IsNull())
- return;
-
- SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator();
- bool isSatisfy = myAllNodesFlag;
-
- gp_XYZ centerXYZ (0, 0, 0);
-
- while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
+ myProjFace.Perform( p );
+ if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol );
{
- SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
- centerXYZ += aPnt;
-
- 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 = (myCurPnt.Distance(aPnt) <= myToler);
- }
- break;
- default:
- {
- isSatisfy = false;
- }
- }
+ // check relatively to the face
+ Quantity_Parameter u, v;
+ myProjFace.LowerDistanceParameters(u, v);
+ gp_Pnt2d aProjPnt (u, v);
+ BRepClass_FaceClassifier aClsf ( TopoDS::Face( myShape ), aProjPnt, myTol );
+ if ( aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON )
+ return false;
}
+ return true;
+}
- if (isSatisfy && myCurShapeType == TopAbs_SOLID) { // Check the center point for volumes MantisBug 0020168
- centerXYZ /= theElemPtr->NbNodes();
- gp_Pnt aCenterPnt (centerXYZ);
- myCurSC.Perform(aCenterPnt, myToler);
- if ( !(myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON))
- isSatisfy = false;
- }
+bool ElementsOnShape::TClassifier::isOutOfEdge (const gp_Pnt& p)
+{
+ myProjEdge.Perform( p );
+ return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol );
+}
- if (isSatisfy)
- myIds.Add(theElemPtr->GetID());
+bool ElementsOnShape::TClassifier::isOutOfVertex(const gp_Pnt& p)
+{
+ return ( myVertexXYZ.Distance( p ) > myTol );
}
+
TSequenceOfXYZ::TSequenceOfXYZ()
{}