Reversed does not lead to expected result

Hi,

when I cut a model with a plane, I get a bunch of edges all jumbled up. I try to sort them so that the start point of an edge matches the end point of the previous edge (preparation to create a polyline).

But now, if the endpoint of the previous edge matches the endpoint of the current edge, I have to flip the current edge.

This does not work. No matter whether I use "Reversed" from Geom_Curve or from TopoDS_Edge, the result does not give the same points in reverse order, but completely different points that don't belong to the curve.

What would be the right way to reverse a curve?

P.S.: I calculate the curve points by using Geom_Curve::D0

Mikhail Sazonov's picture

Hi,

In order to make a connected chain of edges, if some edge must be reversed you should reverse it, not to reverse an underlining curve.

When you get a point of one of the ends of the edge using Geom_Curve::D0, you must consider the edge orientation, so that to get opposite end in the case of reversed edge.

Hint: probably the method ShapeAnalysis_FreeBounds::ConnectEdgesToWires() does what you need.

BR,
Mikhail

DjangoReinhard's picture

Hi Mikhail,

Thank you very much for your help! I read the docs for hinted method - I don't have compound of faces. I don't even have a wire. Guess result of boolean operation is just a bunch of unrelated edges ...

So I tried to follow your first advice and change the direction of the Geom_Curve. Hm, does not work as expected. To reverse a straight line, I could simply create a new one and forget the old one. But for arcs its not that easy. When I create an arc from scratch, it will be a Geom_Trimmed_Curve based on a circle (I'm not aware of any other way to create an arc), but all arcs from boolean operation are no trimmed curves. All arcs are circles with different start and end parameters.

Actually I try to flip curves with this:

TopoDS_Edge flipCurve(Handle(Geom_Curve) c, double param0, double param1) {
  TopoDS_Edge rv;

  if (c->DynamicType() == STANDARD_TYPE(Geom_Line)) {
     Handle(Geom_Line) line = Handle(Geom_Line)::DownCast(c);
     gp_Dir            dir  = line->Position().Direction();
     gp_Dir            rDir = dir.Reversed();

     qDebug() << "line direction:" << dir.X() << "/" << dir.Y() << "/" << dir.Z();
     qDebug() << "      reversed:" << rDir.X() << "/" << rDir.Y() << "/" << rDir.Z();

     line->SetDirection(rDir);
     BRepBuilderAPI_MakeEdge me(line);

     rv = me.Edge();
     }
  else if (c->DynamicType() == STANDARD_TYPE(Geom_Circle)) {
     Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(c);
     gp_Ax1              axis   = circle->Axis();
     gp_Dir              dir    = circle->Axis().Direction();
     gp_Dir              rDir   = dir.Reversed();

     qDebug() << "circle direction:" << dir.X() << "/" << dir.Y() << "/" << dir.Z();
     qDebug() << "        reversed:" << rDir.X() << "/" << rDir.Y() << "/" << rDir.Z();

     axis.SetDirection(rDir);
     circle->SetAxis(axis);
     BRepBuilderAPI_MakeEdge me(circle);

     rv = me.Edge();
     }
  gp_Pnt p0, p1;

  c->D0(param0, p0);
  c->D0(param1, p1);

  qDebug() << "> flipped edge" << p0.X() << "/" << p0.Y() << "\t-\t" << p1.X() << "/" << p1.Y()
           << "\t(" << param0 << " - " << param1 << ")";

  return rv;
  }

debug output looks like:

find neighbour for edge 12.9028 / -78.9526  -    -12.9028 / -78.9526    ( 1.4088  -  1.73279 )
         check edge -25.102 / -48.7587  -    -12.9028 / -78.9526    ( 17.9024  -  50.4677 )
line direction: 0.374607 / -0.927184 / 0
      reversed: -0.374607 / 0.927184 / 0
> flipped edge -38.5147 / -15.5609  -    -50.7139 / 14.633  ( 17.9024  -  50.4677 )
Mikhail Sazonov's picture

Hi DjangoReinhard,

The hinted method does not deal with faces. Its declaration is:

  Standard_EXPORT static void ConnectEdgesToWires
        (Handle(TopTools_HSequenceOfShape)& edges,
         const Standard_Real toler,
         const Standard_Boolean shared,
         Handle(TopTools_HSequenceOfShape)& wires);

So, you just pass there the list of edges and it will prepare for you the list of wires.

>So I tried to follow your first advice and change the direction of the Geom_Curve. 

I am sorry if I was not clear enough, but I did not advise you to reverse the curve. In opposite, I advised you to change orientation of edge.

BR,
Mikhail

DjangoReinhard's picture

Hi,

I finally got around to trying out your tip.

Unfortunately the result is not usable for me, because I still have to calculate points on the edges - and the only way I know to achieve this using Geom_Curve::D0.

So I left it as unresolved problem and sort the edges without flipping them if needed. The polylines from CavalierContour are much easier to handle. Including the change of direction of a curve.

... and I have no problem in visualizing that polylines with opencascade.

so - after all: thank you very much for your attention and your support!

xu rongyan's picture

Hi, I had a similar problem in OCCT 7.8.0. I try to call Geom_Curve::Reversed to get a reversed copy of the origin curve, and then I use the first and last parameter obtained from the Geom_Curve::FirstParameter and Geom_Curve::LastParameter to the Geom_Curve::D0 function to verify the resulting result but got unexpected result. Here is my code:

Standard_Real first, last;
Handle(Geom_Curve) curve = BRep_Tool::Curve(e, first, last);
gp_Pnt originP1, originP2;
curve->D0(first, originP1);
curve->D0(last, originP2);
curve->Reverse();
gp_Pnt P1, P2;
curve->D0(curve->FirstParameter(), P1);
curve->D0(curve->LastParameter(), P2);

result:

originP1 = (0, 1, 0) originP2 = (0, 0, 0)

P1 = (0, 1, 0) P2 = (0, -2, 0)

It seems that the Reversed function actually behaves quite differently from the behavior described in the documentation

Mikhail Sazonov's picture

The method BRep_Tool::Curve returns parameters on the curve corresponding to the vertices of the edge. Whereas curve->FirstParameter() and curve->LastParameter() return end parameters of the full curve. The correct code would be the following:

  Standard_Real first, last;
  Handle(Geom_Curve) curve = BRep_Tool::Curve(e, first, last);
  gp_Pnt originP1, originP2;
  curve->D0(first, originP1);
  curve->D0(last, originP2);
  Handle(Geom_Curve) curveRev = curve->Reversed();
  gp_Pnt P1, P2;
  Standard_Real firstRev = curve->ReversedParameter(last);
  Standard_Real lastRev = curve->ReversedParameter(first);
  curveRev->D0(firstRev, P1);
  curveRev->D0(lastRev, P2);