BOPTColStd_Failure during BRepAlgoAPI_Cut operation

I am experiencing an ocasional failure in BRepAlgoAPI_Cut operations on simple solids. I'm using Windows VS2005 and OCC6.3. The VS output window shows a First-chance exception ..: BOPTColStd_Failure. This does not happen often and does not happen on shapes of any significant complexity as they are all simple extruded faces. Before I spend hours tracing down into the library I thought I would ask if anyone has seen this message/behavior before. I searched the forms and net for a mention of BOPTColStd_Failure and found only the usual OCC documentation.
Tim

Thomas Paviot's picture

Hi Tim,

It's hard to answer your question in general terms. Could it be possible to have a bit more information about your specific problem, especially the shapes you're try to cut? Although they are 'simple', there might be several issues leading to the BOPColStd_Failure: shapes are not intersecting, tangent faces etc. If you manage to provide a simple test case, you can help to point out a bug.

Best Regards,

Thomas

tmay's picture

Thomas,
My application is a full CAD system for a vertical market application - making it difficult to carve out a sample. The problem occurs intermitently. But once a particular solid has a problem, it is reproducable.

I'll have to augment my app with a capture mechanisim to grab the specific shape geometries involved and then wrap that in a simple sample. FWIW, the two case you mentioned do not seem to be an issue.

Non-Intersection:
BTW, calling BOPAlgoAPI_Cut on two parts that do not intersect does not cause a BOPColStd_Failure. I always check that the operation has completed. ex:
BRepAlgoAPI_Cut CutOp(pAssyShape,m_FinalShape);
if(CutOp.IsDone())
{ //Save new shape from cut operation CutOp.Shape()
pAssyComponent->m_FinalShape = CutOp.Shape();
}
Failure to check IsDone() and a subsequent use of the Shape returned from a failed cut operation will result in an error (as expected).

Tangency:
Can you illuminate me on the particulars of the tangent problem you mentioned? I have seen a couple of references to this on the forum but believed this issue came up only on complex curved surface intersections. FWIW, the solids demonstrating this issue in my applciation are simple "flat" extrusions usually intersecting at 90 degress with one shape cutting completly through the other.

Thanks for your interest and I will put the time into pulling a sample together as this problem is a show stopper for our application.

Tim

tmay's picture

Thomas,
Here is code that reproduces the problem. I think I have found the reason for the issue. My CAD component is producing some bezier curves segments that have pole points like this (where the first, second and third are all the same):
aPoles(1) = gp_Pnt(284,83,0);
aPoles(2) = gp_Pnt(284,83,0);
aPoles(3) = gp_Pnt(284,83,0);
aPoles(4) = gp_Pnt(285,83,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
This is clearly not optimum and if you remove these curves (by adjusting the preceeding or following segment intersection points) the cut problem goes away.

As I understand Bezier curves this construction is valid but unusual and can be replaced with a simple line segment.

Obviously this is a problem I can check for and fix on the CAD side and never feed OCC a curve of this form. The sample code snippet below shows how the error can be duplicated. I don't know if OCC should check for and handle this kind of curve input so I'm not sure if this can be considered a bug in OCC. It is clearly one more of many found in the CAD component I'm using.

//Component: Part1
gp_Ax2 Part1Pin_Ax2 = gp_Ax2(gp_Pnt(78,559,0),gp::DZ(),gp_Dir(gp_Vec(gp_Pnt(78,559,0),gp_Pnt(78,503,0))));
gp_Trsf Part1_Trsf;
TopoDS_Shape Part1_Shape;
{
BRepBuilderAPI_MakeWire Shape_Wire;
Handle(Geom_BezierCurve) aCurve = NULL;
//Segment 1
TColgp_Array1OfPnt aPoles(1,4);
aPoles(1) = gp_Pnt(188,481,0);
aPoles(2) = gp_Pnt(247,481,0);
aPoles(3) = gp_Pnt(297,481,0);
aPoles(4) = gp_Pnt(378,468,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 2
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(gp_Pnt(378,468,0),gp_Pnt(388,741,0)));
//Segment 3
aPoles(1) = gp_Pnt(388,741,0);
aPoles(2) = gp_Pnt(249,723,0);
aPoles(3) = gp_Pnt(168,723,0);
aPoles(4) = gp_Pnt(72,664,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 4
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(gp_Pnt(72,664,0),gp_Pnt(72,494,0)));
//Segment 5
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(gp_Pnt(72,494,0),gp_Pnt(188,481,0)));
//Make Part1 solid
Part1_Shape = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(Shape_Wire),gp_Vec(0,0,10));
//Position Part1 in scene
gp_Ax2 Part1ParentPin_Ax2 = gp_Ax2(gp_Pnt(0,0,0),gp::DZ(),gp::DY()); //Root in scene
gp_Trsf T1; //Transformation required to move child part to parent part connection
T1.SetDisplacement(gp_Ax3(Part1Pin_Ax2),gp_Ax3(Part1ParentPin_Ax2)); //Move shape to root
gp_Trsf T2; //Transformation required to rotate child part around child pin
T2.SetRotation(gp_Ax1(Part1Pin_Ax2.Location(),Part1Pin_Ax2.XDirection()),0.0);
Part1_Trsf = T1*T2;
Part1_Shape.Location(TopLoc_Location(Part1_Trsf));
}

