Compare if two Geom_Curves are identical

Hey people,

I have the following situation: suppose we want to build a swept surface from three Geom_Lines - two end sections and a spine curve. Thus at the and we will have something like a rectangular surface. Now, I want to get the boundaries of this new surface, so I run a TopExp_Explorer on this new TopoDS_Face, and extract all the TopoDS_Edges. Obviously there would be 4 edges: the 3 original edge, and a 4th one so that the wire enclosing the face can be closed.

So far, so good, but now comes the problem. I want to add the face to my data structure (I have a separate data structure for other reasons), along with the enclosing edges. So I run through all the bounding edges, and check whether an edge already existed in the database or not.

What should this check function be composed of?

It seems that when you create a new surface from existing curves, the boundary would be composed of new TopoDS_Edges, so I cannot just say:

if(curTopoDS_Edge == dataBaseTopoDS_Edge)
{
return;
}

What would be a good comparison? I guess the best way is to somehow compare the underlying geometrical entites, but I couldn't find a nice way to check if two curves are geometrically the same.

Thanks for your help!

László

Hennig's picture

Hello Laszlo,

you cant check if they are the same (neither with .IsEqual nor with IsSame(), because the TShape differ after explore it from the face).

My idea would be to get the centre of mass from the edges as a gp_Pnt and compare them with ISEqual. This is not a nice way but should work in your case. When you find a better way to compare edges or there geom_curves please inform me. Im faced with a similar problem.

Hope this help.
paul

Laszlo Kudela's picture

Hello Paul,

I think I have found a solution. It is computationally quite expensive I guess, but might work for most of the cases.

The idea is the following:
Get the two Geom_Curves (Curve A and Curve B), and make a quick check if the two endpoints of the curves are the same. If this is not the case, they are not equal for sure. If this condition is satisfied, then loop through all the points of Curve B, and make a projection to Curve A from these points. If the distance of the projected point on Curve A to the point on Curve B is higher then a given tolerance, then the curves are not equal. If for all the points the distance of projection stays under the limit, they are geometrically equal.

Yeah, basically we do not loop through all the points of curve B, we only use a specific resolution.

Here is the code:

bool checkForGeometricEquality(Handle(Geom_Curve) curveA, Standard_Real startParamA,Standard_Real endParamA, Handle(Geom_Curve) curveB,Standard_Real startParamB, Standard_Real endParamB)
//The function takes curveA and its parameter range, and curveB with its parameter //range
{
//How many projections do we want
int resolution = 10;
Standard_Real paramIncrement = ((startParamB-endParamB)/double(resolution));

GeomAPI_ProjectPointOnCurve projector;

//Get the start end endpoints of the curves
gp_Pnt startPointA = curveA->Value(startParamA);
gp_Pnt startPointB = curveB->Value(startParamB);
gp_Pnt endPointA = curveA->Value(endParamA);
gp_Pnt endPointB = curveB->Value(endParamB);

// Check if there are matching pairs
if(startPointA.IsEqual(startPointB,Precision::Confusion()) ||
startPointA.IsEqual(endPointB,Precision::Confusion()) ||
endPointA.IsEqual(startPointB,Precision::Confusion()) ||
endPointA.IsEqual(endPointB,Precision::Confusion()))
{
//Loop through points of curveB and project them on curveA
for(int i=0;iValue(startParamB+i*paramIncrement);
projector.Init(checkPnt,curveA);
//If the distance exceeds the limit, return false
if(projector.LowerDistance()>Precision::Confusion())
{
return false;
}
}
//If the for cycle finished, the curves are equal
return true;
}

return false;
}

So if you have two TopoDS_Edges (topoEdgeA and TopoEdgeB), this is how the function is called:

Standard_Real startParamA,endParamA;
Standard_Real startParamB,endParamB;

Handle(Geom_Curve) curveA = BRep_Tool::Curve(topoEdgeA,startParamA,endParamA);
Handle(Geom_Curve) curveB = BRep_Tool::Curve(topoEdgeB,startParamB,endParamB);

if(checkForGeometricEquality(curveA,startParamA,endParamA,curveB,startParamB,endParamB)
{
//They are equal
}
else
{
// They are not equal
}

I haven't done extensive testing, but it worked for matching Geom_Lines and Geom_BezierCurves. And it also worked for my original problem (compare two TopoDS_Edges geometrically.)

Hope this helped! :)

Best regards,
László

Laszlo Kudela's picture

Sorry, I have to add a small correction to my code:

