Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created by: Peter KURNEV
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BOPTools_AlgoTools2D.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <BRepTools.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomInt.hxx>
#include <GeomLib.hxx>
#include <gp.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <IntTools_Context.hxx>
#include <IntTools_Tools.hxx>
#include <Precision.hxx>
#include <ProjLib_ProjectedCurve.hxx>
#include <ProjLib.hxx>
#include <Standard_ConstructionError.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
static double MaxToleranceEdge(const TopoDS_Face&);
//=================================================================================================
void BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const occ::handle<IntTools_Context>& theContext)
{
BRep_Builder aBB;
occ::handle<Geom2d_Curve> aC2D;
double aTolPC, aTolFact, aTolEdge, aFirst, aLast;
bool aHasOld;
aHasOld = BOPTools_AlgoTools2D::HasCurveOnSurface(aE, aF, aC2D, aFirst, aLast, aTolEdge);
if (aHasOld)
{
return;
}
BOPTools_AlgoTools2D::CurveOnSurface(aE, aF, aC2D, aTolPC, theContext);
aTolEdge = BRep_Tool::Tolerance(aE);
aTolFact = std::max(aTolEdge, aTolPC);
aBB.UpdateEdge(aE, aC2D, aF, aTolFact);
}
//=================================================================================================
bool BOPTools_AlgoTools2D::EdgeTangent(const TopoDS_Edge& anEdge, const double aT, gp_Vec& aTau)
{
bool isdgE;
double first, last;
isdgE = BRep_Tool::Degenerated(anEdge);
if (isdgE)
{
return false;
}
occ::handle<Geom_Curve> aC = BRep_Tool::Curve(anEdge, first, last);
gp_Pnt aP;
aC->D1(aT, aP, aTau);
double mod = aTau.Magnitude();
if (mod > gp::Resolution())
{
aTau /= mod;
}
else
{
return false;
}
// aTau.Normalize();
if (anEdge.Orientation() == TopAbs_REVERSED)
{
aTau.Reverse();
}
return true;
}
//=================================================================================================
void BOPTools_AlgoTools2D::PointOnSurface(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
const double aParameter,
double& U,
double& V,
const occ::handle<IntTools_Context>& theContext)
{
gp_Pnt2d aP2D;
occ::handle<Geom2d_Curve> aC2D;
double aToler, aFirst, aLast;
BOPTools_AlgoTools2D::CurveOnSurface(aE, aF, aC2D, aFirst, aLast, aToler, theContext);
aC2D->D0(aParameter, aP2D);
U = aP2D.X();
V = aP2D.Y();
}
//=================================================================================================
void BOPTools_AlgoTools2D::CurveOnSurface(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
occ::handle<Geom2d_Curve>& aC2D,
double& aToler,
const occ::handle<IntTools_Context>& theContext)
{
double aFirst, aLast;
//
BOPTools_AlgoTools2D::CurveOnSurface(aE, aF, aC2D, aFirst, aLast, aToler, theContext);
//
}
//=================================================================================================
void BOPTools_AlgoTools2D::CurveOnSurface(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
occ::handle<Geom2d_Curve>& aC2D,
double& aFirst,
double& aLast,
double& aToler,
const occ::handle<IntTools_Context>& theContext)
{
bool aHasOld;
occ::handle<Geom2d_Curve> C2D;
aHasOld = BOPTools_AlgoTools2D::HasCurveOnSurface(aE, aF, C2D, aFirst, aLast, aToler);
if (aHasOld)
{
aC2D = C2D;
return;
}
BOPTools_AlgoTools2D::Make2D(aE, aF, C2D, aFirst, aLast, aToler, theContext);
aC2D = C2D;
}
//=================================================================================================
bool BOPTools_AlgoTools2D::HasCurveOnSurface(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
occ::handle<Geom2d_Curve>& aC2D,
double& aFirst,
double& aLast,
double& aToler)
{
bool aHasOld;
aToler = BRep_Tool::Tolerance(aE);
BRep_Tool::Range(aE, aFirst, aLast);
if ((aLast - aFirst) < Precision::PConfusion())
{
return false;
}
aC2D = BRep_Tool::CurveOnSurface(aE, aF, aFirst, aLast);
aHasOld = !aC2D.IsNull();
return aHasOld;
}
//=================================================================================================
bool BOPTools_AlgoTools2D::HasCurveOnSurface(const TopoDS_Edge& aE, const TopoDS_Face& aF)
{
bool bHasOld;
occ::handle<Geom2d_Curve> aC2D;
double aFirst, aLast;
//
BRep_Tool::Range(aE, aFirst, aLast);
//
if ((aLast - aFirst) < Precision::PConfusion())
{
return false;
}
//
aC2D = BRep_Tool::CurveOnSurface(aE, aF, aFirst, aLast);
bHasOld = !aC2D.IsNull();
//
return bHasOld;
}
//=================================================================================================
void BOPTools_AlgoTools2D::AdjustPCurveOnFace(const TopoDS_Face& theF,
const occ::handle<Geom_Curve>& theC3D,
const occ::handle<Geom2d_Curve>& theC2D,
occ::handle<Geom2d_Curve>& theC2DA,
const occ::handle<IntTools_Context>& theContext)
{
double aT1 = theC3D->FirstParameter();
double aT2 = theC3D->LastParameter();
//
BOPTools_AlgoTools2D::AdjustPCurveOnFace(theF, aT1, aT2, theC2D, theC2DA, theContext);
}
//=================================================================================================
void BOPTools_AlgoTools2D::AdjustPCurveOnFace(const TopoDS_Face& theF,
const double theFirst,
const double theLast,
const occ::handle<Geom2d_Curve>& theC2D,
occ::handle<Geom2d_Curve>& theC2DA,
const occ::handle<IntTools_Context>& theContext)
{
BRepAdaptor_Surface aBASTmp;
const BRepAdaptor_Surface* pBAS;
if (!theContext.IsNull())
{
pBAS = &theContext->SurfaceAdaptor(theF);
}
else
{
aBASTmp.Initialize(theF, true);
pBAS = &aBASTmp;
}
//
BOPTools_AlgoTools2D::AdjustPCurveOnSurf(*pBAS, theFirst, theLast, theC2D, theC2DA);
}
//=================================================================================================
void BOPTools_AlgoTools2D::AdjustPCurveOnSurf(const BRepAdaptor_Surface& aBAS,
const double aFirst,
const double aLast,
const occ::handle<Geom2d_Curve>& aC2D,
occ::handle<Geom2d_Curve>& aC2DA)
{
bool mincond, maxcond;
double UMin, UMax, VMin, VMax, aT, u2, v2, du, dv, aDelta;
double aUPeriod;
//
const TopoDS_Face& aF = aBAS.Face();
UMin = aBAS.FirstUParameter();
UMax = aBAS.LastUParameter();
VMin = aBAS.FirstVParameter();
VMax = aBAS.LastVParameter();
//
aDelta = Precision::PConfusion();
aT = .5 * (aFirst + aLast);
gp_Pnt2d pC2D;
aC2D->D0(aT, pC2D);
u2 = pC2D.X();
v2 = pC2D.Y();
//
// du
du = 0.;
if (aBAS.IsUPeriodic())
{
aUPeriod = aBAS.UPeriod();
//
// a. try to clarify u2 using the precision (aDelta)
if (fabs(u2 - UMin) < aDelta)
{
u2 = UMin;
}
else if (fabs(u2 - UMin - aUPeriod) < aDelta)
{
u2 = UMin + aUPeriod;
}
// b. compute du again using clarified value of u2
GeomInt::AdjustPeriodic(u2, UMin, UMax, aUPeriod, u2, du, 0.);
//
if (du == 0.)
{
if (aBAS.GetType() == GeomAbs_Cylinder)
{
double aR, dFi, aTol;
//
gp_Cylinder aCylinder = aBAS.Cylinder();
aR = aCylinder.Radius();
aTol = MaxToleranceEdge(aF);
dFi = aTol / aR;
if (dFi < aDelta)
{
dFi = aDelta;
}
//
mincond = (UMin - u2 > dFi);
maxcond = (u2 - UMax > dFi);
if (mincond || maxcond)
{
du = (mincond) ? aUPeriod : -aUPeriod;
}
}
}
}
// dv
dv = 0.;
if (aBAS.IsVPeriodic())
{
double aVPeriod, aVm, aVr, aVmid, dVm, dVr;
//
aVPeriod = aBAS.VPeriod();
mincond = (VMin - v2 > aDelta);
maxcond = (v2 - VMax > aDelta);
//
if (mincond || maxcond)
{
dv = (mincond) ? aVPeriod : -aVPeriod;
}
//
if ((VMax - VMin < aVPeriod) && dv)
{
aVm = v2;
aVr = v2 + dv;
aVmid = 0.5 * (VMin + VMax);
dVm = fabs(aVm - aVmid);
dVr = fabs(aVr - aVmid);
if (dVm < dVr)
{
dv = 0.;
}
}
}
//
{
// check the point with classifier
double u, v;
u = u2 + du;
v = v2 + dv;
if (aBAS.IsUPeriodic())
{
aUPeriod = aBAS.UPeriod();
if ((UMax - UMin - 2 * aDelta) > aUPeriod)
{
if ((u > (UMin + aDelta + aUPeriod)) || (u < (UMax - aDelta - aUPeriod)))
{
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(aF, gp_Pnt2d(u, v), aDelta);
TopAbs_State Status = aClassifier.State();
if (Status == TopAbs_OUT)
{
du += (u > (UMin + aDelta + aUPeriod)) ? -aUPeriod : aUPeriod;
}
}
}
}
//
u = u2 + du;
if (aBAS.IsVPeriodic())
{
double aVPeriod = aBAS.VPeriod();
if ((VMax - VMin - 2 * aDelta) > aVPeriod)
{
if ((v > (VMin + aDelta + aVPeriod)) || (v < (VMax - aDelta - aVPeriod)))
{
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(aF, gp_Pnt2d(u, v), aDelta);
TopAbs_State Status = aClassifier.State();
if (Status == TopAbs_OUT)
{
dv += (v > (VMin + aDelta + aVPeriod)) ? -aVPeriod : aVPeriod;
}
}
}
}
}
// Translation if necessary
occ::handle<Geom2d_Curve> aC2Dx = aC2D;
if (du != 0. || dv != 0.)
{
occ::handle<Geom2d_Curve> PCT = occ::down_cast<Geom2d_Curve>(aC2Dx->Copy());
gp_Vec2d aV2D(du, dv);
PCT->Translate(aV2D);
aC2Dx = PCT;
}
aC2DA = aC2Dx;
}
//=================================================================================================
double BOPTools_AlgoTools2D::IntermediatePoint(const double aFirst, const double aLast)
{
// define parameter division number as 10*e^(-PI) = 0.43213918
const double PAR_T = 0.43213918;
double aParm;
aParm = (1. - PAR_T) * aFirst + PAR_T * aLast;
return aParm;
}
//=================================================================================================
double BOPTools_AlgoTools2D::IntermediatePoint(const TopoDS_Edge& aE)
{
double aT, aT1, aT2;
occ::handle<Geom_Curve> aC1 = BRep_Tool::Curve(aE, aT1, aT2);
if (aC1.IsNull())
{
BRep_Tool::Range(aE, aT1, aT2);
}
aT = BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
return aT;
}
//=================================================================================================
void BOPTools_AlgoTools2D::Make2D(const TopoDS_Edge& aE,
const TopoDS_Face& aF,
occ::handle<Geom2d_Curve>& aC2D,
double& aFirst,
double& aLast,
double& aToler,
const occ::handle<IntTools_Context>& theContext)
{
bool aLocIdentity;
double f3d, l3d;
TopLoc_Location aLoc;
occ::handle<Geom2d_Curve> C2D;
C2D = BRep_Tool::CurveOnSurface(aE, aF, aFirst, aLast);
if (!C2D.IsNull())
{
aC2D = C2D;
return;
}
occ::handle<Geom_Curve> C3D2, C3D;
C3D = BRep_Tool::Curve(aE, aLoc, f3d, l3d);
//
if (C3D.IsNull())
{
// aE has no 3D curve, so nothing is done
}
//
aLocIdentity = aLoc.IsIdentity();
if (aLocIdentity)
{
C3D2 = C3D;
}
else
{
C3D2 = occ::down_cast<Geom_Curve>(C3D->Transformed(aLoc.Transformation()));
}
//
aToler = BRep_Tool::Tolerance(aE);
BOPTools_AlgoTools2D::MakePCurveOnFace(aF, C3D2, f3d, l3d, aC2D, aToler, theContext);
//
aFirst = f3d;
aLast = l3d;
}
//=================================================================================================
void BOPTools_AlgoTools2D::MakePCurveOnFace(const TopoDS_Face& aF,
const occ::handle<Geom_Curve>& aC3D,
occ::handle<Geom2d_Curve>& aC2D, //->
double& TolReached2d,
const occ::handle<IntTools_Context>& theContext)
{
double aFirst, aLast;
aFirst = aC3D->FirstParameter();
aLast = aC3D->LastParameter();
//
TolReached2d = 0.;
//
BOPTools_AlgoTools2D::MakePCurveOnFace(aF, aC3D, aFirst, aLast, aC2D, TolReached2d, theContext);
}
//=================================================================================================
void BOPTools_AlgoTools2D::MakePCurveOnFace(const TopoDS_Face& aF,
const occ::handle<Geom_Curve>& aC3D,
const double aT1,
const double aT2,
occ::handle<Geom2d_Curve>& aC2D,
double& TolReached2d,
const occ::handle<IntTools_Context>& theContext)
{
BRepAdaptor_Surface aBASTmp;
const BRepAdaptor_Surface* pBAS;
if (!theContext.IsNull())
{
pBAS = &theContext->SurfaceAdaptor(aF);
}
else
{
aBASTmp.Initialize(aF, true);
pBAS = &aBASTmp;
}
//
occ::handle<BRepAdaptor_Surface> aBAHS = new BRepAdaptor_Surface(*pBAS);
occ::handle<GeomAdaptor_Curve> aBAHC = new GeomAdaptor_Curve(aC3D, aT1, aT2);
//
double aTolR;
double aTR = Precision::Confusion(); // 1.e-7;
double aMaxTol = 1.e3 * aTR; // 0.0001
bool isAnaSurf = ProjLib::IsAnaSurf(aBAHS);
// when the type of surface is GeomAbs_SurfaceOfRevolution
if (pBAS->GetType() == GeomAbs_SurfaceOfRevolution)
{
if (TolReached2d > aTR)
{
aTR = TolReached2d;
}
//
ProjLib_ProjectedCurve aProj1(aBAHS, aBAHC, aTR);
ProjLib::MakePCurveOfType(aProj1, aC2D);
aTolR = aProj1.GetTolerance();
}
else
{
ProjLib_ProjectedCurve aProjCurv(aBAHS);
int aDegMin = -1, aDegMax = -1, aMaxSegments = -1;
double aMaxDist = -1;
AppParCurves_Constraint aBndPnt = AppParCurves_TangencyPoint;
bool isExtendSurf = false;
if ((TolReached2d >= 10. * aTR) && (TolReached2d <= aMaxTol || isAnaSurf))
{
aTR = std::min(aMaxTol, 0.1 * TolReached2d);
aMaxSegments = 100;
aMaxDist = 1.e3 * TolReached2d;
if (!isAnaSurf || TolReached2d > 1.)
{
aBndPnt = AppParCurves_PassPoint;
}
isExtendSurf = true;
}
else if (TolReached2d > aMaxTol)
{
aTR = std::min(TolReached2d, 1.e3 * aMaxTol);
aMaxDist = 1.e2 * aTR;
aMaxSegments = 100;
isExtendSurf = true;
}
if (isExtendSurf)
{
occ::handle<Adaptor3d_Surface> anA3dSurf;
double dt = (aBAHS->LastUParameter() - aBAHS->FirstUParameter());
if (!aBAHS->IsUPeriodic() || std::abs(dt - aBAHS->UPeriod()) > 0.01 * dt)
{
dt *= 0.01;
anA3dSurf = aBAHS->UTrim(aBAHS->FirstUParameter() - dt, aBAHS->LastUParameter() + dt, 0.);
}
dt = (aBAHS->LastVParameter() - aBAHS->FirstVParameter());
if (!aBAHS->IsVPeriodic() || std::abs(dt - aBAHS->VPeriod()) > 0.01 * dt)
{
dt *= 0.01;
anA3dSurf = aBAHS->VTrim(aBAHS->FirstVParameter() - dt, aBAHS->LastVParameter() + dt, 0.);
}
if (!anA3dSurf.IsNull())
{
aProjCurv.Load(anA3dSurf);
}
}
aProjCurv.Load(aTR);
aProjCurv.SetDegree(aDegMin, aDegMax);
aProjCurv.SetMaxSegments(aMaxSegments);
aProjCurv.SetBndPnt(aBndPnt);
aProjCurv.SetMaxDist(aMaxDist);
aProjCurv.Perform(aBAHC);
ProjLib::MakePCurveOfType(aProjCurv, aC2D);
aTolR = aProjCurv.GetTolerance();
}
//
if (aC2D.IsNull() && (aTR < aMaxTol || aTR < TolReached2d))
{
aTR = std::max(TolReached2d, aMaxTol);
ProjLib_ProjectedCurve aProjCurvAgain(aBAHS, aBAHC, aTR); // 2
ProjLib::MakePCurveOfType(aProjCurvAgain, aC2D);
aTolR = aProjCurvAgain.GetTolerance();
}
//
if (aC2D.IsNull())
{
throw Standard_ConstructionError("BOPTools_AlgoTools2D::MakePCurveOnFace : PCurve is Null");
}
//
TolReached2d = aTolR;
// Adjust curve for periodic surface
occ::handle<Geom2d_Curve> aC2DA;
BOPTools_AlgoTools2D::AdjustPCurveOnSurf(*pBAS, aT1, aT2, aC2D, aC2DA);
aC2D = aC2DA;
// Make sure that the range of the 2D curve is sufficient for representation of the 3D curve.
double aTCFirst = aC2D->FirstParameter();
double aTCLast = aC2D->LastParameter();
if ((aTCFirst - aT1) > Precision::PConfusion() || (aT2 - aTCLast) > Precision::PConfusion())
{
if (aTCFirst < aT1)
{
aTCFirst = aT1;
}
if (aTCLast > aT2)
{
aTCLast = aT2;
}
GeomLib::SameRange(Precision::PConfusion(), aC2D, aTCFirst, aTCLast, aT1, aT2, aC2D);
}
// compute the appropriate tolerance for the edge
const occ::handle<Geom_Surface> aS = pBAS->GeomSurfaceTransformed();
//
double aT;
if (IntTools_Tools::ComputeTolerance(aC3D, aC2D, aS, aT1, aT2, aTolR, aT))
{
if (aTolR > TolReached2d)
{
TolReached2d = aTolR;
}
}
}
//=================================================================================================
double MaxToleranceEdge(const TopoDS_Face& aF)
{
double aTol, aTolMax;
TopExp_Explorer aExp;
//
aTolMax = 0.;
aExp.Init(aF, TopAbs_EDGE);
for (; aExp.More(); aExp.Next())
{
const TopoDS_Edge& aE = *((TopoDS_Edge*)&aExp.Current());
aTol = BRep_Tool::Tolerance(aE);
if (aTol > aTolMax)
{
aTolMax = aTol;
}
}
return aTolMax;
}
//=================================================================================================
void BOPTools_AlgoTools2D::IsEdgeIsoline(const TopoDS_Edge& theE,
const TopoDS_Face& theF,
bool& isTheUIso,
bool& isTheVIso)
{
isTheUIso = isTheVIso = false;
gp_Vec2d aT;
gp_Pnt2d aP;
double aFirst = 0.0, aLast = 0.0;
const occ::handle<Geom2d_Curve> aPC = BRep_Tool::CurveOnSurface(theE, theF, aFirst, aLast);
aPC->D1(0.5 * (aFirst + aLast), aP, aT);
const double aSqMagn = aT.SquareMagnitude();
if (aSqMagn <= gp::Resolution())
{
return;
}
// Normalize aT
aT /= sqrt(aSqMagn);
// sin(da) ~ da, when da->0.
constexpr double aTol = Precision::Angular();
const gp_Vec2d aRefVDir(0.0, 1.0), aRefUDir(1.0, 0.0);
const double aDPv = aT.CrossMagnitude(aRefVDir), aDPu = aT.CrossMagnitude(aRefUDir);
isTheUIso = (aDPv <= aTol);
isTheVIso = (aDPu <= aTol);
}