Fuse cylindrical faces

Hello folks,

I have two faces (see attached png) which lie on the same cylindrical surface and which share two edges. I need to merge them into one single face.
I tried to use BRepAlgoAPI_Fuser as well as the older version BRepAlgo_Fuser. Both failed. That is, both returned a shape concisting of the two original faces.
I also tried BRepAlgoAPI_Sewer which gave the same result.

Another idea was to build the face from scratch, using the edges of the original faces. I deleted all twin edges (one sibiling) and added all remaining edges to the BRepBuilderAPI_MakeWire. The wire construction seemed ok. I ran ShapeFix_Shape on the wire and tried to build a new face by using BRepBuilderAPI_MakeFace(gp_Cylinder, TopoDS_Wire), which failed.

How can I turn these faces into one?

Any hint/suggestion is welcome.

Thanks

Dennis

Dennis G.'s picture

Okay, by now I think the method to use should be BRepBuilderAPI_Sewing.
But it doesn't work as I would have expected. The result is always the same: a Shell consisting of two faces.
I tried higher tolerances and also the Load function to define the context shape. Nothing.
I use this code:

[code]
BRepBuilderAPI_Sewing tailor;
// TopoDS_Face dummyFace;
// tailor.Load(dummyFace);
tailor.Add(f1);
tailor.Add(f2);
tailor.Perform();
tailor.Dump();

TopoDS_Shape swdShp = tailor.SewedShape();
TopAbs::Print(swdShp.ShapeType(),cout);
[/code]

-Dump() :
Informations
===========================================================

Number of input shapes : 2
Number of actual shapes : 2
Number of Bounds : 4
Number of Sections : 4
Number of Edges : 4
Number of Vertices : 4
Number of Nodes : 4
Number of Free Edges : 4
Number of Contigous Edges : 0
Number of Multiple Edges : 0
Number of Degenerated Edges : 0
===========================================================
-end Dump()

ShapeType is: SHELL

Regards,

Dennis

Dennis G.'s picture

I did some testing with the DRAW executable (same results). Please find attached a step file containing the two faces to be sewed.

Since the standard functions fail to merge these faces, I'll try to build the result face from scratch once again.
These are my planed steps:
1. extract all edges from both original faces
2. fuse nonlinear edges lying on the same curve to get rid of intermediate vertices (is ..._Sewing() suitable for edges?)
3. pick a vertex of one of the nonlinear (fused) edges and find the linear edge that shares this vertex (same orientation)
4. find the vertex on the other nonlinear edge, that is the same as the end-point vertex of the linear edge
5. pick the other ends vertex of the other nonlinear edge and find the second linear edge
-- now the four bounding edges of the final face should be known (ordered)
6. build a TopoDS_Wire using BRepBuilderAPI_MakeWire (.Add(...))
7. build the final TopoDS_Face using BRepBuilderAPI_MakeFace(theWire)

If someone has enough experience to see that this is not gonna work, I would greatly appreciate to know it before I start implementing this tomorrow morning.

Regards,

Dennis

Attachments: 
Evgeny Lodyzhehsky's picture

Dear Dennis G.

Your task is not so simple,
but it can be solved for some cases.
The case you've sent is one of them.
____________
Legend:
- x1 is compound containing your two faces;
- fz is the result face.

Use the Draw commands below:
restore x1

explode x1 f
copy x1_1 b1
copy x1_2 b2

mksurface s1 b1
mkface f1 s1

bop f1 b1
bopcommon r1
explode r1 f
explode r1_1 e

bop f1 b2
bopcommon r2
explode r2 f
explode r2_1 e

wire w r1_1_1 r1_1_3 r1_1_4 r2_1_1 r2_1_2 r2_1_4
mkface fz s1 w
____________

The main idea is to
1. have the one 2D domain "s1" for all edges;
2. reject redundant edges r1_1_2, r2_1_3

Dennis G.'s picture

Thank you Evgeny Nicolaich,

I'll try to implement this method into an algorithm for my programme.

Cheers,

Dennis

Dennis G.'s picture

Dear Evgeny Nicolaich,

Your example is very precious to me, but still I can't solve the problem inside my programme. I can construct a wire and the BRepBuilderAPI_MakeFace class creates a face (with an incredibly huge area).

Here's what I do when fusing of two faces (f1, f2) on the same surface fails...