Standard_Real paramIncrement = ((endParamB-startParamB)/double(resolution));

I was computing the paramIncrement in a bad manner. It was returning a negative number sometimes. I'm not sure, maybe this paramIncrement should depend of the parameter range, and check if there is a sign change in the parameter range.

Hennig's picture

hey laszlo,

thanks for the code. i will try this after translating in PythonOCC. currently i use my easy check with the CenterOfMass.

greetings

Ear MongHeng's picture

Hi paul,

i met the same problem,can you tell me more how to do it or write a code?

i am looking forward hearing from you soon.

From Cambodia student.

Forum supervisor's picture

Dear Laszlo,
In OCCT 6.5.4, you can use method IsEqual() of the class Geom_BSplineCurve to compare two b-splines for equality. Alas, other types of curves do not implement this possibility yet. However OCCT is open source,
so you can contribute to the project by implementing the expected functionality and submitting the changes for integration to OCCT. See 'Get involved' at the Collaborative development portal for details http://dev.opencascade.org.
Regards

Laszlo Kudela's picture

Dear Forum supervisor,

thanks for the note. The research group here uses version 6.3, so I guess I won't be using this IsEqual() function of the Geom_BSplineCurve for a while.

However, if it is there, and working, then a good way for comparing curves might be to convert the curves to be compared to b-spline curves, and check their equality using the above mentioned function.

I will check out the link also.

Best regards,
László

haowei's picture

Dear Forum supervisor
I don't find the method IsEqual() of the class Geom_BSplineCurve in OCCT6.5.4. Are you sure the method IsEqual() exist in OCCT6.5.4 ?

Forum supervisor's picture

Dear haowei,
Sorry, it seems I was wrong.
It has been integrated after the last release.
But you can access it via the development portal.
See http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff;h=a7493ad...
Regards

Laszlo Kudela's picture

Hi everyone, I was improving the algorithm a little bit. It now checks for pairs of matching points. (Thus it will skip all the objects that have one endpoint in common)

Here it is:

bool checkForGeometricEquality(Handle(Geom_Curve) curveA, Standard_Real startParamA,Standard_Real endParamA, Handle(Geom_Curve) curveB,Standard_Real startParamB, Standard_Real endParamB)
{
//The function gets two Geom_Curve objects with their parameter ranges and compares
//them if they are equal. If yes, it returns true. If not, it returns false.

//Resolution for point-wise comparison
int resolution = 10;
Standard_Real paramIncrement = ((endParamB-startParamB)/double(resolution));

GeomAPI_ProjectPointOnCurve projector;

//Get the endpoints of the curves.
gp_Pnt startPointA = curveA->Value(startParamA);
gp_Pnt startPointB = curveB->Value(startParamB);
gp_Pnt endPointA = curveA->Value(endParamA);
gp_Pnt endPointB = curveB->Value(endParamB);

//Compare the endpoints, check if there are matching pairs. If not, te curves are not equal
if(( startPointA.IsEqual(startPointB,Precision::Confusion()) && endPointA.IsEqual(endPointB,Precision::Confusion()))
||
( endPointA.IsEqual(startPointB,Precision::Confusion()) && startPointA.IsEqual(endPointB,Precision::Confusion()))
)
{
//Project points from curveB to curveA, and check the distance of projection.
for(int i=0;iValue(startParamB+i*paramIncrement);
projector.Init(checkPnt,curveA);
//If the distance is more than a given limit, return false
if(projector.NbPoints()>0)
{
//Old algorithm, might be useful later...
/*Standard_Real maxDistance = projector.LowerDistance();
for(int j = 1;j<=projector.NbPoints();j++)
{
if(projector.Distance(j)>maxDistance)
{
maxDistance = projector.Distance(j);
}
}
if(maxDistance=Precision::Confusion())
{
return false;
}
return true;
}
}
}
return false;
}

Laszlo Kudela's picture

Also, you might check the bounding boxes of the two objects as a pre-filter for this function. It looks like this:

bool checkBndBoxes(TopoDS_Edge edgeA, TopoDS_Edge edgeB)
{
//The function compares if the bounding boxes of edgeA and edgeB are touching or intersecting
//each other
Bnd_Box boxA;
Bnd_Box boxB;

BRepBndLib::Add(edgeA,boxA);
BRepBndLib::Add(edgeB,boxB);

if(boxA.Distance(boxB) <= Precision::Confusion())
{
return true;
}
return false;
}