Problem with MapShapesAndAncestors

Hello again,

The attached file shows a model with 2 faces highlighted (Face1.jpg and Face2.jpg), and the edge that these faces share (Edge.jpg). These pictures are here to show that OCCT is correctly detecting faces and edges on that model.
I need to check all edges of the model for their concavity, and for that I need the ancestor faces of every edge. So I checked the forums and got the following piece of code:

============================================================================

//
TopTools_IndexedDataMapOfShapeListOfShape anEFsMap;
TopExp::MapShapesAndAncestors(modelo3D, TopAbs_EDGE, TopAbs_FACE, anEFsMap);

//
for(int i = 1; i

if (anEFsMap.FindFromIndex(i).Extent() != 2)
cout }

=============================================================================

This is not working properly, for it says the number of ancestor faces is 1, for every edge.
Any guesses as to what is going on?

Thanks in advance,
Rodrigo

Attachments: 
Rodrigo Castro Andrade's picture

In an attempt to find out what is going on, I used TopExp_Explorer to compare all edges with one another, i hopes that method MapShapesAndAncestors was considering that 2 edges exactly alike with different orientations were being considered 2 different edges. That would explain why every edge only has a single face as ancestor.
Sadly, that did not work. I've compared every edge with one another using TopoDS_Shape methods IsEqual(), IsPartner(), and IsSame(), with no hits. It's as if the edge on a particular location belongs only to a single face, leaving the other face without edge at that boundary.
Is it even possible to have a face with no edge at a particular boundary?

Rodrigo Castro Andrade's picture

By doing some research on the forums, I found out that determining if edges are the same is a rather complex task, and the end result is only an approximate justification. Thanks to fellow users, I can now compare two edges with a rather high level of certainty.
Closing this issue, I decided to use TopExp_Explorer in order to compare every edge of every single face with one another, to find out which faces shared the same edge. This method worked well, and now I have the proper ancestor faces of every edge.

Thanks for those who maintain and contribute to the forums!

hadi.parvaz's picture

Dear Rodrigo

How did you solve the problem? would you please describe your method?

I have the same problem and tried out the iteration on all edges of faces but no success. Again, it gives me 1 face for each edge.

thanks in advance

Rodrigo Castro Andrade's picture

Hello Hadi,

There are two issues here:

1- Correctly iterate through the edges of every face: I had to create 2 TopExp_Explorer objects to compare every edge of a face with every edge of the other face, for every 2 faces of my solid. To do that you could use another 2 TopExp_Explorer objects to explore the faces of the solid/compound. I found it easier to place all the faces on a list and iterate through it. Be careful not to compare a face with itself. Using maps is probably easier than my way...

2- Correctly check if 2 edges are the same: ShapeAnalysis_Edge::CheckOverlapping() was sufficient for my purposes, but I found the following code on the forums (my thanks to whoever wrote it):

int IsCurveEqual(TopoDS_Edge &aEdge_1, TopoDS_Edge &aEdge_2)
{
int nResult = 0;
// int IsSatisfied_1 = 1, IsSatisfied_2 = 1;

Handle(Geom_Curve) theCurve_1, theCurve_2;
TopLoc_Location L_1, L_2;
Standard_Real First_1, Last_1;
Standard_Real First_2, Last_2;
//
//
theCurve_1 = BRep_Tool::Curve(aEdge_1, L_1, First_1, Last_1);
theCurve_2 = BRep_Tool::Curve(aEdge_2, L_2, First_2, Last_2);

// IsSatisfied_1 = fabs(First_1 - First_2);
// IsSatisfied_2 = fabs(First_1 - Last_2);

// if (!(IsSatisfied_1 || IsSatisfied_2))
// return nResult;

GeomAdaptor_Curve GAC_1(theCurve_1);
GeomAdaptor_Curve GAC_2(theCurve_2);

//
gp_Pnt aPoint1, aPoint2;
Standard_Real uRatio = 0.5;
aPoint1 = AddNewPointOnCurve(aEdge_1, uRatio);
aPoint2 = AddNewPointOnCurve(aEdge_2, uRatio);

if (aPoint1.Distance(aPoint2) > TOLERANCIA_DIST_PONTOS) {
return nResult;
}
uRatio = 0.9;
aPoint1 = AddNewPointOnCurve(aEdge_1, uRatio);
aPoint2 = AddNewPointOnCurve(aEdge_2, uRatio);

if (aPoint1.Distance(aPoint2) > TOLERANCIA_DIST_PONTOS) {
return nResult;
}
uRatio = 0.1;
aPoint1 = AddNewPointOnCurve(aEdge_1, uRatio);
aPoint2 = AddNewPointOnCurve(aEdge_2, uRatio);

if (aPoint1.Distance(aPoint2) > TOLERANCIA_DIST_PONTOS) {
return nResult;
}

if (!(GAC_1.GetType() == GAC_2.GetType()))
{
return nResult;
}

nResult = 1;
return nResult;
}

const gp_Pnt& AddNewPointOnCurve(TopoDS_Edge support_edge, Standard_Real desired_ratio){

const TopoDS_Edge& aEdge = TopoDS::Edge(support_edge);
Standard_Real aFP, aLP, aP;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aFP, aLP);
aP = aFP + (aLP - aFP) * desired_ratio;
gp_Pnt p1 = aCurve->Value(aP);

return p1;
}

Make sure the edges are not degenerated before using this (BRep_Tool::Degenerated()). It pretty much consists of comparing particular points between the two edges, even more so if you remove the IsSatisfied_1/2 checks, which I did. As you can see, you can add more points to compare, for greater precision.
Instead of a particular value for TOLERANCIA_DIST_PONTOS, you can use Precision::Confusion(), or some other method from the great Precision class.

Hope it helps,
Rodrigo