0032214: Modeling Algorithms - 2d Offset produces wrong result

Add new option to convert input contours into ones consisting of 2D circular arcs and 2D linear segments only.

Update documentation
This commit is contained in:
jgv
2022-08-22 12:15:42 +03:00
committed by smoskvin
parent 05cfce4d83
commit b71cb85f67
18 changed files with 1830 additions and 12 deletions

View File

@@ -17,9 +17,12 @@
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAlgo.hxx>
#include <BRepAlgo_FaceRestrictor.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepLib.hxx>
#include <BRepOffsetAPI_MakeOffset.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <Extrema_ExtPS.hxx>
@@ -41,6 +44,49 @@
static Standard_Boolean AffichSpine = Standard_False;
#endif
static Standard_Boolean NeedsConvertion (const TopoDS_Wire& theWire)
{
TopoDS_Iterator anIter (theWire);
for (; anIter.More(); anIter.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge (anIter.Value());
BRepAdaptor_Curve aBAcurve (anEdge);
GeomAbs_CurveType aType = aBAcurve.GetType();
if (aType != GeomAbs_Line &&
aType != GeomAbs_Circle)
return Standard_True;
}
return Standard_False;
}
static TopoDS_Face ConvertFace (const TopoDS_Face& theFace,
const Standard_Real theAngleTolerance)
{
TopAbs_Orientation anOr = theFace.Orientation();
TopoDS_Face aFace = theFace;
aFace.Orientation (TopAbs_FORWARD);
TopoDS_Face aNewFace = TopoDS::Face (aFace.EmptyCopied());
BRep_Builder aBB;
TopoDS_Iterator anIter (aFace);
for (; anIter.More(); anIter.Next())
{
TopoDS_Wire aWire = TopoDS::Wire (anIter.Value());
if (NeedsConvertion (aWire))
{
TopAbs_Orientation anOrOfWire = aWire.Orientation();
aWire = BRepAlgo::ConvertWire (aWire, theAngleTolerance, aFace);
BRepLib::BuildCurves3d (aWire);
aWire.Orientation (anOrOfWire);
}
aBB.Add (aNewFace, aWire);
}
aNewFace.Orientation (anOr);
return aNewFace;
}
//=======================================================================
//function : BRepOffsetAPI_MakeOffset
//purpose :
@@ -49,7 +95,8 @@ static Standard_Boolean AffichSpine = Standard_False;
BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset()
: myIsInitialized( Standard_False),
myJoin(GeomAbs_Arc),
myIsOpenResult(Standard_False)
myIsOpenResult(Standard_False),
myIsToApprox(Standard_False)
{
}
@@ -80,6 +127,7 @@ void BRepOffsetAPI_MakeOffset::Init(const TopoDS_Face& Spine,
myIsInitialized = Standard_True;
myJoin = Join;
myIsOpenResult = IsOpenResult;
myIsToApprox = Standard_False;
TopExp_Explorer exp;
for (exp.Init(myFace,TopAbs_WIRE); exp.More();exp.Next()) {
myWires.Append(exp.Current());
@@ -99,6 +147,7 @@ BRepOffsetAPI_MakeOffset::BRepOffsetAPI_MakeOffset(const TopoDS_Wire& Spine,
myIsInitialized = Standard_True;
myJoin = Join;
myIsOpenResult = IsOpenResult;
myIsToApprox = Standard_False;
}
//=======================================================================
@@ -113,6 +162,18 @@ void BRepOffsetAPI_MakeOffset::Init(const GeomAbs_JoinType Join,
myIsOpenResult = IsOpenResult;
}
//=======================================================================
//function : SetApprox
//purpose : Set approximation flag
// for convertion input contours into ones consisting of
// 2D circular arcs and 2D linear segments only
//=======================================================================
void BRepOffsetAPI_MakeOffset::SetApprox(const Standard_Boolean ToApprox)
{
myIsToApprox = ToApprox;
}
//=======================================================================
//function : BRepOffsetAPI_MakeOffset
//purpose :
@@ -289,6 +350,46 @@ void BRepOffsetAPI_MakeOffset::Perform(const Standard_Real Offset,
try
{
if (myIsToApprox)
{
Standard_Real aTol = 0.01;
if (myFace.IsNull())
{
TopoDS_Face aFace;
Standard_Boolean OnlyPlane = Standard_True;
TopTools_ListIteratorOfListOfShape anItl (myWires);
for (; anItl.More(); anItl.Next())
{
BRepBuilderAPI_MakeFace aFaceMaker (TopoDS::Wire(anItl.Value()), OnlyPlane);
if (aFaceMaker.Error() == BRepBuilderAPI_FaceDone)
{
aFace = aFaceMaker.Face();
break;
}
}
for (anItl.Initialize(myWires); anItl.More(); anItl.Next())
{
const TopoDS_Wire& aWire = TopoDS::Wire(anItl.Value());
if (NeedsConvertion (aWire))
{
TopoDS_Wire aNewWire = BRepAlgo::ConvertWire (aWire, aTol, aFace);
BRepLib::BuildCurves3d (aNewWire);
aNewWire.Orientation (aWire.Orientation());
anItl.ChangeValue() = aNewWire;
}
}
}
else
{
myFace = ConvertFace (myFace, aTol);
BRepLib::BuildCurves3d (myFace);
myWires.Clear();
TopoDS_Iterator anIter (myFace);
for (; anIter.More(); anIter.Next())
myWires.Append (anIter.Value());
}
}
Standard_Integer i = 1;
BRepFill_ListIteratorOfListOfOffsetWire itOW;
TopoDS_Compound Res;

View File

@@ -63,6 +63,11 @@ public:
//! Initialize the evaluation of Offsetting.
Standard_EXPORT void Init (const GeomAbs_JoinType Join = GeomAbs_Arc, const Standard_Boolean IsOpenResult = Standard_False);
//! Set approximation flag
//! for convertion input contours into ones consisting of
//! 2D circular arcs and 2D linear segments only.
Standard_EXPORT void SetApprox (const Standard_Boolean ToApprox);
//! Initializes the algorithm to construct parallels to the wire Spine.
Standard_EXPORT void AddWire (const TopoDS_Wire& Spine);
@@ -96,6 +101,7 @@ private:
Standard_Boolean myLastIsLeft;
GeomAbs_JoinType myJoin;
Standard_Boolean myIsOpenResult;
Standard_Boolean myIsToApprox;
TopoDS_Face myFace;
TopTools_ListOfShape myWires;
BRepFill_ListOfOffsetWire myLeft;