edge ordering for a torus

When I go around the edges of a torus, the order seems to be wrong.

This is the code i use to go around the edges in the parameter space (notice I do use WireExplorer):

#include "occ_header.h"

int main() {

TopExp_Explorer Ex;
TopExp_Explorer Ex2;
TopExp_Explorer Ex3;
BRepTools_WireExplorer Ex4;
TopoDS_Shell Shell;
TopoDS_Face Face;
TopoDS_Wire Wire;
TopoDS_Edge Edge;
Standard_Real First;
Standard_Real Last;
gp_Pnt2d P;

TopoDS_Solid Solid= BRepPrimAPI_MakeTorus(10.,1.);

for (Ex.Init(Solid, TopAbs_SHELL); Ex.More(); Ex.Next())
{
Shell= TopoDS::Shell(Ex.Current());
for (Ex2.Init(Shell, TopAbs_FACE); Ex2.More(); Ex2.Next())
{
Face= TopoDS::Face(Ex2.Current());
for (Ex3.Init(Face, TopAbs_WIRE); Ex3.More(); Ex3.Next())
{
Wire= TopoDS::Wire(Ex3.Current());

for (Ex4.Init(Wire); Ex4.More(); Ex4.Next())
{
Edge= TopoDS::Edge(Ex4.Current());

cout

//const Handle(Geom_Curve)& Curve=BRep_Tool::Curve(Edge,First,Last);

const Handle(Geom2d_Curve)& Curve2d=BRep_Tool::CurveOnSurface(Edge,Face,First,Last);
Curve2d->D0(First,P);

cout cout

Curve2d->D0(Last,P);

cout cout }
}
}
}

return 0;

}

and here's the output
for each edge, i compute the (u,v) at beginning and end of underlying curve
Orient is the edge orientation
recall that 0 means FORWARD and 1 means REVERSED
if it says FORWARD, you have to go from First to Last
if it says REVERSED, you have to go from Last to First in order to loop around the torus.

Orient= 1
First= 0
u= 0 v= 6.28319
Last= 6.28319
u= 6.28319 v= 6.28319
Orient= 0
First= 0
u= 6.28319 v= 0
Last= 6.28319
u= 6.28319 v= 6.28319
Orient= 0
First= 0
u= 0 v= 0
Last= 6.28319
u= 6.28319 v= 0
Orient= 1
First= 0
u= 0 v= 0
Last= 6.28319
u= 0 v= 6.28319

So, the loop goes like this:
(6.28,6.28) to (0,6.28) to (6.28,0) which is wrong!

Can somebody take a loop? Either i am doing something wrong or this is a bug.

Ugo Capeto's picture

anybody?

is what i am doing correct to get a discretized representation of the model face's boundary in the (u,v) parameter space? In the example above, i am just looking at the beginning and end of each bounding edge (in real life, i may be taking more samples along each bounding edge).

i have been using this method for all types of faces and it seems to work alright except for a full torus.

Roman Lygin's picture

Hi Ugo,

First off, you are not doing anything wrong - you are exploring the model correctly. As improvement suggestion:
you can explore wires directly using
TopExp_Explorer anExp (aShape, TopAbs_WIRE) instead of going level-by-level from shells.

Secondly, Open CASCADE does NOT require a wire to be clock-wise, anti-clockwise, tail-to-head, etc oriented. Edges can be in any arbitrary order, of course ensuring that each edge is correctly oriented. Torus, sphere (and probably other elementary shapes) are created such that their edges go in head-to-tail (instead of more logical tail-to-head) order. See in Draw:
pload MODELING
av2d
ptorus p 100 50
fit
explode p f
pcurve p_1
2dfit
whatis . . . . #then click 4 times on each pcurve to get their names

Same works for 'psphere 50'.

BRepTools_WireExplore is aimed to facilitate the edge ordering tail-to-head during exploration. If it fails in this case, it sounds like a bug.

Shape Healing's ShapeAnalysis_Wire has stronger capabilities to check and orient wire's edges - working for 2D or 3D modes, closed and open wires, etc. The usage model would be either:
- create ShapeFix_Wire feeding a wire and a face
- call ::FixReOrder()
- retrieve ShapeBuild_WireData using ::WireData()
- explore edges

or

- create ShapeExtend_WireData from a wire
- create ShapeAnalysis_Wire feeding a WireData and a face
- Call CheckConnected() specifying a 2D mode flag, retrieve an object ShapeAnalysis_WireOrder
- request index of each edge in original WireData object using ShapeAnalysis_WireOrder::Ordered().

Hope this helps.
Roman

Ugo Capeto's picture

thank you Roman for your detailed answer.

Does this thread constitute a proper "bug report" or is there a more formal way of doing so?

Roman Lygin's picture

Hopefully OCC team could pay attention to this trying to reproduce/refute?

sergey zaritchny's picture

Hi Ugo,
I tried to reproduce your case (using Draw commands ptorus, pcurve,2dcvalue, dval), but didn't get any wrong result.
See the attached picture presenting pcurves of torus. By green color presented coordinates,
by yellow - names of the corresponding pcurves.
More over your debugging output is correct too!
Just conclusion seems wrong. Below I am going along your output.
1. p_1_1: (0, 6.28) --> (6.28,6.28); OR = 1
2. p_1_2: (6.28, 0) --> (6.28, 6.28); OR = 0
3. p_1_3: (0, 0) --> (6.28, 0); OR = 0
4. p_1_4: (0, 0) --> (0, 6.28); OR = 1
Edges oriented in next order: (p_1_3, p_1_2, p_1_1, p_1_4) ==> counterclockwise.
It looks Ok(see the attached picture). You may check it once again.
Regards
Sergey

Attachments: 
sergey zaritchny's picture

Sorry, the analysis is still not finished.
It sent by mistake.
Regards

sergey zaritchny's picture

sorry, I didn't catch that you are using WireExplorer.
I checked it once again. So, we didn't consider it as a bug of algorithm.
Rather it is a documentation bug. From current description it is not very clear which constructor should be used. We will take care to fix it.
If a wire to be analyzed has underlying face you should use the appropriate constructor with two parameters:
BRepTools_WireExplorer exp(wire, face).
In this case you will get expected by you order.
Regards
Sergey

Ugo Capeto's picture

Sergey:

Thanks for taking a look. I did as you suggested but i get the exact same result.
it goes from (6.28,6.28) to (0,6.28) for the 1st Edge in the Wire
and then from (6.28,0) to (6.28,6.28) for the 2nd Edge in the Wire, same as before.

Do you actually get the right behavior when you do it?

I now use the proper constructor BRepTools_WireExplorer Ex4(Wire,Face) but am I missing something else?

sergey zaritchny's picture

Hi Ugo,
I actually got the right order - see the attached pictures.
Besides you may easy reproduce it in Draw:
ptorus p 10 1
explo p F
explo p_1 ## p_1 is a face
whatis p_1_1 ## p_1_1 is a Wire
wexplo p_1_1 p_1
directory ## => p_1_1 WEDGE_1 WEDGE_2 WEDGE_3 WEDGE_4 pi minf axes2d pinf p axes grid p_1
av2d
pcurve p1 WEDGE_1 p_1
2dfit
pcurve p2 WEDGE_2 p_1 ## the first picture present this point
2dfit
pcurve p3 WEDGE_3 p_1 ## the second picture presents this point
2dfit
pcurve p4 WEDGE_4 p_1
2dfit

So, probably you should check your code once again.
Regards

Attachments: 
Ugo Capeto's picture

ok, Sergey, you're absolutely right, it does give the correct ordering when you construct the wire explorer with the pair (Wire,Face). Thanks for checking this!