DiscussionsIssue archiveOCCT:Modeling Algorithms

Archived issue #0023463

Boolean operations provide wrong results for solids with faces formed by bspline surfaces.

CommunityOCCT:Modeling Algorithmsnew0 public notes

Search issues

Description

Boolean operations (common, cut and fuse) on two same solids (one rotated by 90° around the z-axis, see attached Attachment 1 (PNG) for the picture of one of the solids) with faces made of simple bspline surfaces provide wrong results (no new solid is created even though there should be exactly one resulting solid for each of the operations). However, this happens only if both solids have their centers in the same point, if you translate one of the solids a little, boolean operations works fine.

Steps to reproduce

The following code creates the described solids, then performs the boolean operation out checks the result:

  TColgp_Array2OfPnt poles(1, 2, 1, 2);
  poles.SetValue(1, 1, gp_Pnt(0.0, -5.0, 0.0));
  poles.SetValue(2, 1, gp_Pnt(5.0, 0.0, 0.0));
  poles.SetValue(1, 2, gp_Pnt(0.0, 0.0, 5.0));
  poles.SetValue(2, 2, gp_Pnt(0.0, 5.0, 0.0));
  TColStd_Array1OfReal uknots(1, 2);
  uknots.SetValue(1, 0.0);
  uknots.SetValue(2, 1.0);
  TColStd_Array1OfInteger umults(1, 2);
  umults.SetValue(1, 2);
  umults.SetValue(2, 2);
  TColStd_Array1OfReal vknots(1, 2);
  vknots.SetValue(1, 0.0);
  vknots.SetValue(2, 1.0);
  TColStd_Array1OfInteger vmults(1, 2);
  vmults.SetValue(1, 2);
  vmults.SetValue(2, 2);

  Handle(Geom_BSplineSurface) surface = new Geom_BSplineSurface(poles, uknots, vknots, umults, vmults, 1, 1);

  BRepBuilderAPI_MakeFace face1Builder(surface, 0.0);
  assert(face1Builder.IsDone());
  
  BRepBuilderAPI_MakeFace face2Builder(Handle(Geom_Surface)::DownCast(surface->Mirrored(gp_Ax2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0)))), 0.0);
  assert(face2Builder.IsDone());

  BRepBuilderAPI_MakeFace face3Builder(Handle(Geom_Surface)::DownCast(surface->Mirrored(gp_Ax2(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)))), 0.0);
  assert(face3Builder.IsDone());

  BRepBuilderAPI_MakeFace face4Builder(Handle(Geom_Surface)::DownCast(surface->Mirrored(gp_Ax1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 1.0, 0.0)))), 0.0);
  assert(face4Builder.IsDone());

  BRepBuilderAPI_Sewing shellBuilder;
  shellBuilder.Add(face1Builder.Shape());
  shellBuilder.Add(face2Builder.Shape());
  shellBuilder.Add(face3Builder.Shape());
  shellBuilder.Add(face4Builder.Shape());
  shellBuilder.Perform();
  TopoDS_Shell shell = TopoDS::Shell(shellBuilder.SewedShape());

  BRepBuilderAPI_MakeSolid solidBuilder(shell);
  assert(solidBuilder.IsDone());
  TopoDS_Solid solid1 = solidBuilder.Solid();

  gp_Trsf rotation;
  rotation.SetRotation(gp_Ax1(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), M_PI / 2.0); // Change the rotation a little and boolean operations will start to work.
  gp_Trsf translation;
  translation.SetTranslation(gp_Vec(0.0, 0.0, 0.0)); // Change the translation to be non-zero and boolean operations will start to work.

  BRepBuilderAPI_Transform rotate(solid1, rotation);
  assert(rotate.IsDone());

  BRepBuilderAPI_Transform translate(rotate.Shape(), translation);
  assert(translate.IsDone());

  TopoDS_Solid solid2 = TopoDS::Solid(translate.Shape());

  BRepAlgo_Common common(solid1, solid2); // Fuse and cut also provide wrong results for this case.
  assert(common.IsDone());
  TopoDS_Shape shape = common.Shape();
  TopExp_Explorer exp(shape, TopAbs_SOLID);
  unsigned int count = 0;
  for ( ; exp.More(); exp.Next())
  {
    ++count;
  }
  std::cout << "Common created " << count << " of solids." << std::endl; // This prints zero, but the common should create one new solid.

Public activity

No public notes

Participants are labeled by their role within this record.