BRepProj_Projection of a wire which is already lying on the face => does not work

Hi,

I have a simple wire (line) and a face. Now I try to project the wire onto the face (BRepProj_Projection). "IsDone" returns true and the resulting wire is correct. Wonderful.

But... sometimes "IsDone" returns false. IMHO this occurs, if the wire already lies on the face. So I tried to force this situation by projecting the result from the first projection on the same face. If I use the appended face.brep, the second projection returns IsDone=false.

How can I distinguish between
"the wire cannot be projected, because there is no result"
and
"the wire cannot be projected, because it already lies on the face"
?

BTW: if I use a plane for the face, the second projection returns IsDone=true. :-/

Here is my code (OCCT 6.6.0):

Handle_V3d_View view = ui.qOCViewer->getV3DView();
Handle_AIS_InteractiveContext context = ui.qOCViewer->getContext();
context->SetDisplayMode(AIS_Shaded);

gp_Pnt p1(382, -300, 100);
gp_Pnt p2(382, 300, 100);
gp_Pnt pMid = p1.Translated(gp_Vec(p1, p2).Scaled(0.5));
addToView(pMid);
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(p1, p2);
context->Display(new AIS_Shape(edge));

gp_Dir direction(0,0,1);

TopoDS_Face face;
bool usePlane = false;
if (usePlane)
{
gp_Pnt pnt = pMid.Translated(gp_Vec(0,0,-100));
gp_Pln plane(pnt, direction);
face = BRepBuilderAPI_MakeFace(plane, -50, 50, -50, 50);
}
else
{
BRep_Builder builder;
TopoDS_Shape importedShape;
Standard_Boolean ok = BRepTools::Read(importedShape, "face.brep", builder);
if (!ok )
{
throw std::exception("Cannot load face");
}
for(TopExp_Explorer ex(importedShape, TopAbs_FACE, TopAbs_SHAPE); ex.More(); ex.Next())
{
face = TopoDS::Face(ex.Current());
}
}
if (face.IsNull())
{
throw std::exception("face is null");
}
context->Display(new AIS_Shape(face));

bool done1 = false;
bool done2 = false;
TopoDS_Shape resultShape;
BRepProj_Projection projector1(edge, face, direction);
if (projector1.IsDone())
{
done1 = true;
resultShape = projector1.Current();// Shape();
}
else
{
direction.Reverse();
BRepProj_Projection projector2(edge, face, direction);
if (projector2.IsDone())
{
done2 = true;
resultShape = projector2.Current();// Shape();
}
}
log(QString("done1 == %0; done2 == %1").arg(done1).arg(done2));
if (done1 || done2)
{
context->Display(new AIS_Shape(resultShape));
}

bool done3 = false;
bool done4 = false;
TopoDS_Shape resultShape2;
BRepProj_Projection projector3(resultShape, face, direction);
if (projector3.IsDone())
{
done3 = true;
resultShape2 = projector3.Current();// Shape();
}
else
{
direction.Reverse();
BRepProj_Projection projector4(resultShape, face, direction);
if (projector4.IsDone())
{
done4 = true;
resultShape2 = projector4.Current();// Shape();
}
}
log(QString("done3 == %0; done4 == %1").arg(done3).arg(done4));
if (done3 || done4)
{
context->Display(new AIS_Shape(resultShape2));
}

Thorsten H's picture

I replaced BRepProj_Projection by BRepOffsetAPI_NormalProjection. But with BRepOffsetAPI_NormalProjection I cannot set the projection direction. BRepOffsetAPI_NormalProjection always projects in the direction of the normal (normal of what? The face? The edge? A Point? What point?).

Mauro Mariotti's picture

Normal to the face, as if each point in the wire were projected normally onto the face.

If the wire lies on it, the theoretical result should be the same as with cylindrical projection, but the algorithm is completely different.

Bye.
Mauro

Thorsten H's picture

I looked at the source of "BRepProj_Projection" (cylindrical projection). Seems like the edge/wire is sweeped (BRepSweep_Prism) and after that sectioned with the face by calling "BRepAlgo_Section". I reproduced the single steps in my own code and it seems that "BRepAlgo_Section" does not work.

In another thread (http://www.opencascade.org/org/forum/thread_23624/?forum=3) the forum supervisor said, "BRepAlgo_Section" is deprecated and not maintained any longer. One should use the "BRepAlgoAPI" Version. So I replaced BRepAlgo_Section by BRepAlgoAPI_Section. It takes much longer, but it works.

One Question remains: why "BRepProj_Projection" uses the old, unmaintained Version of the section algorithm?

Mauro Mariotti's picture

I would like to know too.
In our version of OpenCASCADE we have done the same.

Thorsten H's picture

@Forum supervisor:
Seems to be a bug in Opencascade. The method BuildSection violates its "purpose" mentioned in the comment:

//=======================================================================
//function : BuildSection
//purpose : Cuts theShape by theTool using BRepAlgoAPI_Section and
// stores result as set of connected wires and compound
//=======================================================================

void BRepProj_Projection::BuildSection (const TopoDS_Shape& theShape,
const TopoDS_Shape& theTool)
{
...
// build section computing pcurves on the shape
//BRepAlgoAPI_Section aSectionTool (aShape, theTool, Standard_False);
BRepAlgo_Section aSectionTool (aShape, theTool, Standard_False);
...
}

P G's picture

Is it documented in OCC bug tracker ??
Forum supervisor please respond

Forum supervisor's picture

Dear PG,
Yes, it is documented (in customer's project section).
The initial attempt to replace the old BRepAlgo_Section by BRepAlgoAPI_Section was not successful, because it lead to a) performance degradation and b) additional bug which still is not fixed.
After solving the mentioned problems it (old algorithm) will be replaced by new one.
Best regards

P G's picture

Dear Forum Supervisor,
thanks for the update.
regards
PG