//Component: Part2 -- aproximate circle -- With screwy segments that cause the problem

gp_Ax2 Part2ParentPin_Ax2 = Part1Pin_Ax2;
Part2ParentPin_Ax2.Transform(Part1_Trsf); //Find final location of parent pin in positioned parent part
gp_Ax2 Part2Pin_Ax2 = gp_Ax2(gp_Pnt(284,188,10),gp::DZ(),gp_Dir(gp_Vec(gp_Pnt(284,188,10),gp_Pnt(284,113,0))));
gp_Trsf Part2_Trsf;
TopoDS_Shape Part2_Shape;
{
BRepBuilderAPI_MakeWire Shape_Wire;
Handle(Geom_BezierCurve) aCurve = NULL;
TColgp_Array1OfPnt aPoles(1,4);
//Segment 1
aPoles(1) = gp_Pnt(284,295,0);
aPoles(2) = gp_Pnt(225,295,0);
aPoles(3) = gp_Pnt(176,247,0);
aPoles(4) = gp_Pnt(176,189,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 2
aPoles(1) = gp_Pnt(176,189,0);
aPoles(2) = gp_Pnt(176,131,0);
aPoles(3) = gp_Pnt(225,83,0);
aPoles(4) = gp_Pnt(284,83,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 3
aPoles(1) = gp_Pnt(284,83,0);
aPoles(2) = gp_Pnt(284,83,0);
aPoles(3) = gp_Pnt(284,83,0);
aPoles(4) = gp_Pnt(285,83,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 4
aPoles(1) = gp_Pnt(285,83,0);
//aPoles(1) = gp_Pnt(284,83,0);
aPoles(2) = gp_Pnt(344,83,0);
aPoles(3) = gp_Pnt(393,131,0);
aPoles(4) = gp_Pnt(393,189,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 5
aPoles(1) = gp_Pnt(393,189,0);
aPoles(2) = gp_Pnt(393,247,0);
aPoles(3) = gp_Pnt(344,295,0);
aPoles(4) = gp_Pnt(285,295,0);
//aPoles(4) = gp_Pnt(284,295,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Segment 6
aPoles(1) = gp_Pnt(285,295,0);
aPoles(2) = gp_Pnt(285,295,0);
aPoles(3) = gp_Pnt(285,295,0);
aPoles(4) = gp_Pnt(284,295,0);
aCurve = new Geom_BezierCurve(aPoles);
Shape_Wire.Add(BRepBuilderAPI_MakeEdge(aCurve));
//Make part2 solid
Part2_Shape = BRepPrimAPI_MakePrism(BRepBuilderAPI_MakeFace(Shape_Wire),gp_Vec(0,0,10));
//Position Part2 in scene
gp_Trsf T1; //Transformation required to move child part to parent part connection
T1.SetDisplacement(gp_Ax3(Part2Pin_Ax2),gp_Ax3(Part2ParentPin_Ax2)); //Move shape to parent part pin
gp_Trsf T2; //Transformation required to rotate child part around child pin
T2.SetRotation(gp_Ax1(Part2Pin_Ax2.Location(),Part2Pin_Ax2.XDirection()),PI/2.0);
Part2_Trsf = T1*T2;
Part2_Shape.Location(TopLoc_Location(Part2_Trsf));
}

//Perform Cut
if(!Part1_Shape.IsNull() && !Part2_Shape.IsNull())
{
BRepAlgoAPI_Cut CutOp(Part2_Shape,Part1_Shape);
if(CutOp.IsDone())
Part2_Shape = CutOp.Shape();
}

//Display Parts
{//Part1
Handle(AIS_Shape) My_AIS_Shape = new AIS_Shape(Part1_Shape);
myAISContext->SetColor(My_AIS_Shape,Quantity_NOC_AZURE);
myAISContext->SetMaterial(My_AIS_Shape,Graphic3d_NOM_PLASTIC);
myAISContext->SetTransparency(My_AIS_Shape,0.8); //Make transparent so we can see cut
myAISContext->SetDisplayMode(My_AIS_Shape,1);
myAISContext->Display(My_AIS_Shape);
}

{//Part2
Handle(AIS_Shape) My2_AIS_Shape = new AIS_Shape(Part2_Shape);
myAISContext->SetColor(My2_AIS_Shape,Quantity_NOC_AZURE);
myAISContext->SetMaterial(My2_AIS_Shape,Graphic3d_NOM_PLASTIC);
myAISContext->SetTransparency(My2_AIS_Shape,0.0);
myAISContext->SetDisplayMode(My2_AIS_Shape,1);
myAISContext->Display(My2_AIS_Shape);
}

myView->SetComputedMode (Standard_False);

myView->FitAll();
myView->Update();

Thanks,
Tim