How to fuse face and face by OpenCascade V7.4.0?

Hello.

I am trying to fuse face and face by following codes, but it is not working.

I use OpenCascade version 7.4.0.

BRepBuilderAPI_MakeWire makeCheckWire;
makeCheckWire.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 0.0, 0.0, 0.0 ), gp_Pnt( 0.0, 0.0, 100.0 ) ) );
makeCheckWire.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 0.0, 0.0, 100.0 ), gp_Pnt( 100.0, 0.0, 100.0 ) ) );
makeCheckWire.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 100.0, 0.0, 100.0 ), gp_Pnt( 100.0, 0.0, 0.0 ) ) );
makeCheckWire.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 100.0, 0.0, 0.0 ), gp_Pnt( 0.0, 0.0, 0.0 ) ) );
BRepBuilderAPI_MakeFace makerFace1( makeCheckWire.Wire() );
TopoDS_Face face1 = makerFace1.Face();

BRepBuilderAPI_MakeWire makeCheckWire2;
double dAdjustX = 40.0;
makeCheckWire2.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 0.0, 0.0, 0.0 ), gp_Pnt( 0.0, 0.0, -20.0 ) ) );
makeCheckWire2.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 0.0, 0.0, -20.0 ), gp_Pnt( dAdjustX, 0.0, -20.0 ) ) );
makeCheckWire2.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( dAdjustX, 0.0, -20.0 ), gp_Pnt( dAdjustX, 0.0, 0.0 ) ) );
makeCheckWire2.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( dAdjustX, 0.0, 0.0 ), gp_Pnt( 0.0, 0.0, 0.0 ) ) );
BRepBuilderAPI_MakeFace makerFace2( makeCheckWire2.Wire() );
TopoDS_Face face2 = makerFace2.Face();

BRepAlgoAPI_Fuse fuseShape( face1, face2 );
fuseShape.Build();
TopoDS_Shape shape = fuseShape.Shape();
ShapeUpgrade_UnifySameDomain unif( shape, Standard_True, Standard_True, Standard_False );
unif.Build();
shape = unif.Shape();

When I use OpenCascade version 6.8.0, 2 faces are fused by ShapeUpgrade_UnifySameDomain class.
But After I upgraded OpenCascade version from 6.8.0 to 7.4.0, These  2 faces are not fused.

Do you know how to solve this problem?

Best regards.

Attachments: 
Eugeny's picture

Currently, your faces have different normal directions. Reversing one of your faces will help.

Keito Okajima's picture

Eugeny, thank you for the Information !
I fixed my code like below and It works good.

TopoDS_Face face2 = makerFace2.Face();

TopoDS_Face face2 = makerFace2.Face();
face2 .Reverse();

I have one more question.
In the case of not plane face, how can I know if I should use reverse or not ?

Eugeny's picture

Hello Keito,

You can create a shell from the compound and use the ShapeFix_Shell to fix the face orientation in the shell. Then you can use the UnifySameDom on the fixed shell.

Best regards, Eugeny.

Keito Okajima's picture

Hello Eugeny,

Thank you for your reply.

I tried to make shell and fix this, but I could not connect cylinder face.

Is something wrong?  I used following codes.

TopExp_Explorer expFace;

BRepBuilderAPI_MakeWire makeCheckWire;

TopoDS_Edge edgeArc1 = BRepBuilderAPI_MakeEdge(

                        GC_MakeArcOfCircle( gp_Circ( gp_Ax2(gp_Pnt(0.0,0.0,0.0), gp_Dir(1.0,0.0,0.0)), 5.0 ),

                                            gp_Pnt( 0.0, -5.0, 0.0 ),

                                            gp_Pnt( 0.0, 5.0, 0.0 ),

                                            Standard_False ).Value() );

makeCheckWire.Add( edgeArc1 );

makeCheckWire.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 0.0, -5.0, 0.0 ), gp_Pnt( 0.0, 5.0, 0.0 ) ) );

BRepBuilderAPI_MakeFace makerFace1( makeCheckWire.Wire() );

TopoDS_Face face1 = makerFace1.Face();

TopoDS_Shape shape1 = BRepPrimAPI_MakePrism( face1, gp_Vec( 20.0, 0.0, 0.0 ) ).Shape();

expFace.Init( shape1, TopAbs_FACE );

for( ; expFace.More(); expFace.Next() ){

    TopoDS_Face face = TopoDS::Face( expFace.Current() );

    BRepAdaptor_Surface adapetrSurface( face );

    if( adapetrSurface.GetType() == GeomAbs_Cylinder ){

        face1 = face;

        break;

    }

}

