mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
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:
parent
05cfce4d83
commit
b71cb85f67
@ -326,7 +326,8 @@ The <i>Geom2dConvert</i> package provides the following:
|
||||
* a global function which is used to construct a BSpline curve from a bounded curve based on a 2D curve from the Geom2d package,
|
||||
* a splitting algorithm which computes the points at which a 2D BSpline curve should be cut in order to obtain arcs with the same degree of continuity,
|
||||
* global functions used to construct the BSpline curves created by this splitting algorithm, or by other types of segmentation of the BSpline curve,
|
||||
* an algorithm which converts a 2D BSpline curve into a series of adjacent Bezier curves.
|
||||
* an algorithm which converts a 2D BSpline curve into a series of adjacent Bezier curves,
|
||||
* an algorithm which converts an arbitrary 2D curve into a series of adjacent 2D circular arcs and 2D linear segments.
|
||||
|
||||
The <i>GeomConvert</i> package also provides the following:
|
||||
|
||||
|
@ -15,8 +15,13 @@
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Curve2d.hxx>
|
||||
#include <BRepAlgo.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
#include <BRepLib_MakeEdge.hxx>
|
||||
@ -25,10 +30,13 @@
|
||||
#include <ElCLib.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_TrimmedCurve.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2dConvert_ApproxArcsSegments.hxx>
|
||||
#include <GeomAbs_CurveType.hxx>
|
||||
#include <GeomConvert.hxx>
|
||||
#include <GeomConvert_CompCurveToBSplineCurve.hxx>
|
||||
#include <GeomLProp.hxx>
|
||||
#include <NCollection_Vector.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <ShapeFix_Shape.hxx>
|
||||
@ -40,6 +48,7 @@
|
||||
#include <TColStd_SequenceOfBoolean.hxx>
|
||||
#include <TColStd_SequenceOfReal.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
@ -47,6 +56,166 @@
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
|
||||
// The minimal tolerance of approximation (edges can be defined with yet smaller tolerance)
|
||||
static const Standard_Real MINIMAL_TOLERANCE = 0.0001;
|
||||
|
||||
namespace {
|
||||
|
||||
struct OrientedCurve
|
||||
{
|
||||
Handle(Geom2d_TrimmedCurve) Curve;
|
||||
Standard_Boolean IsReverse;
|
||||
inline gp_Pnt2d Point (const Standard_Boolean isEnd) const
|
||||
{
|
||||
if (isEnd == IsReverse)
|
||||
return Curve->StartPoint();
|
||||
return Curve->EndPoint();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ConvertWire
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
TopoDS_Wire BRepAlgo::ConvertWire(const TopoDS_Wire& theWire,
|
||||
const Standard_Real theAngleTol,
|
||||
const TopoDS_Face& theFace)
|
||||
{
|
||||
TopoDS_Wire aResult;
|
||||
Standard_Real aMaxTol(0.);
|
||||
const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
|
||||
NCollection_Vector<OrientedCurve> vecCurve;
|
||||
|
||||
BRepTools_WireExplorer anExpE(theWire, theFace);
|
||||
// Explore the edges in the current wire, in their connection order
|
||||
for (; anExpE.More(); anExpE.Next()) {
|
||||
const TopoDS_Edge& anEdge = anExpE.Current();
|
||||
BRepAdaptor_Curve2d aCurve(anEdge, theFace);
|
||||
Standard_Real aTol = BRep_Tool::Tolerance(anEdge);
|
||||
if (aTol < MINIMAL_TOLERANCE)
|
||||
aTol = MINIMAL_TOLERANCE;
|
||||
if (aTol > aMaxTol)
|
||||
aMaxTol = aTol;
|
||||
Geom2dConvert_ApproxArcsSegments anAlgo(aCurve, aTol, theAngleTol);
|
||||
const TColGeom2d_SequenceOfCurve& aResultApprox = anAlgo.GetResult();
|
||||
|
||||
// Form the array of approximated elementary curves
|
||||
if (anEdge.Orientation() == TopAbs_REVERSED) {
|
||||
for (Standard_Integer iCrv = aResultApprox.Length(); iCrv > 0 ; iCrv--) {
|
||||
const Handle(Geom2d_Curve)& aCrv = aResultApprox(iCrv);
|
||||
if (aCrv.IsNull() == Standard_False) {
|
||||
OrientedCurve& anOCurve = vecCurve.Append(OrientedCurve());
|
||||
anOCurve.Curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCrv);
|
||||
anOCurve.IsReverse = Standard_True;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Standard_Integer iCrv = 1; iCrv <= aResultApprox.Length(); iCrv++) {
|
||||
const Handle(Geom2d_Curve)& aCrv = aResultApprox(iCrv);
|
||||
if (aCrv.IsNull() == Standard_False) {
|
||||
OrientedCurve& anOCurve = vecCurve.Append(OrientedCurve());
|
||||
anOCurve.Curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCrv);
|
||||
anOCurve.IsReverse = Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vecCurve.Length() > 0)
|
||||
{
|
||||
// Build the first vertex
|
||||
BRep_Builder aVBuilder;
|
||||
gp_Pnt2d aPnt[2] = {
|
||||
vecCurve(0).Point(Standard_False),
|
||||
vecCurve(vecCurve.Length() - 1).Point(Standard_True)
|
||||
};
|
||||
Standard_Real aDist = aPnt[0].Distance(aPnt[1]);
|
||||
if (aDist > aMaxTol + Precision::Confusion())
|
||||
aDist = Precision::Confusion();
|
||||
else {
|
||||
aDist = 0.5 * aDist + Precision::Confusion();
|
||||
aPnt[0] = 0.5 * (aPnt[0].XY() + aPnt[1].XY());
|
||||
}
|
||||
gp_Pnt aPnt3d;
|
||||
aSurf->D0(aPnt[0].X(), aPnt[0].Y(), aPnt3d);
|
||||
TopoDS_Vertex aFirstVertex;
|
||||
aVBuilder.MakeVertex(aFirstVertex, aPnt3d, aDist);
|
||||
|
||||
// Loop creating edges
|
||||
BRepBuilderAPI_MakeWire aMkWire;
|
||||
TopoDS_Edge anEdgeRes;
|
||||
TopoDS_Vertex aVertex = aFirstVertex;
|
||||
for (Standard_Integer iCrv = 0; iCrv < vecCurve.Length(); iCrv++) {
|
||||
const OrientedCurve& anOCurve = vecCurve(iCrv);
|
||||
TopoDS_Vertex aNextVertex;
|
||||
aPnt[0] = anOCurve.Point(Standard_True);
|
||||
if (iCrv == vecCurve.Length() - 1) {
|
||||
aPnt[1] = vecCurve(0).Point(Standard_False);
|
||||
aDist = aPnt[0].Distance(aPnt[1]);
|
||||
if (aDist > aMaxTol + Precision::Confusion()) {
|
||||
aSurf->D0(aPnt[0].X(), aPnt[0].Y(), aPnt3d);
|
||||
aVBuilder.MakeVertex(aNextVertex, aPnt3d, Precision::Confusion());
|
||||
} else {
|
||||
aNextVertex = aFirstVertex;
|
||||
}
|
||||
} else {
|
||||
aPnt[1] = vecCurve(iCrv + 1).Point(Standard_False);
|
||||
aDist = 0.5 * (aPnt[0].Distance(aPnt[1])) + Precision::Confusion();
|
||||
aPnt[0] = 0.5 * (aPnt[0].XY() + aPnt[1].XY());
|
||||
aSurf->D0(aPnt[0].X(), aPnt[0].Y(), aPnt3d);
|
||||
aVBuilder.MakeVertex(aNextVertex, aPnt3d, aDist);
|
||||
}
|
||||
const Standard_Real aParam[2] = {
|
||||
anOCurve.Curve->FirstParameter(),
|
||||
anOCurve.Curve->LastParameter()
|
||||
};
|
||||
if (anOCurve.IsReverse) {
|
||||
BRepBuilderAPI_MakeEdge aMkEdge(anOCurve.Curve, aSurf, aNextVertex,
|
||||
aVertex, aParam[0], aParam[1]);
|
||||
anEdgeRes = aMkEdge.Edge();
|
||||
anEdgeRes.Orientation(TopAbs_REVERSED);
|
||||
} else {
|
||||
BRepBuilderAPI_MakeEdge aMkEdge(anOCurve.Curve, aSurf, aVertex,
|
||||
aNextVertex, aParam[0], aParam[1]);
|
||||
anEdgeRes = aMkEdge.Edge();
|
||||
}
|
||||
aVertex = aNextVertex;
|
||||
aMkWire.Add(anEdgeRes);
|
||||
}
|
||||
|
||||
if (aMkWire.IsDone())
|
||||
aResult = aMkWire.Wire();
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ConvertFace
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
TopoDS_Face BRepAlgo::ConvertFace (const TopoDS_Face& theFace,
|
||||
const Standard_Real theAngleTolerance)
|
||||
{
|
||||
TopoDS_Face aResult;
|
||||
const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace);
|
||||
BRepBuilderAPI_MakeFace aMkFace(aSurf,Precision::Confusion());
|
||||
|
||||
TopExp_Explorer anExp(theFace, TopAbs_WIRE);
|
||||
for (; anExp.More(); anExp.Next()) {
|
||||
const TopoDS_Wire& aWire = TopoDS::Wire(anExp.Current());
|
||||
const TopoDS_Wire aNewWire = ConvertWire(aWire, theAngleTolerance, theFace);
|
||||
aMkFace.Add(aNewWire);
|
||||
}
|
||||
if (aMkFace.IsDone()) {
|
||||
aResult = aMkFace.Face();
|
||||
}
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ConcatenateWire
|
||||
//purpose :
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
class TopoDS_Wire;
|
||||
class TopoDS_Edge;
|
||||
class TopoDS_Face;
|
||||
class TopoDS_Shape;
|
||||
|
||||
|
||||
@ -43,6 +44,28 @@ public:
|
||||
//! Junction points between edges of wire may be sharp,
|
||||
//! resulting curve of the resulting edge may be C0.
|
||||
Standard_EXPORT static TopoDS_Edge ConcatenateWireC0 (const TopoDS_Wire& Wire);
|
||||
|
||||
//! Method of wire conversion, calls BRepAlgo_Approx internally.
|
||||
//! @param theWire
|
||||
//! Input Wire object.
|
||||
//! @param theAngleTolerance
|
||||
//! Angle (in radians) defining the continuity of the wire: if two vectors
|
||||
//! differ by less than this angle, the result will be smooth (zero angle of
|
||||
//! tangent lines between curve elements).
|
||||
//! @return
|
||||
//! The new TopoDS_Wire object consisting of edges each representing an arc
|
||||
//! of circle or a linear segment. The accuracy of conversion is defined
|
||||
//! as the maximal tolerance of edges in theWire.
|
||||
static Standard_EXPORT TopoDS_Wire ConvertWire
|
||||
(const TopoDS_Wire& theWire,
|
||||
const Standard_Real theAngleTolerance,
|
||||
const TopoDS_Face& theFace);
|
||||
|
||||
//! Method of face conversion. The API corresponds to the method ConvertWire.
|
||||
//! This is a shortcut for calling ConvertWire() for each wire in theFace.
|
||||
static Standard_EXPORT TopoDS_Face ConvertFace
|
||||
(const TopoDS_Face& theFace,
|
||||
const Standard_Real theAngleTolerance);
|
||||
|
||||
//! Checks if the shape is "correct". If not, returns
|
||||
//! <Standard_False>, else returns <Standard_True>.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1530,10 +1530,23 @@ Standard_Integer mkoffset(Draw_Interpretor& di,
|
||||
char name[100];
|
||||
|
||||
BRepOffsetAPI_MakeOffset Paral;
|
||||
|
||||
Standard_Boolean ToApprox = Standard_False;
|
||||
GeomAbs_JoinType theJoinType = GeomAbs_Arc;
|
||||
if (n >= 6 && strcmp(a[5], "i") == 0)
|
||||
theJoinType = GeomAbs_Intersection;
|
||||
Paral.Init(theJoinType);
|
||||
|
||||
Standard_Integer anIndArg = 6;
|
||||
if (n >= 6)
|
||||
{
|
||||
if (strcmp(a[5], "-approx") == 0)
|
||||
{
|
||||
ToApprox = Standard_True;
|
||||
anIndArg++;
|
||||
}
|
||||
|
||||
if (n >= anIndArg && strcmp(a[anIndArg-1], "i") == 0)
|
||||
theJoinType = GeomAbs_Intersection;
|
||||
}
|
||||
|
||||
TopoDS_Shape Base = DBRep::Get(a[2],TopAbs_FACE);
|
||||
|
||||
if ( Base.IsNull())
|
||||
@ -1553,6 +1566,7 @@ Standard_Integer mkoffset(Draw_Interpretor& di,
|
||||
Base.Orientation(TopAbs_FORWARD);
|
||||
Paral.Init(TopoDS::Face(Base), theJoinType);
|
||||
}
|
||||
Paral.SetApprox (ToApprox);
|
||||
|
||||
Standard_Real U, dU;
|
||||
Standard_Integer Nb;
|
||||
@ -1560,8 +1574,8 @@ Standard_Integer mkoffset(Draw_Interpretor& di,
|
||||
Nb = Draw::Atoi(a[3]);
|
||||
|
||||
Standard_Real Alt = 0.;
|
||||
if ( n == 7)
|
||||
Alt = Draw::Atof(a[6]);
|
||||
if (n > anIndArg)
|
||||
Alt = Draw::Atof(a[anIndArg]);
|
||||
|
||||
Standard_Integer Compt = 1;
|
||||
|
||||
@ -1598,16 +1612,30 @@ Standard_Integer openoffset(Draw_Interpretor& di,
|
||||
char name[100];
|
||||
|
||||
BRepOffsetAPI_MakeOffset Paral;
|
||||
|
||||
Standard_Boolean ToApprox = Standard_False;
|
||||
GeomAbs_JoinType theJoinType = GeomAbs_Arc;
|
||||
if (n == 6 && strcmp(a[5], "i") == 0)
|
||||
theJoinType = GeomAbs_Intersection;
|
||||
Paral.Init(theJoinType, Standard_True);
|
||||
|
||||
Standard_Integer anIndArg = 6;
|
||||
if (n >= 6)
|
||||
{
|
||||
if (strcmp(a[5], "-approx") == 0)
|
||||
{
|
||||
ToApprox = Standard_True;
|
||||
anIndArg++;
|
||||
}
|
||||
|
||||
if (n >= anIndArg && strcmp(a[anIndArg-1], "i") == 0)
|
||||
theJoinType = GeomAbs_Intersection;
|
||||
}
|
||||
|
||||
TopoDS_Shape Base = DBRep::Get(a[2] ,TopAbs_FACE);
|
||||
|
||||
if ( Base.IsNull())
|
||||
{
|
||||
Base = DBRep::Get(a[2], TopAbs_WIRE);
|
||||
if (Base.IsNull()) return 1;
|
||||
Paral.Init(theJoinType, Standard_True);
|
||||
Paral.AddWire(TopoDS::Wire(Base));
|
||||
}
|
||||
else
|
||||
@ -1615,6 +1643,7 @@ Standard_Integer openoffset(Draw_Interpretor& di,
|
||||
Base.Orientation(TopAbs_FORWARD);
|
||||
Paral.Init(TopoDS::Face(Base), theJoinType, Standard_True);
|
||||
}
|
||||
Paral.SetApprox (ToApprox);
|
||||
|
||||
Standard_Real U, dU;
|
||||
Standard_Integer Nb;
|
||||
@ -1755,6 +1784,72 @@ Standard_Integer edgeintersector(Draw_Interpretor& di,
|
||||
|
||||
}
|
||||
|
||||
//=================================================================================
|
||||
//function : arclinconvert
|
||||
//purpose : Convert a single face to a face with contour made of arcs and segments
|
||||
//=================================================================================
|
||||
|
||||
static Standard_Integer arclinconvert (Draw_Interpretor& /*dout*/, Standard_Integer n, const char** a)
|
||||
{
|
||||
// Check the command arguments
|
||||
if (n < 3) {
|
||||
std::cout<<"Error: "<<a[0]<<" - invalid number of arguments"<<std::endl;
|
||||
std::cout<<"Usage: type help "<<a[0]<<std::endl;
|
||||
return 1; //TCL_ERROR
|
||||
}
|
||||
|
||||
//read shape
|
||||
const TopoDS_Shape aShape = DBRep::Get(a[2]);
|
||||
if (aShape.IsNull()) {
|
||||
std::cout<<"Error: "<<a[2]<<" is null"<<std::endl;
|
||||
return 1; //TCL_ERROR
|
||||
}
|
||||
|
||||
TopAbs_ShapeEnum aType = aShape.ShapeType();
|
||||
if (aType != TopAbs_WIRE &&
|
||||
aType != TopAbs_FACE)
|
||||
{
|
||||
std::cout<<"Error: "<<a[2]<<" is neither wire no face"<<std::endl;
|
||||
return 1; //TCL_ERROR
|
||||
}
|
||||
|
||||
//read tolerance
|
||||
Standard_Real aTol = 0.01;
|
||||
if (n > 3)
|
||||
aTol = Draw::Atof(a[3]);
|
||||
std::cout<<"Info: tolerance is set to "<<aTol<<std::endl;
|
||||
|
||||
TopoDS_Shape aResult;
|
||||
|
||||
if (aType == TopAbs_WIRE)
|
||||
{
|
||||
Standard_Boolean OnlyPlane = Standard_False;
|
||||
BRepBuilderAPI_MakeFace aFaceMaker (TopoDS::Wire(aShape), OnlyPlane);
|
||||
if (aFaceMaker.Error() != BRepBuilderAPI_FaceDone)
|
||||
{
|
||||
std::cout<<"Error: failed to find a face for the wire "<<a[2]<<std::endl;
|
||||
return 1; //TCL_ERROR
|
||||
}
|
||||
TopoDS_Face aFace = aFaceMaker.Face();
|
||||
TopoDS_Iterator anIter (aFace);
|
||||
TopoDS_Wire aWire = TopoDS::Wire (anIter.Value());
|
||||
aResult = BRepAlgo::ConvertWire (aWire, aTol, aFace);
|
||||
}
|
||||
else if (aType == TopAbs_FACE)
|
||||
{
|
||||
TopoDS_Face aFace = TopoDS::Face(aShape);
|
||||
aResult = BRepAlgo::ConvertFace (aFace, aTol);
|
||||
}
|
||||
|
||||
if (aResult.IsNull()) {
|
||||
std::cout<<"Error: could not convert "<<a[2]<<std::endl;
|
||||
return 1; //TCL_ERROR
|
||||
}
|
||||
|
||||
DBRep::Set(a[1], aResult);
|
||||
return 0; //TCL_OK
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : concatC0wire
|
||||
//purpose :
|
||||
@ -1908,11 +2003,11 @@ void BRepTest::CurveCommands(Draw_Interpretor& theCommands)
|
||||
profile2d,g);
|
||||
|
||||
theCommands.Add("mkoffset",
|
||||
"mkoffset result face/compound of wires nboffset stepoffset [jointype(a/i) [alt]]",__FILE__,
|
||||
"mkoffset result face/compound of wires nboffset stepoffset [-approx] [jointype(a/i) [alt]]",__FILE__,
|
||||
mkoffset,g);
|
||||
|
||||
theCommands.Add("openoffset",
|
||||
"openoffset result face/wire nboffset stepoffset [jointype(a/i)]",__FILE__,
|
||||
"openoffset result face/wire nboffset stepoffset [-approx] [jointype(a/i)]",__FILE__,
|
||||
openoffset,g);
|
||||
|
||||
theCommands.Add("mkedge",
|
||||
@ -1968,6 +2063,12 @@ void BRepTest::CurveCommands(Draw_Interpretor& theCommands)
|
||||
"reducepcurves shape1 shape2 ...",__FILE__,
|
||||
reducepcurves, g);
|
||||
|
||||
theCommands.Add("arclinconvert",
|
||||
"arclinconvert result wire/face [tol]",
|
||||
__FILE__,
|
||||
arclinconvert,
|
||||
g);
|
||||
|
||||
theCommands.Add("concatC0wire",
|
||||
"concatC0wire result wire",
|
||||
__FILE__,
|
||||
|
@ -1,5 +1,7 @@
|
||||
Geom2dConvert.cxx
|
||||
Geom2dConvert.hxx
|
||||
Geom2dConvert_ApproxArcsSegments.cxx
|
||||
Geom2dConvert_ApproxArcsSegments.hxx
|
||||
Geom2dConvert_ApproxCurve.cxx
|
||||
Geom2dConvert_ApproxCurve.hxx
|
||||
Geom2dConvert_BSplineCurveKnotSplitting.cxx
|
||||
@ -8,3 +10,6 @@ Geom2dConvert_BSplineCurveToBezierCurve.cxx
|
||||
Geom2dConvert_BSplineCurveToBezierCurve.hxx
|
||||
Geom2dConvert_CompCurveToBSplineCurve.cxx
|
||||
Geom2dConvert_CompCurveToBSplineCurve.hxx
|
||||
Geom2dConvert_PPoint.cxx
|
||||
Geom2dConvert_PPoint.hxx
|
||||
Geom2dConvert_SequenceOfPPoint.hxx
|
||||
|
911
src/Geom2dConvert/Geom2dConvert_ApproxArcsSegments.cxx
Normal file
911
src/Geom2dConvert/Geom2dConvert_ApproxArcsSegments.cxx
Normal file
@ -0,0 +1,911 @@
|
||||
// Created: 2009-01-21
|
||||
//
|
||||
// Copyright (c) 2009-2013 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS,
|
||||
// furnished in accordance with the terms and conditions of the contract
|
||||
// and with the inclusion of this copyright notice.
|
||||
// This file or any part thereof may not be provided or otherwise
|
||||
// made available to any third party.
|
||||
//
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#include <Geom2dConvert_ApproxArcsSegments.hxx>
|
||||
|
||||
#include <Adaptor2d_Curve2d.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
#include <GCE2d_MakeArcOfCircle.hxx>
|
||||
#include <GCE2d_MakeSegment.hxx>
|
||||
#include <GCPnts_QuasiUniformDeflection.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#include <gp.hxx>
|
||||
#include <gp_Ax2d.hxx>
|
||||
#include <gp_Lin2d.hxx>
|
||||
|
||||
static const Standard_Integer MAXPOINTS = 100;
|
||||
static const Standard_Real MyCurvatureTolerance = 0.0001;
|
||||
|
||||
static Standard_Boolean checkContinuity (const Handle(Geom2d_Curve)& theCurve1,
|
||||
const Handle(Geom2d_Curve)& theCurve2,
|
||||
const Standard_Real theAnglTol);
|
||||
|
||||
static Geom2dConvert_PPoint getParameter (const gp_XY& theXY1,
|
||||
const Standard_Real theFirstPar,
|
||||
const Standard_Real theLastPar,
|
||||
const Adaptor2d_Curve2d& theCurve);
|
||||
|
||||
static Standard_Boolean isInflectionPoint (const Standard_Real theParam,
|
||||
const Adaptor2d_Curve2d& theCurve);
|
||||
|
||||
static Standard_Boolean isInflectionPoint (const Standard_Real theParam,
|
||||
const Geom2dConvert_PPoint& theFirstInf,
|
||||
const Adaptor2d_Curve2d& theCurve,
|
||||
const Standard_Real theAnglTol);
|
||||
|
||||
|
||||
//=======================================================================
|
||||
//function : Geom2dConvert_ApproxArcsSegments()
|
||||
//purpose : Constructor
|
||||
//=======================================================================
|
||||
|
||||
Geom2dConvert_ApproxArcsSegments::Geom2dConvert_ApproxArcsSegments
|
||||
(const Adaptor2d_Curve2d& theCurve,
|
||||
const Standard_Real theTolerance,
|
||||
const Standard_Real theAngleTol)
|
||||
: myCurve (theCurve),
|
||||
myAlloc (new NCollection_IncAllocator(4000)),
|
||||
myTolerance (theTolerance),
|
||||
myAngleTolerance (theAngleTol),
|
||||
mySeqParams (myAlloc),
|
||||
myStatus (StatusNotDone)
|
||||
{
|
||||
myExt[0] = Geom2dConvert_PPoint(myCurve.FirstParameter(), myCurve);
|
||||
myExt[1] = Geom2dConvert_PPoint(myCurve.LastParameter(), myCurve);
|
||||
|
||||
switch (myCurve.GetType())
|
||||
{
|
||||
case GeomAbs_Line:
|
||||
{
|
||||
// Create a single line segment.
|
||||
const Standard_Real aDist = myExt[0].Dist(myExt[1]);
|
||||
if (aDist > Precision::Confusion()) {
|
||||
const gp_Ax2d anAx2d(myExt[0].Point(), gp_Vec2d(myExt[0].Point(),
|
||||
myExt[1].Point()));
|
||||
const Handle(Geom2d_Line) aLine = new Geom2d_Line(anAx2d);
|
||||
mySeqCurves.Append(new Geom2d_TrimmedCurve(aLine, 0., aDist));
|
||||
myStatus = StatusOK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GeomAbs_Circle:
|
||||
{
|
||||
// Create a couple of arcs of equal size.
|
||||
const Geom2dConvert_PPoint aPP(.5 *(myExt[0].Parameter() +
|
||||
myExt[1].Parameter()), myCurve);
|
||||
Handle(Geom2d_Curve) aCurve = makeCircle (myExt[0], aPP);
|
||||
if (aCurve.IsNull() == Standard_False) {
|
||||
mySeqCurves.Append(aCurve);
|
||||
aCurve = makeCircle (aPP, myExt[1]);
|
||||
if (aCurve.IsNull() == Standard_False)
|
||||
mySeqCurves.Append(aCurve);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
makeFreeform();
|
||||
}
|
||||
|
||||
// Check status of the calculation
|
||||
if (myStatus == StatusNotDone) {
|
||||
if (mySeqCurves.IsEmpty() == Standard_False)
|
||||
myStatus = StatusOK;
|
||||
else {
|
||||
//std::cout << "GeomConv2d_Approx: no geometry converted." << std::endl;
|
||||
myStatus = StatusError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : makeCircle
|
||||
//purpose : method for creation of circle
|
||||
//=======================================================================
|
||||
|
||||
Handle(Geom2d_Curve) Geom2dConvert_ApproxArcsSegments::makeCircle
|
||||
(const Geom2dConvert_PPoint& theFirst,
|
||||
const Geom2dConvert_PPoint& theLast) const
|
||||
{
|
||||
Handle(Geom2d_Curve) aResult;
|
||||
gp_Pnt2d aPointM (0.0,0.0);
|
||||
const Standard_Real aParaM = (theFirst.Parameter() + theLast.Parameter()) *.5;
|
||||
myCurve.D0(aParaM, aPointM);
|
||||
GCE2d_MakeArcOfCircle aMakeArc1(theFirst.Point(), aPointM, theLast.Point());
|
||||
|
||||
if (aMakeArc1.IsDone())
|
||||
aResult = aMakeArc1.Value();
|
||||
//else
|
||||
//std::cout << "makeCircle(): Circle not built" << std::endl;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : makeArc
|
||||
//purpose : creation arcs by two points and derivative in the first point
|
||||
/// : parameter isFirst specified direction of the arc.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_ApproxArcsSegments::makeArc
|
||||
(const Geom2dConvert_PPoint& theParam1,
|
||||
Geom2dConvert_PPoint& theParam2,
|
||||
const Standard_Boolean isFirst,
|
||||
Handle(Geom2d_TrimmedCurve)& theCurve) const
|
||||
{
|
||||
const gp_XY aP1 (theParam1.Point());
|
||||
const gp_XY aP2 (theParam2.Point());
|
||||
const gp_XY aVec (isFirst? theParam1.D1() : -theParam1.D1());
|
||||
|
||||
// Detect the sense (CCW means positive)
|
||||
const gp_XY aDelta = aP2 - aP1;
|
||||
Standard_Real aSense = aVec ^ aDelta;
|
||||
if (aSense > Precision::Angular())
|
||||
aSense = 1.;
|
||||
else if (aSense < -Precision::Angular())
|
||||
aSense = -1.;
|
||||
else {
|
||||
//std::cout << "makeArc(): Arc Not Built" << std::endl;
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// Find the centre of the circle
|
||||
const gp_XY aMiddle = (aP2 + aP1) * 0.5;
|
||||
const Standard_Real prodP1V = aP1 * aVec;
|
||||
const Standard_Real prodDeM = aDelta * aMiddle;
|
||||
const Standard_Real vprodVD = aVec ^ aDelta;
|
||||
const Standard_Real aResolution = gp::Resolution();
|
||||
|
||||
if (vprodVD < -aResolution || vprodVD > aResolution) {
|
||||
const gp_Pnt2d aCenter((prodP1V * aDelta.Y() - prodDeM * aVec.Y())/vprodVD,
|
||||
(prodDeM * aVec.X() - prodP1V * aDelta.X())/vprodVD);
|
||||
const Standard_Real aRad =
|
||||
(aCenter.Distance(aP1) + aCenter.Distance(aP2)) * 0.5;
|
||||
const gp_Ax22d ax22d (aCenter, gp_Dir2d(1., 0.), gp_Dir2d(0., 1.));
|
||||
const gp_Circ2d aCir (ax22d, aRad);
|
||||
const Handle(Geom2d_Circle) Circ = new Geom2d_Circle(aCir);
|
||||
|
||||
//calculation parameters first and last points of arc.
|
||||
Standard_Real anAlpha1, anAlpha2;
|
||||
if (isFirst) {
|
||||
anAlpha1 = ElCLib::Parameter(aCir, aP1);
|
||||
anAlpha2 = ElCLib::Parameter(aCir, aP2);
|
||||
} else {
|
||||
anAlpha1 = ElCLib::Parameter(aCir, aP2);
|
||||
anAlpha2 = ElCLib::Parameter(aCir, aP1);
|
||||
aSense = -aSense;
|
||||
}
|
||||
|
||||
if (fabs (anAlpha1 - anAlpha2) < 1e-100)
|
||||
// very small value, just to avoid exact match
|
||||
return Standard_False;
|
||||
|
||||
// Reverse the circle if the sense is negative
|
||||
if (aSense < 0.) {
|
||||
anAlpha1 = Circ->ReversedParameter(anAlpha1);
|
||||
anAlpha2 = Circ->ReversedParameter(anAlpha2);
|
||||
Circ->Reverse();
|
||||
}
|
||||
theCurve = new Geom2d_TrimmedCurve(Circ, anAlpha1, anAlpha2);
|
||||
// Correct the direction in the opposite point
|
||||
const gp_XY aRadV = theParam2.Point() - aCenter.XY();
|
||||
theParam2.SetD1(gp_XY(- aRadV.Y() * aSense, aRadV.X() * aSense));
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// Algorithm failed, possibly because aVec is normal to the chorde
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : makeLine
|
||||
//purpose : method for creation of line
|
||||
//=======================================================================
|
||||
|
||||
Handle(Geom2d_TrimmedCurve) Geom2dConvert_ApproxArcsSegments::makeLine
|
||||
(Geom2dConvert_PPoint& theFirst,
|
||||
Geom2dConvert_PPoint& theLast,
|
||||
const Standard_Boolean isCheck) const
|
||||
{
|
||||
Handle(Geom2d_TrimmedCurve) aResult;
|
||||
|
||||
gp_XY aSlope = theLast.Point() - theFirst.Point();
|
||||
if (fabs(aSlope.SquareModulus()) < gp::Resolution())
|
||||
return aResult;
|
||||
gp_Dir2d aDirLine(aSlope);
|
||||
|
||||
if (isCheck) {
|
||||
if (theFirst.D1().SquareModulus() < gp::Resolution() ||
|
||||
theLast.D1().SquareModulus() < gp::Resolution())
|
||||
return aResult;
|
||||
|
||||
// Angular continuity (G1) is only checked when the end of the line is not
|
||||
// on the extremity of the curve
|
||||
Standard_Real absAngle[2] = { 0., 0. };
|
||||
if (theFirst != myExt[0]) {
|
||||
const Standard_Real anAng = aDirLine.Angle(theFirst.D1());
|
||||
absAngle[0] = (anAng > 0. ? anAng : -anAng);
|
||||
}
|
||||
if (theLast != myExt[1]) {
|
||||
const Standard_Real anAng = aDirLine.Angle(theLast.D1());
|
||||
absAngle[1] = (anAng > 0. ? anAng : -anAng);
|
||||
}
|
||||
|
||||
// if the derivatives in the end points differ from the derivative line
|
||||
// more than value of the specified continuity tolerance
|
||||
// then a biarc should be build instead of a line.
|
||||
const Standard_Real aContTolerance = ::Max(myAngleTolerance, 0.01);
|
||||
if (absAngle[0] > aContTolerance || absAngle[1] > aContTolerance) {
|
||||
//std::cout << "makeLine(): Line not built" << std::endl;
|
||||
return aResult;
|
||||
}
|
||||
} // end if (isCheck)
|
||||
|
||||
//bulding segment of line
|
||||
GCE2d_MakeSegment aMakeSeg (theFirst.Point(), theLast.Point());
|
||||
if (aMakeSeg.IsDone()) {
|
||||
Handle(Geom2d_TrimmedCurve) aCurve = aMakeSeg.Value();
|
||||
if (checkCurve (aCurve, theFirst.Parameter(), theLast.Parameter())) {
|
||||
aResult = aCurve;
|
||||
// correct the derivatives fields in both arguments
|
||||
const gp_XY aNewD1 (theLast.Point() - theFirst.Point());
|
||||
theFirst.SetD1(aNewD1);
|
||||
theLast.SetD1(aNewD1);
|
||||
}
|
||||
}
|
||||
//else
|
||||
//std::cout << "makeLine(): Line not built" << std::endl;
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : makeFreeform
|
||||
//purpose : get a sequence of Geom curves from one curve
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_ApproxArcsSegments::makeFreeform()
|
||||
{
|
||||
Geom2dConvert_SequenceOfPPoint seqParamPoints(myAlloc);
|
||||
Geom2dConvert_PPoint* aPrevParam = &myExt[0];
|
||||
|
||||
//calculation of the inflection points.
|
||||
getLinearParts(seqParamPoints);
|
||||
const Standard_Boolean isNoInfPoints = seqParamPoints.IsEmpty();
|
||||
|
||||
TColGeom2d_SequenceOfCurve aSeqLinearParts;
|
||||
Standard_Boolean isDone (Standard_True);
|
||||
Standard_Integer i;
|
||||
for (i = 1; i < seqParamPoints.Length(); i += 2)
|
||||
{
|
||||
Handle(Geom2d_Curve) aLineCurve;
|
||||
Geom2dConvert_PPoint& aParam0 = seqParamPoints.ChangeValue(i);
|
||||
Geom2dConvert_PPoint& aParam1 = seqParamPoints.ChangeValue(i+1);
|
||||
if (aParam0 != aParam1)
|
||||
//linear part of the curve lies between odd and even values of i.
|
||||
//parameters from parameter's sequence.
|
||||
aLineCurve = makeLine (aParam0, aParam1, Standard_False);
|
||||
aSeqLinearParts.Append(aLineCurve);
|
||||
}
|
||||
|
||||
for (i = 1; i < seqParamPoints.Length(); i += 2)
|
||||
{
|
||||
//approximation for non-linear part preceding the linear part
|
||||
if (seqParamPoints(i) != * aPrevParam) {
|
||||
const Standard_Integer aLastInd = mySeqCurves.Length();
|
||||
isDone = makeApproximation (* aPrevParam, seqParamPoints(i));
|
||||
if (isDone && aLastInd && mySeqCurves.Length() > aLastInd)
|
||||
isDone = checkContinuity(mySeqCurves.Value(aLastInd),
|
||||
mySeqCurves.Value(aLastInd+1),
|
||||
myAngleTolerance);
|
||||
if (!isDone) {
|
||||
myStatus = StatusError;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const Handle(Geom2d_Curve)& aCurve = aSeqLinearParts.Value((i+1)/2);
|
||||
if (aCurve.IsNull() == Standard_False)
|
||||
mySeqCurves.Append(aCurve);
|
||||
else {
|
||||
Geom2dConvert_PPoint& aParam0 = seqParamPoints.ChangeValue(i);
|
||||
Geom2dConvert_PPoint& aParam1 = seqParamPoints.ChangeValue(i+1);
|
||||
const Standard_Integer aLastInd = mySeqCurves.Length();
|
||||
isDone = makeApproximation (aParam0, aParam1);
|
||||
if (isDone && aLastInd && mySeqCurves.Length() > aLastInd)
|
||||
isDone = checkContinuity(mySeqCurves.Value(aLastInd),
|
||||
mySeqCurves.Value(aLastInd+1),
|
||||
myAngleTolerance);
|
||||
|
||||
if (!isDone) {
|
||||
myStatus = StatusError;
|
||||
//std::cout << "makeOther: Line not built" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
aPrevParam = &seqParamPoints(i+1);
|
||||
}
|
||||
|
||||
//approximation for non-linear part following the last linear part
|
||||
if (isDone && (* aPrevParam != myExt[1]))
|
||||
{
|
||||
// Case of a closed edge like an ellipse
|
||||
if (isNoInfPoints &&
|
||||
(myExt[0].Point() - myExt[1].Point()).Modulus() < myTolerance)
|
||||
{
|
||||
Geom2dConvert_PPoint aPPoint(0.5 * (myExt[0].Parameter() +
|
||||
myExt[1].Parameter()), myCurve);
|
||||
isDone = makeApproximation (myExt[0], aPPoint);
|
||||
if (isDone)
|
||||
isDone = makeApproximation (aPPoint, myExt[1]);
|
||||
} else {
|
||||
isDone = makeApproximation (* aPrevParam, myExt[1]);
|
||||
}
|
||||
if (!isDone) {
|
||||
myStatus = StatusError;
|
||||
//std::cout << "makeOther: Line not built" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return (mySeqCurves.Length() && myStatus != StatusError);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : getLinearParts
|
||||
//purpose : method for geting inflection points
|
||||
//=======================================================================
|
||||
|
||||
void Geom2dConvert_ApproxArcsSegments::getLinearParts (Geom2dConvert_SequenceOfPPoint& theSeqPar)
|
||||
{
|
||||
Standard_Integer i;
|
||||
// Fill the sequences with values along the curve
|
||||
mySeqParams.Clear();
|
||||
Adaptor2d_Curve2d& myCurveMut = const_cast<Adaptor2d_Curve2d&>(myCurve);
|
||||
GCPnts_QuasiUniformDeflection aQUDefAlgo (myCurveMut, myTolerance * 0.5);
|
||||
Standard_Boolean isUniformDone = aQUDefAlgo.IsDone();
|
||||
|
||||
gp_XY aLastPnt(myExt[0].Point());
|
||||
if (isUniformDone) {
|
||||
for (i = 1; i <= aQUDefAlgo.NbPoints(); i++) {
|
||||
const Geom2dConvert_PPoint aPP (aQUDefAlgo.Parameter(i), myCurve);
|
||||
mySeqParams.Append(aPP);
|
||||
aLastPnt = aPP.Point();
|
||||
}
|
||||
} else {
|
||||
const Standard_Real aParamStep =
|
||||
(myExt[1].Parameter() - myExt[0].Parameter()) / MAXPOINTS;
|
||||
for (i = 1; i <= MAXPOINTS; i++) {
|
||||
const Standard_Real aParam = myExt[0].Parameter() + aParamStep * i;
|
||||
const Geom2dConvert_PPoint aPP (aParam, myCurve);
|
||||
mySeqParams.Append(aPP);
|
||||
aLastPnt = aPP.Point();
|
||||
}
|
||||
}
|
||||
|
||||
//check if the curve may be linearised
|
||||
gp_XY aDir = myExt[1].Point() - myExt[0].Point();
|
||||
const Standard_Real aMod2 = aDir.SquareModulus();
|
||||
if (aMod2 > Precision::Confusion())
|
||||
{
|
||||
Standard_Boolean isLinear = Standard_True;
|
||||
aDir /= sqrt(aMod2);
|
||||
for (i = 1; i <= mySeqParams.Length(); i++) {
|
||||
// Distance from point "i" to the segment between two extremities
|
||||
const Standard_Real aDist = aDir ^ (mySeqParams(i).Point() -
|
||||
myExt[0].Point());
|
||||
if (aDist > myTolerance * 0.5 || aDist < -myTolerance * 0.5) {
|
||||
isLinear = Standard_False;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isLinear) {
|
||||
theSeqPar.Append(myExt[0]);
|
||||
theSeqPar.Append(myExt[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//check if point for First Parameter is inflection point.
|
||||
Standard_Integer indStartLinear (0);
|
||||
Geom2dConvert_PPoint aLastInflParam = myExt[0];
|
||||
Geom2dConvert_PPoint aFirstInflParam = myExt[0];
|
||||
|
||||
// Getting further inflection points with step by parameter.
|
||||
// The point with index 1 is the same as myExt[0]
|
||||
for (i = 1; i <= mySeqParams.Length(); i++)
|
||||
{
|
||||
const Geom2dConvert_PPoint& aCurParam = mySeqParams(i);
|
||||
if (indStartLinear) {
|
||||
Standard_Boolean isStillInflectionFirst =
|
||||
isInflectionPoint (aFirstInflParam.Parameter(), aCurParam,
|
||||
myCurve, myAngleTolerance);
|
||||
if (isInflectionPoint (aCurParam.Parameter(), aFirstInflParam,
|
||||
myCurve, myAngleTolerance))
|
||||
{
|
||||
aLastInflParam = mySeqParams(i);
|
||||
while (isStillInflectionFirst == Standard_False) {
|
||||
if (++indStartLinear >= i) {
|
||||
indStartLinear = 0;
|
||||
break;
|
||||
}
|
||||
aFirstInflParam = mySeqParams(indStartLinear);
|
||||
isStillInflectionFirst =
|
||||
isInflectionPoint (aFirstInflParam.Parameter(), aCurParam,
|
||||
myCurve, myAngleTolerance);
|
||||
}
|
||||
} else {
|
||||
// Add the interval in the output sequence
|
||||
// The interval is added only if it is more than 10 times the tolerance
|
||||
aLastInflParam = findInflection (aLastInflParam, aCurParam);
|
||||
if (!isInflectionPoint (aFirstInflParam.Parameter(), aLastInflParam,
|
||||
myCurve, myAngleTolerance))
|
||||
{
|
||||
aFirstInflParam = findInflection (aLastInflParam, aFirstInflParam);
|
||||
}
|
||||
const Standard_Real aDist((aFirstInflParam.Point() -
|
||||
aLastInflParam.Point()).Modulus());
|
||||
if (aFirstInflParam.Parameter() < aLastInflParam.Parameter() &&
|
||||
aDist > 10 * myTolerance)
|
||||
{
|
||||
theSeqPar.Append(aFirstInflParam);
|
||||
theSeqPar.Append(aLastInflParam);
|
||||
}
|
||||
indStartLinear = 0;
|
||||
}
|
||||
} else
|
||||
if (isInflectionPoint (aCurParam.Parameter(), myCurve)) {
|
||||
aLastInflParam = aCurParam;
|
||||
if (i > 1)
|
||||
aFirstInflParam = findInflection (aCurParam, mySeqParams(i-1));
|
||||
indStartLinear = i;
|
||||
}
|
||||
}
|
||||
|
||||
const Standard_Real aDist((aFirstInflParam.Point() -
|
||||
myExt[1].Point()).Modulus());
|
||||
if (indStartLinear && aDist > 10 * myTolerance)
|
||||
{
|
||||
theSeqPar.Append(aFirstInflParam);
|
||||
theSeqPar.Append(myExt[1]);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : findInflection
|
||||
//purpose : Dichotomic search of the boundary of inflection interval, between
|
||||
// two parameters on the Curve
|
||||
//=======================================================================
|
||||
|
||||
Geom2dConvert_PPoint Geom2dConvert_ApproxArcsSegments::findInflection
|
||||
(const Geom2dConvert_PPoint& theParamIsInfl,
|
||||
const Geom2dConvert_PPoint& theParamNoInfl) const
|
||||
{
|
||||
Standard_Real aLower (theParamIsInfl.Parameter());
|
||||
Standard_Real anUpper (theParamNoInfl.Parameter());
|
||||
Standard_Real aTest(0.);
|
||||
for (Standard_Integer i = 0; i < 3; i++) { // 3 iterations
|
||||
aTest = (aLower + anUpper) * 0.5;
|
||||
if (isInflectionPoint (aTest, theParamIsInfl, myCurve, myAngleTolerance))
|
||||
aLower = aTest;
|
||||
else
|
||||
anUpper = aTest;
|
||||
}
|
||||
return Geom2dConvert_PPoint(aTest, myCurve);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : makeApproximation
|
||||
//purpose : make approximation non-linear part of the other curve
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_ApproxArcsSegments::makeApproximation
|
||||
(Geom2dConvert_PPoint& theFirstParam,
|
||||
Geom2dConvert_PPoint& theLastParam)
|
||||
{
|
||||
// if difference between parameters is less than Precision::PConfusion
|
||||
//approximation was not made.
|
||||
Standard_Boolean isDone = Standard_False;
|
||||
if (theLastParam != theFirstParam) {
|
||||
const Standard_Real aDistance =
|
||||
(theFirstParam.Point() - theLastParam.Point()).Modulus();
|
||||
if (aDistance < myTolerance)
|
||||
{
|
||||
const Handle(Geom2d_Curve) aCurve = makeLine(theFirstParam, theLastParam,
|
||||
Standard_True);
|
||||
isDone = !aCurve.IsNull();
|
||||
if (isDone && mySeqCurves.Length())
|
||||
isDone = checkContinuity(mySeqCurves.Last(), aCurve, myAngleTolerance);
|
||||
if (isDone || aDistance < Precision::Confusion()) {
|
||||
mySeqCurves.Append(aCurve);
|
||||
return isDone;
|
||||
}
|
||||
}
|
||||
//calculate biarc
|
||||
isDone = calculateBiArcs (theFirstParam, theLastParam);
|
||||
|
||||
// if biarc was not calculated calculation is repeated on half the interval.
|
||||
if (!isDone)
|
||||
{
|
||||
Geom2dConvert_PPoint aParaM
|
||||
(theFirstParam.Parameter() +
|
||||
(theLastParam.Parameter() - theFirstParam.Parameter()) * 0.55,
|
||||
myCurve);
|
||||
isDone = makeApproximation (theFirstParam, aParaM);
|
||||
if (isDone)
|
||||
isDone = makeApproximation (aParaM, theLastParam);
|
||||
}
|
||||
}
|
||||
return isDone;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : calculateBiArcs
|
||||
//purpose : method for calculation of the biarcs.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_ApproxArcsSegments::calculateBiArcs
|
||||
(Geom2dConvert_PPoint& theFirstParam,
|
||||
Geom2dConvert_PPoint& theLastParam)
|
||||
{
|
||||
const Standard_Real aResolution = gp::Resolution();
|
||||
|
||||
if (theFirstParam.D1().SquareModulus() < aResolution ||
|
||||
theLastParam.D1().SquareModulus() < aResolution)
|
||||
{
|
||||
//std::cout << "calculateBiArcs(): bad initial data" << std::endl;
|
||||
return Standard_False;
|
||||
}
|
||||
const gp_XY aPnt[2] = {
|
||||
theFirstParam.Point(),
|
||||
theLastParam.Point()
|
||||
};
|
||||
gp_Dir2d aDir[2] = {
|
||||
theFirstParam.D1(),
|
||||
theLastParam.D1()
|
||||
};
|
||||
|
||||
// Try to approximate the curve by a single arc. The criterion for that is
|
||||
// more rigid if the curve is the entire input curve
|
||||
// (possible pb. connecting with other boundaries)
|
||||
const gp_Vec2d aDelta (aPnt[1] - aPnt[0]);
|
||||
Standard_Real anAngle1 = aDelta.Angle(gp_Vec2d(aDir[0]));
|
||||
if (anAngle1 < 0.)
|
||||
anAngle1 = -anAngle1;
|
||||
Standard_Real anAngle2 = aDelta.Angle(gp_Vec2d(aDir[1]));
|
||||
if (anAngle2 < 0.)
|
||||
anAngle2 = -anAngle2;
|
||||
|
||||
//in the case when two angles are equal one arc can be built.
|
||||
Standard_Real anAngleThreshold (Precision::Angular() * 10.);
|
||||
if (theFirstParam != myExt[0] || theLastParam != myExt[1])
|
||||
anAngleThreshold = myAngleTolerance * 0.1;
|
||||
if (fabs(anAngle1 - anAngle2) < anAngleThreshold)
|
||||
{
|
||||
Handle(Geom2d_TrimmedCurve) aCurve;
|
||||
// protect the theLastParam from modification of D1, when
|
||||
// the created arc is rejected.
|
||||
Geom2dConvert_PPoint aLastParam (theLastParam);
|
||||
if (!makeArc (theFirstParam, aLastParam, Standard_True, aCurve))
|
||||
return Standard_False;
|
||||
if (checkCurve(aCurve, theFirstParam.Parameter(), aLastParam.Parameter()))
|
||||
{
|
||||
theLastParam = aLastParam;
|
||||
mySeqCurves.Append(aCurve);
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
|
||||
// if one arc was not built or for other cases biarc will be built
|
||||
// method for building biarc was taken from article Ahmad H. Nasri et al.
|
||||
// "A Recursive Subdivision Algorithm for Piecewise Circular Spline",
|
||||
// Computer Graphics Forum, 2001.
|
||||
|
||||
// definition of point of intersection two tangent directions in the points
|
||||
// corresponding FirstParameter and LastParameter.
|
||||
aDir[1].Reverse();
|
||||
|
||||
// Direct calculation of intersection point, replaces a class call below
|
||||
const Standard_Real aProd [3] = {
|
||||
aPnt[0] ^ aDir[0].XY(),
|
||||
aPnt[1] ^ aDir[1].XY(),
|
||||
aDir[1] ^ aDir[0].XY()
|
||||
};
|
||||
gp_XY aIntPoint((aProd[0] * aDir[1].X() - aProd[1] * aDir[0].X()) / aProd[2],
|
||||
(aProd[0] * aDir[1].Y() - aProd[1] * aDir[0].Y()) / aProd[2]);
|
||||
const gp_XY aDiff[2] = {
|
||||
aIntPoint - aPnt[0],
|
||||
aIntPoint - aPnt[1]
|
||||
};
|
||||
if (aDiff[0] * aDir[0].XY() < 0. || aDiff[1] * aDir[1].XY() < 0.)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//calculation middle point for building biarc.
|
||||
const Standard_Real ad1 = aDiff[0].Modulus();
|
||||
const Standard_Real ad2 = aDiff[1].Modulus();
|
||||
const Standard_Real ad12 = aDelta.Magnitude();
|
||||
|
||||
const Standard_Real aB1 = ad1 / (ad1 + ad2);
|
||||
if (fabs(aB1 - 0.5) < 0.0001)
|
||||
return Standard_False;
|
||||
|
||||
gp_XY aXY[2] = {
|
||||
aPnt[0] + aDir[0].XY() * ad12 * ad1 / (ad12 + ad1 + ad2),
|
||||
aPnt[1] + aDir[1].XY() * ad12 * ad2 / (ad12 + ad1 + ad2)
|
||||
};
|
||||
|
||||
const gp_XY aXYmidArc (aXY[0] + aB1*(aXY[1] - aXY[0]));
|
||||
Geom2dConvert_PPoint aParamMidArc =
|
||||
getParameter (aXYmidArc, theFirstParam.Parameter(),
|
||||
theLastParam.Parameter(), myCurve);
|
||||
|
||||
//building first arc from biarc.
|
||||
Handle(Geom2d_TrimmedCurve) aCurve1, aCurve2;
|
||||
if (!makeArc (theFirstParam, aParamMidArc, Standard_True, aCurve1))
|
||||
return Standard_False;
|
||||
|
||||
if (!checkCurve (aCurve1, theFirstParam.Parameter(),
|
||||
aParamMidArc.Parameter()))
|
||||
return Standard_False;
|
||||
|
||||
//building second arc from biarc.
|
||||
if (makeArc (theLastParam, aParamMidArc, Standard_False, aCurve2)) {
|
||||
if (checkCurve (aCurve2, aParamMidArc.Parameter(),
|
||||
theLastParam.Parameter())) {
|
||||
mySeqCurves.Append(aCurve1);
|
||||
mySeqCurves.Append(aCurve2);
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : calculateLines
|
||||
//purpose : method for calculation of the linear interpolation.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_ApproxArcsSegments::calculateLines
|
||||
(Geom2dConvert_PPoint& theFirstParam,
|
||||
Geom2dConvert_PPoint& theLastParam)
|
||||
{
|
||||
Geom2dConvert_PPoint* aPrevParam = &theFirstParam;
|
||||
for (int i = 1; i <= mySeqParams.Length(); i++)
|
||||
{
|
||||
Geom2dConvert_PPoint& aCurParam = mySeqParams.ChangeValue(i);
|
||||
if (aCurParam.Parameter() < (*aPrevParam).Parameter()) {
|
||||
continue;
|
||||
}
|
||||
if (aCurParam.Parameter() > theLastParam.Parameter()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// build line segment
|
||||
if (aCurParam != *aPrevParam)
|
||||
{
|
||||
const Standard_Real aDistance =
|
||||
(aCurParam.Point() - (*aPrevParam).Point()).Modulus();
|
||||
if (aDistance > myTolerance)
|
||||
{
|
||||
const Handle(Geom2d_Curve) aCurve =
|
||||
makeLine(*aPrevParam, aCurParam, Standard_False);
|
||||
if (aCurve.IsNull()) {
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
mySeqCurves.Append(aCurve);
|
||||
aPrevParam = &mySeqParams(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : checkCurve
|
||||
//purpose : method for checking max deflection Geom curve from Adaptor Curve
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_ApproxArcsSegments::checkCurve
|
||||
(const Handle(Geom2d_Curve)& aCurve,
|
||||
const Standard_Real theFirstParam,
|
||||
const Standard_Real theLastParam) const
|
||||
{
|
||||
if (aCurve.IsNull())
|
||||
return Standard_False; // check fails on empty input
|
||||
Standard_Boolean isUniformDone = !mySeqParams.IsEmpty();
|
||||
//calcualtion sequence of the parameters or step by parameter.
|
||||
Standard_Integer aNbPnts = (isUniformDone ? mySeqParams.Length() :MAXPOINTS);
|
||||
Standard_Real aParamStep = (theLastParam - theFirstParam)/MAXPOINTS;
|
||||
|
||||
Handle(Geom2d_Curve) aCurve1 = aCurve;
|
||||
Handle(Geom2d_TrimmedCurve) aTrCurve =
|
||||
Handle(Geom2d_TrimmedCurve)::DownCast(aCurve);
|
||||
if (!aTrCurve.IsNull())
|
||||
aCurve1 = aTrCurve->BasisCurve();
|
||||
gp_Lin2d aLin2d;
|
||||
gp_Circ2d aCirc2d;
|
||||
Handle(Geom2d_Line) aGeomLine = Handle(Geom2d_Line)::DownCast(aCurve1);
|
||||
Standard_Boolean isLine = (!aGeomLine.IsNull());
|
||||
Standard_Boolean isCircle = (!isLine);
|
||||
if (isLine)
|
||||
aLin2d = aGeomLine->Lin2d();
|
||||
|
||||
else {
|
||||
Handle(Geom2d_Circle) aGeomCircle =
|
||||
Handle(Geom2d_Circle)::DownCast(aCurve1);
|
||||
isCircle = (!aGeomCircle.IsNull());
|
||||
if (isCircle)
|
||||
aCirc2d = aGeomCircle->Circ2d();
|
||||
else
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//calculation of the max deflection points from CurveAdaptor from Geom curve.
|
||||
Standard_Boolean isLess = Standard_True;
|
||||
Standard_Integer i = 1;
|
||||
for (; i <= aNbPnts && isLess; i++)
|
||||
{
|
||||
|
||||
Standard_Real aParam = (isUniformDone ? mySeqParams.Value(i).Parameter() :
|
||||
(theFirstParam + i*aParamStep));
|
||||
if (aParam < (theFirstParam - Precision::PConfusion()) ||
|
||||
aParam > (theLastParam + Precision::PConfusion())) continue;
|
||||
|
||||
//getting point from adaptor curve by specified parameter.
|
||||
gp_Pnt2d aPointAdaptor(0., 0.);
|
||||
gp_Pnt2d aProjPoint(0., 0.);
|
||||
myCurve.D0(aParam, aPointAdaptor);
|
||||
Standard_Real aParameterCurve = 0.0;
|
||||
|
||||
//getting point from geom curve by specified parameter.
|
||||
if (isLine)
|
||||
{
|
||||
aParameterCurve = ElCLib::Parameter(aLin2d, aPointAdaptor);
|
||||
aProjPoint = ElCLib::Value(aParameterCurve, aLin2d);
|
||||
}
|
||||
else if (isCircle)
|
||||
{
|
||||
|
||||
aParameterCurve = ElCLib::Parameter(aCirc2d, aPointAdaptor);
|
||||
aProjPoint = ElCLib::Value(aParameterCurve, aCirc2d);
|
||||
}
|
||||
else isLess = Standard_False;
|
||||
|
||||
isLess = (aProjPoint.Distance(aPointAdaptor) <
|
||||
myTolerance + Precision::PConfusion());
|
||||
}
|
||||
return isLess;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : checkContinuity
|
||||
//purpose : check continuty first derivative between two curves.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean checkContinuity (const Handle(Geom2d_Curve)& theCurve1,
|
||||
const Handle(Geom2d_Curve)& theCurve2,
|
||||
const Standard_Real theAngleTol)
|
||||
{
|
||||
gp_Vec2d v11,v21;
|
||||
gp_Pnt2d p1, p2;
|
||||
theCurve1->D1(theCurve1->LastParameter(), p1, v11);
|
||||
theCurve2->D1(theCurve2->FirstParameter(), p2, v21);
|
||||
|
||||
//check continuity with the specified tolerance.
|
||||
return (v11.IsParallel(v21, theAngleTol));
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : getParameter
|
||||
//purpose : getting the nearest point on AdaptorCurve to the specified point.
|
||||
//=======================================================================
|
||||
|
||||
Geom2dConvert_PPoint getParameter (const gp_XY& theXY1,
|
||||
const Standard_Real theFirstParam,
|
||||
const Standard_Real theLastParam,
|
||||
const Adaptor2d_Curve2d& theCurve)
|
||||
{
|
||||
Geom2dConvert_PPoint aResult;
|
||||
Standard_Real prevParam = theFirstParam;
|
||||
Standard_Real af1 = theFirstParam;
|
||||
Standard_Real af2 = theLastParam;
|
||||
|
||||
// for finding nearest point use method half division.
|
||||
Standard_Real aMinDist = RealLast();
|
||||
Standard_Integer i = 1;
|
||||
for (; i <= MAXPOINTS; i++)
|
||||
{
|
||||
aResult = Geom2dConvert_PPoint(af1, theCurve);
|
||||
Standard_Real adist1 = (theXY1 - aResult.Point()).Modulus();
|
||||
if (adist1 < Precision::Confusion())
|
||||
{
|
||||
return aResult;
|
||||
}
|
||||
|
||||
aResult = Geom2dConvert_PPoint(af2, theCurve);
|
||||
Standard_Real adist2 = (theXY1 - aResult.Point()).Modulus();
|
||||
if (adist2 < Precision::Confusion())
|
||||
{
|
||||
return aResult;
|
||||
}
|
||||
|
||||
if (aMinDist <= adist2 -Precision::Confusion() &&
|
||||
aMinDist <= adist1 -Precision::Confusion())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (adist1 < adist2 -Precision::Confusion())
|
||||
{
|
||||
prevParam = af1;
|
||||
aMinDist = adist1;
|
||||
af2 = (af1 + af2) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevParam = af2;
|
||||
aMinDist = adist2;
|
||||
af1 = (af1 + af2) * 0.5;
|
||||
}
|
||||
}
|
||||
aResult = Geom2dConvert_PPoint(prevParam, theCurve);
|
||||
return aResult;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : isInflectionPoint
|
||||
//purpose : method calculating that point specified by parameter
|
||||
// is inflection point
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean isInflectionPoint (const Standard_Real theParam,
|
||||
const Adaptor2d_Curve2d& theCurve)
|
||||
{
|
||||
gp_Pnt2d aP1;
|
||||
gp_Vec2d aD1, aD2;
|
||||
theCurve.D2(theParam, aP1, aD1, aD2);
|
||||
const Standard_Real aSqMod = aD1.XY().SquareModulus();
|
||||
const Standard_Real aCurvature =
|
||||
fabs (aD1.XY() ^ aD2.XY()) / (aSqMod * sqrt(aSqMod));
|
||||
return (aCurvature < MyCurvatureTolerance);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : isInflectionPoint
|
||||
//purpose : method calculating that point specified by parameter
|
||||
// is inflection point
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean isInflectionPoint (const Standard_Real theParam,
|
||||
const Geom2dConvert_PPoint& theFirstInfl,
|
||||
const Adaptor2d_Curve2d& theCurve,
|
||||
const Standard_Real theAngleTol)
|
||||
{
|
||||
gp_Pnt2d aP1;
|
||||
gp_Vec2d aD1, aD2;
|
||||
theCurve.D2(theParam, aP1, aD1, aD2);
|
||||
const Standard_Real aSqMod = aD1.XY().SquareModulus();
|
||||
const Standard_Real aCurvature =
|
||||
fabs (aD1.XY() ^ aD2.XY()) / (aSqMod * sqrt(aSqMod));
|
||||
Standard_Real aContAngle =
|
||||
fabs(gp_Vec2d(aP1.XY() - theFirstInfl.Point()).Angle(aD1));
|
||||
aContAngle = ::Min(aContAngle, fabs(M_PI - aContAngle));
|
||||
return (aCurvature < MyCurvatureTolerance && aContAngle < theAngleTol);
|
||||
}
|
113
src/Geom2dConvert/Geom2dConvert_ApproxArcsSegments.hxx
Normal file
113
src/Geom2dConvert/Geom2dConvert_ApproxArcsSegments.hxx
Normal file
@ -0,0 +1,113 @@
|
||||
// Created: 2009-01-20
|
||||
//
|
||||
// Copyright (c) 2009-2013 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS,
|
||||
// furnished in accordance with the terms and conditions of the contract
|
||||
// and with the inclusion of this copyright notice.
|
||||
// This file or any part thereof may not be provided or otherwise
|
||||
// made available to any third party.
|
||||
//
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef _Geom2dConvert_ApproxArcsSegments_HeaderFile
|
||||
#define _Geom2dConvert_ApproxArcsSegments_HeaderFile
|
||||
|
||||
#include <TColGeom2d_SequenceOfCurve.hxx>
|
||||
#include <Geom2dConvert_PPoint.hxx>
|
||||
#include <Geom2dConvert_SequenceOfPPoint.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
|
||||
//! Approximation of a free-form curve by a sequence of arcs+segments.
|
||||
class Geom2dConvert_ApproxArcsSegments
|
||||
{
|
||||
public:
|
||||
// ---------- PUBLIC METHODS ----------
|
||||
|
||||
enum Status {
|
||||
StatusOK = 0,
|
||||
StatusNotDone,
|
||||
StatusError
|
||||
};
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Geom2dConvert_ApproxArcsSegments (const Adaptor2d_Curve2d& theCurve,
|
||||
const Standard_Real theTolerance,
|
||||
const Standard_Real theAngleTol);
|
||||
|
||||
//! Get the result curve after approximation.
|
||||
const TColGeom2d_SequenceOfCurve& GetResult() const
|
||||
{ return mySeqCurves; }
|
||||
|
||||
private:
|
||||
|
||||
//! Create arc of circle by three points (knowing that myCurve is circle).
|
||||
Handle(Geom2d_Curve)
|
||||
makeCircle (const Geom2dConvert_PPoint& theFirst,
|
||||
const Geom2dConvert_PPoint& theLast) const;
|
||||
|
||||
//! Create an arc of circle using 2 points and a derivative in the first point.
|
||||
Standard_Boolean makeArc (const Geom2dConvert_PPoint& theParam1,
|
||||
Geom2dConvert_PPoint& theParam2,
|
||||
const Standard_Boolean isFirst,
|
||||
Handle(Geom2d_TrimmedCurve)& theCurve) const;
|
||||
|
||||
//! Make a line from myCurve in the limits by parameter from theFirst to theLast
|
||||
Handle(Geom2d_TrimmedCurve)
|
||||
makeLine (Geom2dConvert_PPoint& theFirst,
|
||||
Geom2dConvert_PPoint& theLast,
|
||||
const Standard_Boolean isCheck) const;
|
||||
|
||||
//! Create a sequence of elementary curves from a free-form adaptor curve.
|
||||
Standard_Boolean makeFreeform ();
|
||||
|
||||
//! Obtain the linear intervals on the curve using as criteria
|
||||
//! curvature tolerance (indicating either linear part or inflection)
|
||||
void getLinearParts (Geom2dConvert_SequenceOfPPoint& theSeqParam);
|
||||
|
||||
//! Dichotomic search of the boundary of inflection interval, between
|
||||
//! two parameters on the Curve
|
||||
Geom2dConvert_PPoint findInflection(const Geom2dConvert_PPoint& theParamIsIn,
|
||||
const Geom2dConvert_PPoint& theParamNoIn) const;
|
||||
|
||||
//! Make approximation non-linear part of the other curve.
|
||||
Standard_Boolean makeApproximation
|
||||
(Geom2dConvert_PPoint& theFirstParam,
|
||||
Geom2dConvert_PPoint& theLastParam);
|
||||
|
||||
//! Method for calculation of a biarc.
|
||||
Standard_Boolean calculateBiArcs(Geom2dConvert_PPoint& theFirstParam,
|
||||
Geom2dConvert_PPoint& theLastParam);
|
||||
|
||||
//! Method for calculation of a linear interpolation.
|
||||
Standard_Boolean calculateLines(Geom2dConvert_PPoint& theFirstParam,
|
||||
Geom2dConvert_PPoint& theLastParam);
|
||||
|
||||
//! Checking max deflection Geom curve from Adaptor Curve
|
||||
Standard_Boolean checkCurve (const Handle(Geom2d_Curve)& aCurve,
|
||||
const Standard_Real theFirstParam,
|
||||
const Standard_Real theLastParam) const;
|
||||
|
||||
private:
|
||||
// ---------- PRIVATE FIELDS ----------
|
||||
|
||||
const Adaptor2d_Curve2d& myCurve;
|
||||
Geom2dConvert_PPoint myExt[2];
|
||||
|
||||
Handle(NCollection_BaseAllocator) myAlloc;
|
||||
Standard_Real myTolerance;
|
||||
Standard_Real myAngleTolerance;
|
||||
|
||||
Geom2dConvert_SequenceOfPPoint mySeqParams;
|
||||
TColGeom2d_SequenceOfCurve mySeqCurves;
|
||||
Status myStatus;
|
||||
|
||||
//! Protection against compiler warning
|
||||
void operator= (const Geom2dConvert_ApproxArcsSegments&);
|
||||
};
|
||||
|
||||
#endif
|
54
src/Geom2dConvert/Geom2dConvert_PPoint.cxx
Normal file
54
src/Geom2dConvert/Geom2dConvert_PPoint.cxx
Normal file
@ -0,0 +1,54 @@
|
||||
// Created: 2009-02-02
|
||||
//
|
||||
// Copyright (c) 2009-2013 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS,
|
||||
// furnished in accordance with the terms and conditions of the contract
|
||||
// and with the inclusion of this copyright notice.
|
||||
// This file or any part thereof may not be provided or otherwise
|
||||
// made available to any third party.
|
||||
//
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#include <Geom2dConvert_PPoint.hxx>
|
||||
|
||||
#include <Adaptor2d_Curve2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
//=======================================================================
|
||||
//function : Geom2dConvert_PPoint
|
||||
//purpose : Constructor
|
||||
//=======================================================================
|
||||
|
||||
Geom2dConvert_PPoint::Geom2dConvert_PPoint (const Standard_Real theParameter,
|
||||
const Adaptor2d_Curve2d& theAdaptor)
|
||||
: myParameter (theParameter)
|
||||
{
|
||||
theAdaptor.D1(theParameter, myPoint, myD1);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Geom2dConvert_PPoint::operator ==
|
||||
//purpose : Compare two values of this type.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_PPoint::operator ==
|
||||
(const Geom2dConvert_PPoint& theOther) const
|
||||
{
|
||||
return (fabs(myParameter - theOther.Parameter()) <= Precision::PConfusion());
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Geom2dConvert_PPoint::operator !=
|
||||
//purpose : Compare two values of this type.
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean Geom2dConvert_PPoint::operator !=
|
||||
(const Geom2dConvert_PPoint& theOther) const
|
||||
{
|
||||
return (fabs(myParameter - theOther.Parameter()) > Precision::PConfusion());
|
||||
}
|
76
src/Geom2dConvert/Geom2dConvert_PPoint.hxx
Normal file
76
src/Geom2dConvert/Geom2dConvert_PPoint.hxx
Normal file
@ -0,0 +1,76 @@
|
||||
// Created: 2009-01-21
|
||||
//
|
||||
// Copyright (c) 2009-2013 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS,
|
||||
// furnished in accordance with the terms and conditions of the contract
|
||||
// and with the inclusion of this copyright notice.
|
||||
// This file or any part thereof may not be provided or otherwise
|
||||
// made available to any third party.
|
||||
//
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef _Geom2dConvert_PPoint_HeaderFile
|
||||
#define _Geom2dConvert_PPoint_HeaderFile
|
||||
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
|
||||
class Adaptor2d_Curve2d;
|
||||
|
||||
//! Class representing a point on curve, with 2D coordinate and the tangent
|
||||
class Geom2dConvert_PPoint
|
||||
{
|
||||
public:
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT inline Geom2dConvert_PPoint ()
|
||||
: myParameter (::RealLast()),
|
||||
myPoint (0., 0.),
|
||||
myD1 (0., 0.) {}
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT inline Geom2dConvert_PPoint (const Standard_Real theParameter,
|
||||
const gp_XY& thePoint,
|
||||
const gp_XY& theD1)
|
||||
: myParameter (theParameter),
|
||||
myPoint (thePoint),
|
||||
myD1 (theD1) {}
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Geom2dConvert_PPoint (const Standard_Real theParameter,
|
||||
const Adaptor2d_Curve2d& theAdaptor);
|
||||
|
||||
//! Compute the distance betwwen two 2d points.
|
||||
inline Standard_Real Dist (const Geom2dConvert_PPoint& theOth) const
|
||||
{ return myPoint.Distance(theOth.myPoint); }
|
||||
|
||||
//! Query the parmeter value.
|
||||
inline Standard_Real Parameter () const { return myParameter; }
|
||||
|
||||
//! Query the point location.
|
||||
inline const gp_XY& Point () const { return myPoint.XY(); }
|
||||
|
||||
//! Query the first derivatives.
|
||||
inline const gp_XY& D1 () const { return myD1.XY(); }
|
||||
|
||||
//! Change the value of the derivative at the point.
|
||||
inline void SetD1 (const gp_XY& theD1)
|
||||
{ myD1.SetXY (theD1); }
|
||||
|
||||
//! Compare two values of this type.
|
||||
Standard_EXPORT Standard_Boolean operator == (const Geom2dConvert_PPoint&) const;
|
||||
|
||||
//! Compare two values of this type.
|
||||
Standard_EXPORT Standard_Boolean operator != (const Geom2dConvert_PPoint&) const;
|
||||
|
||||
private:
|
||||
Standard_Real myParameter; //! Parameter value
|
||||
gp_Pnt2d myPoint; //! Point location
|
||||
gp_Vec2d myD1; //! derivatives by parameter (components of the tangent).
|
||||
};
|
||||
|
||||
#endif
|
25
src/Geom2dConvert/Geom2dConvert_SequenceOfPPoint.hxx
Normal file
25
src/Geom2dConvert/Geom2dConvert_SequenceOfPPoint.hxx
Normal file
@ -0,0 +1,25 @@
|
||||
// Created: 2009-01-09
|
||||
//
|
||||
// Copyright (c) 2009-2013 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of commercial software by OPEN CASCADE SAS,
|
||||
// furnished in accordance with the terms and conditions of the contract
|
||||
// and with the inclusion of this copyright notice.
|
||||
// This file or any part thereof may not be provided or otherwise
|
||||
// made available to any third party.
|
||||
//
|
||||
// No ownership title to the software is transferred hereby.
|
||||
//
|
||||
// OPEN CASCADE SAS makes no representation or warranties with respect to the
|
||||
// performance of this software, and specifically disclaims any responsibility
|
||||
// for any damages, special or consequential, connected with its use.
|
||||
|
||||
#ifndef _Geom2dConvert_SequenceOfPPoint_HeaderFile
|
||||
#define _Geom2dConvert_SequenceOfPPoint_HeaderFile
|
||||
|
||||
#include <NCollection_Sequence.hxx>
|
||||
class Geom2dConvert_PPoint;
|
||||
|
||||
typedef NCollection_Sequence<Geom2dConvert_PPoint> Geom2dConvert_SequenceOfPPoint;
|
||||
|
||||
#endif
|
23
tests/bugs/modalg_8/bug32214_1
Normal file
23
tests/bugs/modalg_8/bug32214_1
Normal file
@ -0,0 +1,23 @@
|
||||
puts "========================================="
|
||||
puts "OCC32214: 2d Offset produces wrong result"
|
||||
puts "========================================="
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug32214.brep] a
|
||||
wire ww a
|
||||
|
||||
arclinconvert result ww
|
||||
build3d result
|
||||
|
||||
checkshape result
|
||||
|
||||
checknbshapes result -t -vertex 50 -edge 49 -wire 1
|
||||
|
||||
set tolres [checkmaxtol result]
|
||||
|
||||
if { ${tolres} > 1.001e-7} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
|
||||
checkprops result -l 1.88301
|
||||
|
24
tests/bugs/modalg_8/bug32214_2
Normal file
24
tests/bugs/modalg_8/bug32214_2
Normal file
@ -0,0 +1,24 @@
|
||||
puts "========================================="
|
||||
puts "OCC32214: 2d Offset produces wrong result"
|
||||
puts "========================================="
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug31992.brep] a
|
||||
wire a a
|
||||
mkplane a a
|
||||
|
||||
arclinconvert result a
|
||||
build3d result
|
||||
|
||||
checkshape result
|
||||
|
||||
checknbshapes result -t -vertex 187 -edge 187 -wire 1 -face 1
|
||||
|
||||
set tolres [checkmaxtol result]
|
||||
|
||||
if { ${tolres} > 1.001e-7} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
|
||||
checkprops result -s 3.13603
|
||||
|
30
tests/bugs/modalg_8/bug32214_3
Normal file
30
tests/bugs/modalg_8/bug32214_3
Normal file
@ -0,0 +1,30 @@
|
||||
puts "========================================="
|
||||
puts "OCC32214: 2d Offset produces wrong result"
|
||||
puts "========================================="
|
||||
puts ""
|
||||
|
||||
beziercurve c1 9 3 3 0 10 0 10 0 100 -3 3 0 10 -10 0 0 100 -3 -3 0 10 0 -10 0 100 3 -3 0 10 10 0 0 100 3 3 0 10
|
||||
beziercurve c2 5 3 0 0 0 3 0 -3 0 0 0 -3 0 3 0 0
|
||||
mkedge e1 c1
|
||||
mkedge e2 c2
|
||||
wire w1 e1
|
||||
wire w2 e2
|
||||
orientation w2 R
|
||||
mkplane a w1
|
||||
add w2 a
|
||||
|
||||
arclinconvert result a
|
||||
build3d result
|
||||
|
||||
checkshape result
|
||||
|
||||
checknbshapes result -t -vertex 170 -edge 170 -wire 2 -face 1
|
||||
|
||||
set tolres [checkmaxtol result]
|
||||
|
||||
if { ${tolres} > 1.001e-7} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
|
||||
checkprops result -s 106.6
|
||||
|
52
tests/bugs/modalg_8/bug32214_4
Normal file
52
tests/bugs/modalg_8/bug32214_4
Normal file
@ -0,0 +1,52 @@
|
||||
puts "========================================="
|
||||
puts "OCC32214: 2d Offset produces wrong result"
|
||||
puts "========================================="
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug32214.brep] a
|
||||
wire ww a
|
||||
donly ww
|
||||
|
||||
mkoffset result ww 14 0.1 -approx
|
||||
|
||||
front
|
||||
fit
|
||||
|
||||
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
|
||||
|
||||
for {set i 1} {$i<=14} {incr i} {
|
||||
checkshape result_${i}
|
||||
set tolres [checkmaxtol result_${i}]
|
||||
if { ${tolres} > 1.001e-7} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
}
|
||||
|
||||
checknbshapes result_1 -t -vertex 114 -edge 114 -wire 1
|
||||
checkprops result_1 -l 4.39365
|
||||
checknbshapes result_2 -t -vertex 110 -edge 110 -wire 1
|
||||
checkprops result_2 -l 5.02084
|
||||
checknbshapes result_3 -t -vertex 104 -edge 104 -wire 1
|
||||
checkprops result_3 -l 5.64778
|
||||
checknbshapes result_4 -t -vertex 101 -edge 101 -wire 1
|
||||
checkprops result_4 -l 6.27443
|
||||
checknbshapes result_5 -t -vertex 95 -edge 95 -wire 1
|
||||
checkprops result_5 -l 6.89816
|
||||
checknbshapes result_6 -t -vertex 92 -edge 92 -wire 1
|
||||
checkprops result_6 -l 7.51255
|
||||
checknbshapes result_7 -t -vertex 88 -edge 88 -wire 1
|
||||
checkprops result_7 -l 8.12807
|
||||
checknbshapes result_8 -t -vertex 81 -edge 81 -wire 1
|
||||
checkprops result_8 -l 8.74586
|
||||
checknbshapes result_9 -t -vertex 72 -edge 72 -wire 1
|
||||
checkprops result_9 -l 9.36292
|
||||
checknbshapes result_10 -t -vertex 65 -edge 65 -wire 1
|
||||
checkprops result_10 -l 9.97455
|
||||
checknbshapes result_11 -t -vertex 60 -edge 60 -wire 1
|
||||
checkprops result_11 -l 10.5864
|
||||
checknbshapes result_12 -t -vertex 59 -edge 59 -wire 1
|
||||
checkprops result_12 -l 11.2017
|
||||
checknbshapes result_13 -t -vertex 57 -edge 57 -wire 1
|
||||
checkprops result_13 -l 11.8196
|
||||
checknbshapes result_14 -t -vertex 55 -edge 55 -wire 1
|
||||
checkprops result_14 -l 12.4395
|
52
tests/bugs/modalg_8/bug32214_5
Normal file
52
tests/bugs/modalg_8/bug32214_5
Normal file
@ -0,0 +1,52 @@
|
||||
puts "========================================="
|
||||
puts "OCC32214: 2d Offset produces wrong result"
|
||||
puts "========================================="
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug32214.brep] a
|
||||
wire ww a
|
||||
donly ww
|
||||
|
||||
openoffset result ww 14 0.1 -approx
|
||||
|
||||
front
|
||||
fit
|
||||
|
||||
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
|
||||
|
||||
for {set i 1} {$i<=14} {incr i} {
|
||||
checkshape result_${i}
|
||||
set tolres [checkmaxtol result_${i}]
|
||||
if { ${tolres} > 1.001e-7} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
}
|
||||
|
||||
checknbshapes result_1 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_1 -l 2.04858
|
||||
checknbshapes result_2 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_2 -l 2.21414
|
||||
checknbshapes result_3 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_3 -l 2.37971
|
||||
checknbshapes result_4 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_4 -l 2.54528
|
||||
checknbshapes result_5 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_5 -l 2.71084
|
||||
checknbshapes result_6 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_6 -l 2.87641
|
||||
checknbshapes result_7 -t -vertex 61 -edge 60 -wire 1
|
||||
checkprops result_7 -l 3.04198
|
||||
checknbshapes result_8 -t -vertex 56 -edge 55 -wire 1
|
||||
checkprops result_8 -l 3.20723
|
||||
checknbshapes result_9 -t -vertex 50 -edge 49 -wire 1
|
||||
checkprops result_9 -l 3.38587
|
||||
checknbshapes result_10 -t -vertex 48 -edge 47 -wire 1
|
||||
checkprops result_10 -l 3.58204
|
||||
checknbshapes result_11 -t -vertex 45 -edge 44 -wire 1
|
||||
checkprops result_11 -l 3.73715
|
||||
checknbshapes result_12 -t -vertex 45 -edge 44 -wire 1
|
||||
checkprops result_12 -l 3.97323
|
||||
checknbshapes result_13 -t -vertex 43 -edge 42 -wire 1
|
||||
checkprops result_13 -l 4.14242
|
||||
checknbshapes result_14 -t -vertex 43 -edge 42 -wire 1
|
||||
checkprops result_14 -l 4.37544
|
52
tests/bugs/modalg_8/bug32214_6
Normal file
52
tests/bugs/modalg_8/bug32214_6
Normal file
@ -0,0 +1,52 @@
|
||||
puts "========================================="
|
||||
puts "OCC32214: 2d Offset produces wrong result"
|
||||
puts "========================================="
|
||||
puts ""
|
||||
|
||||
restore [locate_data_file bug32214.brep] a
|
||||
wire ww a
|
||||
donly ww
|
||||
|
||||
openoffset result ww 14 -0.1 -approx
|
||||
|
||||
front
|
||||
fit
|
||||
|
||||
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
|
||||
|
||||
for {set i 1} {$i<=14} {incr i} {
|
||||
checkshape result_${i}
|
||||
set tolres [checkmaxtol result_${i}]
|
||||
if { ${tolres} > 1.001e-7} {
|
||||
puts "Error: bad tolerance of result"
|
||||
}
|
||||
}
|
||||
|
||||
checknbshapes result_1 -t -vertex 50 -edge 49 -wire 1
|
||||
checkprops result_1 -l 1.66475
|
||||
checknbshapes result_2 -t -vertex 46 -edge 45 -wire 1
|
||||
checkprops result_2 -l 1.57655
|
||||
checknbshapes result_3 -t -vertex 40 -edge 39 -wire 1
|
||||
checkprops result_3 -l 1.48755
|
||||
checknbshapes result_4 -t -vertex 37 -edge 36 -wire 1
|
||||
checkprops result_4 -l 1.39682
|
||||
checknbshapes result_5 -t -vertex 31 -edge 30 -wire 1
|
||||
checkprops result_5 -l 1.30715
|
||||
checknbshapes result_6 -t -vertex 28 -edge 27 -wire 1
|
||||
checkprops result_6 -l 1.27033
|
||||
checknbshapes result_7 -t -vertex 24 -edge 23 -wire 1
|
||||
checkprops result_7 -l 1.1996
|
||||
checknbshapes result_8 -t -vertex 22 -edge 21 -wire 1
|
||||
checkprops result_8 -l 1.1737
|
||||
checknbshapes result_9 -t -vertex 18 -edge 17 -wire 1
|
||||
checkprops result_9 -l 1.17713
|
||||
checknbshapes result_10 -t -vertex 17 -edge 16 -wire 1
|
||||
checkprops result_10 -l 1.22711
|
||||
checknbshapes result_11 -t -vertex 14 -edge 13 -wire 1
|
||||
checkprops result_11 -l 1.2663
|
||||
checknbshapes result_12 -t -vertex 14 -edge 13 -wire 1
|
||||
checkprops result_12 -l 1.33108
|
||||
checknbshapes result_13 -t -vertex 14 -edge 13 -wire 1
|
||||
checkprops result_13 -l 1.39586
|
||||
checknbshapes result_14 -t -vertex 14 -edge 13 -wire 1
|
||||
checkprops result_14 -l 1.46064
|
Loading…
x
Reference in New Issue
Block a user