[code ****************************************************]
if(f1.ShapeType() == TopAbs_Cylinder)
{
// prepare faces
///////////////////////////////////
BRepAdaptor_Surface baS(f1);
gp_Cylinder aCyl = baS.Cylinder();
TopoDS_Face cylFc = BRepBuilderAPI_MakeFace(aCyl).Face();

BRepAlgoAPI_Common cmn1(cylFc, f1);
TopoDS_Shape cmnShp1;
if(cmn1.IsDone())
cmnShp1 = cmn1.Shape();

BRepAlgoAPI_Common cmn2(cylFc, f2);
TopoDS_Shape cmnShp2;
if(cmn2.IsDone())
cmnShp2 = cmn2.Shape();

if(cmnShp1.IsNull() || cmnShp2.IsNull())
break;

// extract faces
///////////////////////////////////
...
// check if common faces are OK
// final common faces are fc1 and fc2
...
// extract edges
///////////////////////////////////
Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;

for(TopExp_Explorer ee(fc1, TopAbs_EDGE); ee.More(); ee.Next())
edges->Append(ee.Current());
for(TopExp_Explorer ee(fc2, TopAbs_EDGE); ee.More(); ee.Next())
edges->Append(ee.Current());

// remove redundant edges and sort
////////////////////////////////////////
...
// I assume that only two of the four linear edges can be considered as redundant
// therefore I check for the curve type and delete two linear curves with the same length and location but
// opposite orientation
// this leaves 6 edges (of formerly 8)
...
// This is what I pass to the BRepBuilderAPI_MakeWire below:
//
// Edge : 1 Length : 32.8768 is circle ... REVERSED
// Edge : 2 Length : 32.8768 is circle ... REVERSED
// Edge : 3 Length : 67.0167 is line ... REVERSED
// Edge : 4 Length : 39.9784 is ellipse ... FORWARD
// Edge : 5 Length : 39.9784 is ellipse ... FORWARD
// Edge : 6 Length : 67.0167 is line ... FORWARD
//
...
// make wire
///////////////////////////////
BRepBuilderAPI_MakeWire wrMkr;
for(int i=1; i<=sortedEdges->Length(); i++)
{
TopoDS_Edge E = TopoDS::Edge(sortedEdges->Value(i));
wrMkr.Add(E);
if(!wrMkr.IsDone())
cout << "WireMaker.Add() failed for edge : " << i << endl;
}
wrMkr.Build();

TopoDS_Wire w = wrMkr.Wire();

// the wire construction seems to be OK, but the wire still contains 6 edges, as TopExp_Explorer reveals
// while the wire in your DRAWEXE example consists of only four edges (nbshapes ...)
//
// Number of shapes in w
// VERTEX : 4
// EDGE : 4
// WIRE : 1 ...
//
// This is why I assume the error within the wire construction.
// I tried different arangements of the edges but with no success.

TopoDS_Face theFace = BRepBuilderAPI_MakeFace(aCyl, w).Face();

if(theFace.IsNull())
cout << "NULL face!!!\n";

// Face Area : 2.63014e+102 || Ooops, that's huge!!!

// output final face into step file
////////////////////////////////////
STEPControl_Writer wrt;
wrt.Transfer(theFace, STEPControl_AsIs);
wrt.Write("theFace.stp");

// ***** Segmentation fault ******
}
[/code ***************************************************]

What could be the problem?

Thanks,

Dennis

Dennis G.'s picture

I solved the problem differently now.

1. introduce a bounding box for the original faces and make it a TopoDS_Shape (BB Shape)
2. make an infinite face from the shared surface (sF)
3. compute COMMON of BB and sF (cmnF)
4. construct faces from the curved edges at the end of the original faces (eF1, eF2)
5. use the end faces eF1 and eF2 to cut the cmnF to the final size

This approach worked for this special case. I will see what other problems I encounter while using this method. I attached an image from the result.

It would still be nice, to know what caused the error in the method above. If anyone sees an obvious mistake, please share your wisedom.

Cheers,

Dennis

Dennis G.'s picture

This didn't pay off so well. Another two faces made BRepAlgoAPI_Common never to finish its work.

Dennis G.'s picture

The constructed face has a quasi-infinite area, because the wire is not closed. Why is the wire not closed? I don't know.
I tried to fix the wire by using ShapeFix_Wire. Without success.
Here's what I've done:

[code *****************************************]
TopoDS_Wire w = wrMkr.Wire();

if(!w.Closed())
{
Handle(ShapeExtend_WireData) wrDta = new ShapeExtend_WireData;
wrDta->Init(w);

Handle(ShapeFix_Wire) wrFxr = new ShapeFix_Wire;
wrFxr->Load(wrDta);
wrFxr->ClosedWireMode() = Standard_True;
if(!wrFxr->FixReorder())
cout << " # reordering failed\n";
if(!wrFxr->FixConnected(1.e-3))
cout << " # fix connected failed\n";
if(!wrFxr->FixClosed(1.e-3))
cout << " # fix closed failed\n";
}
[/code ****************************************]

Guess what the output of this section is?
# reordering failed
# fix connected failed
# fix closed failed

But why? I have six edges and no free vertices. Attached you'll find the constructed wire (wr.rle).
Any ideas?

Thanks,

Dennis

Attachments: 
Evgeny Lodyzhehsky's picture

Dear Dennis G.

The wire wr.rle is wrong.
It can not be closed, because
1. it contains the pair of linear edges that should be removed;
2. it does not contain other pair of linear edges that should be added to the wire;
Use Draw command "pcurve" to make sure in the facts above (if you want of course)

The hopes that the tricks as ShapeExtend_WireData/ShapeFix_Wire, etc. can help is quite baseless. The usage of tools like that is the last resort for shapes that are
at least correct with topological point of view. Your case wr.rle is not correct.