BRepBuilderAPI_MakeWire makeCheckWire2;

TopoDS_Edge edgeArc2 = BRepBuilderAPI_MakeEdge(

                        GC_MakeArcOfCircle( gp_Circ( gp_Ax2(gp_Pnt(0.0,0.0,0.0), gp_Dir(1.0,0.0,0.0)), 5.0 ),

                                            gp_Pnt( 0.0, 5.0, 0.0 ),

                                            gp_Pnt( 0.0, -5.0, 0.0 ),

                                            Standard_False ).Value() );

makeCheckWire2.Add( edgeArc2 );

makeCheckWire2.Add( BRepBuilderAPI_MakeEdge( gp_Pnt( 0.0, -5.0, 0.0 ), gp_Pnt( 0.0, 5.0, 0.0 ) ) );

BRepBuilderAPI_MakeFace makerFace2( makeCheckWire2.Wire() );

TopoDS_Face face2 = makerFace2.Face();

TopoDS_Shape shape2 = BRepPrimAPI_MakePrism( face2, gp_Vec( 20.0, 0.0, 0.0 ) ).Shape();

expFace.Init( shape2, TopAbs_FACE );

for( ; expFace.More(); expFace.Next() ){

    TopoDS_Face face = TopoDS::Face( expFace.Current() );

    BRepAdaptor_Surface adapetrSurface( face );

    if( adapetrSurface.GetType() == GeomAbs_Cylinder ){

        face2 = face;

        break;

    }

}

face2.Reverse(); // for test, reverse face.

BRepAlgoAPI_Fuse fuseShape( face1, face2 );

fuseShape.Build();

TopoDS_Shell shell;

BRep_Builder builder;

builder.MakeShell( shell );

TopExp_Explorer exFace( fuseShape.Shape(), TopAbs_FACE );

for( ; exFace.More(); exFace.Next() ){

    builder.Add( shell, exFace.Current() );

}

ShapeFix_Shell fixShell;

fixShell.FixFaceOrientation( shell, Standard_True, Standard_False );

ShapeUpgrade_UnifySameDomain unif( shell, Standard_True, Standard_True, Standard_False );

unif.Build();

TopoDS_Shape shape = unif.Shape(); // cylinder faces are divied.

Best regards, Keito.

Eugeny's picture

Hello Keito,

Could you please dump the shapes after fuse? You can use either BinTools::Write or BRepTools::Write for that.

One remark for your code - you can use arc edge directly for making the cylindrical face, instead of making the planar face first, making solid and looking for the cylindrical face in that solid.

Here is the draw script which produces the desired result:

circle c1 0 0 0 0 0 1 0 1 0 5
trim c1 c1 0 pi

circle c2 0 0 0 0 0 1 0 1 0 5
trim c2 c2 pi 2*pi

mkedge e1 c1
mkedge e2 c2

prism f1 e1 0 0 20
prism f2 e2 0 0 20

bfuse r f1 f2

shape shell Sh
foreach f [explode r] { add $f shell }

fixshape shell shell
unifysamedom result shell
Keito Okajima's picture

Hello Eugeny,

Thank you for the information and coding advice.

I fixed my code like below, but result is same.

Is something wrong?

~~~~
fuseShape.Build();

TopoDS_Shape shapeTmp = fuseShape.Shape();
BinTools::Write( shapeTmp, "@test" );
BinTools::Read( shapeTmp, "@test" );

TopoDS_Shell shell;
BRep_Builder builder;
builder.MakeShell( shell );
TopExp_Explorer exFace( shapeTmp , TopAbs_FACE );
for( ; exFace.More(); exFace.Next() ){
    builder.Add( shell, exFace.Current() );
}
ShapeFix_Shell fixShell;
fixShell.FixFaceOrientation( shell, Standard_True, Standard_False );
ShapeUpgrade_UnifySameDomain unif( shell, Standard_True, Standard_True, Standard_False );
unif.Build();
TopoDS_Shape shape = unif.Shape(); // cylinder faces are divied.

Best regards, Keito.

Eugeny's picture

I suggested to dump the shapes so you could load it in draw and try to reproduce the issue with unification there. No need to dump and restore it in your code.

Anyway, this looks like an issue in OCCT, so you could register a bug in OCCT mantis bugtracker and contact OCCT Support via the Contact form to advance the issue.

Keito Okajima's picture

Thany you for the imformation.

I will register a bug in OCCT mantis bugtracker.