Loading files
4f95ecaa3This file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1994-11-14
// Created by: Bruno DUMORTIER
// Copyright (c) 1994-1999 Matra Datavision
// 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 <BRepFill_MultiLine.hxx>
#include <BRepIntCurveSurface_Inter.hxx>
#include <gp.hxx>
#include <gp_Ax3.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Circ2d.hxx>
#include <Precision.hxx>
#include <BRep_Tool.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom_Surface.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom2d_Line.hxx>
#include <GeomProjLib.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <Standard_ConstructionError.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <ElCLib.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomAbs_SurfaceType.hxx>
// POP pour NT
#include <cstdio>
//=================================================================================================
static bool isIsoU(const TopoDS_Face& Face, const TopoDS_Edge& Edge)
{
occ::handle<Geom2d_Curve> C;
occ::handle<Geom2d_Line> Li;
double f, l;
C = BRep_Tool::CurveOnSurface(Edge, Face, f, l);
if (C.IsNull())
{
throw Standard_ConstructionError("BRepFill_MultiLine : Edge without PCurve");
}
gp_Dir2d D = C->DN(f, 1);
return std::abs(D.Dot(gp::DX2d())) < std::abs(D.Dot(gp::DY2d()));
}
//=================================================================================================
BRepFill_MultiLine::BRepFill_MultiLine()
{
myNbPnt2d = 2;
myNbPnt = 1;
}
//=================================================================================================
BRepFill_MultiLine::BRepFill_MultiLine(const TopoDS_Face& Face1,
const TopoDS_Face& Face2,
const TopoDS_Edge& Edge1,
const TopoDS_Edge& Edge2,
const bool Inv1,
const bool Inv2,
const occ::handle<Geom2d_Curve>& Bissec)
: myFace1(Face1),
myFace2(Face2),
myBis(Bissec),
myKPart(0)
{
//
constexpr double mult = 5.;
constexpr double eps = mult * Precision::Confusion();
//
myNbPnt2d = 2;
myNbPnt = 1;
// eval if myedges are IsoU or not
myIsoU1 = isIsoU(Face1, Edge1);
myIsoU2 = isIsoU(Face2, Edge2);
// eval myU1, myV1, myU2, myV2;
occ::handle<Geom_Plane> RefPlane;
occ::handle<Geom_Plane> BasisPlane = new Geom_Plane(0., 0., 1., 0.);
TopLoc_Location L;
TopExp_Explorer Exp;
double Umin = 0., Vmin = 0., Umax = 0., Vmax = 0., U, V;
gp_Pnt2d P1, P2;
gp_Vec DZ;
gp_Pnt P;
// Result on Face1
bool First = true;
for (Exp.Init(myFace1, TopAbs_EDGE); Exp.More(); Exp.Next())
{
TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
BRep_Tool::UVPoints(CurEdge, myFace1, P1, P2);
if (First)
{
First = false;
Umin = std::min(P1.X(), P2.X());
Umax = std::max(P1.X(), P2.X());
Vmin = std::min(P1.Y(), P2.Y());
Vmax = std::max(P1.Y(), P2.Y());
}
else
{
U = std::min(P1.X(), P2.X());
Umin = std::min(Umin, U);
U = std::max(P1.X(), P2.X());
Umax = std::max(Umax, U);
V = std::min(P1.Y(), P2.Y());
Vmin = std::min(Vmin, V);
V = std::max(P1.Y(), P2.Y());
Vmax = std::max(Vmax, V);
}
}
// return isos in their domain of restriction.
occ::handle<Geom_Curve> UU1, UU2, VV1, VV2;
occ::handle<Geom_Surface> S;
S = BRep_Tool::Surface(myFace1, L);
if (!L.IsIdentity())
{
S = occ::down_cast<Geom_Surface>(S->Transformed(L.Transformation()));
}
if (myIsoU1)
{
if (!BRep_Tool::Degenerated(Edge1) && !Inv1)
{
UU1 = S->UIso(Umin);
GeomAdaptor_Curve Dummy(UU1);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU1 = S->UIso(Umax);
}
}
else
{
UU1 = S->UIso(Umax);
GeomAdaptor_Curve Dummy(UU1);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU1 = S->UIso(Umin);
}
}
VV1 = S->VIso(Vmin);
}
else
{
if (!BRep_Tool::Degenerated(Edge1) && !Inv1)
{
UU1 = S->VIso(Vmin);
GeomAdaptor_Curve Dummy(UU1);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU1 = S->VIso(Vmax);
}
}
else
{
UU1 = S->VIso(Vmax);
GeomAdaptor_Curve Dummy(UU1);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU1 = S->VIso(Vmin);
}
}
VV1 = S->UIso(Umin);
}
if (myIsoU1)
{
double dummyUmin = Umin, dummyUmax = Umax;
Umin = Vmin;
Umax = Vmax;
Vmin = dummyUmin;
Vmax = dummyUmax;
}
// try duplication
GeomAdaptor_Surface GAS1(S);
GeomAbs_SurfaceType Type1 = GAS1.GetType();
if (UU1->IsPeriodic())
{
ElCLib::AdjustPeriodic(UU1->FirstParameter(),
UU1->LastParameter(),
Precision::PConfusion(),
Umin,
Umax);
}
if (VV1->IsPeriodic())
{
ElCLib::AdjustPeriodic(VV1->FirstParameter(),
VV1->LastParameter(),
Precision::PConfusion(),
Vmin,
Vmax);
}
// end try duplication
myU1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU1, BasisPlane), Umin, Umax);
UU1->D1(Umin, P, DZ);
RefPlane = new Geom_Plane(gp_Ax3(P, DZ, gp::DZ()));
myV1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV1, RefPlane), Vmin, Vmax);
First = true;
for (Exp.Init(myFace2, TopAbs_EDGE); Exp.More(); Exp.Next())
{
TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
BRep_Tool::UVPoints(CurEdge, myFace2, P1, P2);
if (First)
{
First = false;
Umin = std::min(P1.X(), P2.X());
Umax = std::max(P1.X(), P2.X());
Vmin = std::min(P1.Y(), P2.Y());
Vmax = std::max(P1.Y(), P2.Y());
}
else
{
U = std::min(P1.X(), P2.X());
Umin = std::min(Umin, U);
U = std::max(P1.X(), P2.X());
Umax = std::max(Umax, U);
V = std::min(P1.Y(), P2.Y());
Vmin = std::min(Vmin, V);
V = std::max(P1.Y(), P2.Y());
Vmax = std::max(Vmax, V);
}
}
// return isos in their domain of restriction.
S = BRep_Tool::Surface(myFace2, L);
if (!L.IsIdentity())
{
S = occ::down_cast<Geom_Surface>(S->Transformed(L.Transformation()));
}
if (myIsoU2)
{
if (!BRep_Tool::Degenerated(Edge2) && !Inv2)
{
UU2 = S->UIso(Umin);
GeomAdaptor_Curve Dummy(UU2);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU2 = S->UIso(Umax);
}
}
else
{
UU2 = S->UIso(Umax);
GeomAdaptor_Curve Dummy(UU2);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU2 = S->UIso(Umin);
}
}
VV2 = S->VIso(Vmin);
}
else
{
if (!BRep_Tool::Degenerated(Edge2) && !Inv2)
{
UU2 = S->VIso(Vmin);
GeomAdaptor_Curve Dummy(UU2);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU2 = S->VIso(Vmax);
}
}
else
{
UU2 = S->VIso(Vmax);
GeomAdaptor_Curve Dummy(UU2);
if (Dummy.GetType() == GeomAbs_Circle && Dummy.Circle().Radius() < eps)
{
UU2 = S->VIso(Vmin);
}
}
VV2 = S->UIso(Umin);
}
if (myIsoU2)
{
double dummyUmin = Umin, dummyUmax = Umax;
Umin = Vmin;
Umax = Vmax;
Vmin = dummyUmin;
Vmax = dummyUmax;
}
// try duplication
GeomAdaptor_Surface GAS2(S);
GeomAbs_SurfaceType Type2 = GAS2.GetType();
if (UU2->IsPeriodic())
{
ElCLib::AdjustPeriodic(UU2->FirstParameter(),
UU2->LastParameter(),
Precision::PConfusion(),
Umin,
Umax);
}
if (VV2->IsPeriodic())
{
ElCLib::AdjustPeriodic(VV2->FirstParameter(),
VV2->LastParameter(),
Precision::PConfusion(),
Vmin,
Vmax);
}
// end try duplication
myU2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU2, BasisPlane), Umin, Umax);
UU2->D1(Umin, P, DZ);
RefPlane = new Geom_Plane(gp_Ax3(P, DZ, gp::DZ()));
myV2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV2, RefPlane), Vmin, Vmax);
// eval if in a particular case.
// Particular case if :
// 1) - Straight Bissectrice
// - Bissectrice orthogonal to the base element.
// ==> Iso on 2 faces.
// 2) - Straight Bissectrice
// - 2 surfaces are planes.
myCont = GeomAbs_C0;
if (myBis.GetType() == GeomAbs_Line)
{
double DeltaU = myBis.LastParameter() - myBis.FirstParameter();
gp_Pnt2d aPnt1 = ValueOnF1(myBis.FirstParameter() + 0.1 * DeltaU);
gp_Pnt2d aPnt2 = ValueOnF1(myBis.FirstParameter() + 0.9 * DeltaU);
if (myIsoU1)
{
if (std::abs(aPnt1.Y() - aPnt2.Y()) < eps)
{
myKPart = 1;
}
}
else
{
if (std::abs(aPnt1.X() - aPnt2.X()) < eps)
{
myKPart = 1;
}
}
if (myKPart == 1)
{
myCont = GeomAbs_G1;
}
if ((Type1 == GeomAbs_Plane) && (Type2 == GeomAbs_Plane))
{
myKPart = 2;
}
}
}
//=================================================================================================
bool BRepFill_MultiLine::IsParticularCase() const
{
return (myKPart != 0);
}
//=================================================================================================
void BRepFill_MultiLine::Curves(occ::handle<Geom_Curve>& Curve,
occ::handle<Geom2d_Curve>& PCurve1,
occ::handle<Geom2d_Curve>& PCurve2) const
{
if (myKPart == 1)
{
gp_Pnt2d P1, P2, PMil;
double f, l;
P1 = ValueOnF1(myBis.FirstParameter());
P2 = ValueOnF1(myBis.LastParameter());
// find value of the with medium point
// the ends can be degenerated points.
PMil = ValueOnF1(0.5 * (myBis.FirstParameter() + myBis.LastParameter()));
TopLoc_Location L;
occ::handle<Geom_Surface> S = BRep_Tool::Surface(myFace1, L);
if (!L.IsIdentity())
{
S = occ::down_cast<Geom_Surface>(S->Transformed(L.Transformation()));
}
bool Sens;
if (!myIsoU1)
{
Curve = S->UIso(PMil.X());
Sens = P1.Y() < P2.Y();
if (Sens)
{
Curve = new Geom_TrimmedCurve(Curve, P1.Y(), P2.Y(), Sens);
}
else
{
Curve = new Geom_TrimmedCurve(Curve, P2.Y(), P1.Y(), Sens);
}
f = Curve->FirstParameter();
l = Curve->LastParameter();
if (Sens)
{
PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(), P1.Y() - f), gp::DY2d());
}
else
{
PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(), P1.Y() + f), -gp::DY2d());
}
PCurve1 = new Geom2d_TrimmedCurve(PCurve1, f, l);
}
else
{
Curve = S->VIso(PMil.Y());
Sens = P1.X() < P2.X();
if (Sens)
{
Curve = new Geom_TrimmedCurve(Curve, P1.X(), P2.X(), Sens);
}
else
{
Curve = new Geom_TrimmedCurve(Curve, P2.X(), P1.X(), Sens);
}
f = Curve->FirstParameter();
l = Curve->LastParameter();
if (Sens)
{
PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() - f, PMil.Y()), gp::DX2d());
}
else
{
PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() + f, PMil.Y()), -gp::DX2d());
}
PCurve1 = new Geom2d_TrimmedCurve(PCurve1, f, l);
}
P1 = ValueOnF2(myBis.FirstParameter());
P2 = ValueOnF2(myBis.LastParameter());
PMil = ValueOnF2(0.5 * (myBis.FirstParameter() + myBis.LastParameter()));
if (!myIsoU2)
{
Sens = P1.Y() < P2.Y();
if (Sens)
{
PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(), (P1.Y() - f)), gp::DY2d());
}
else
{
PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(), (P1.Y() + f)), -gp::DY2d());
}
}
else
{
Sens = P1.X() < P2.X();
if (Sens)
{
PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() - f, PMil.Y()), gp::DX2d());
}
else
{
PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() + f, PMil.Y()), -gp::DX2d());
}
}
PCurve2 = new Geom2d_TrimmedCurve(PCurve2, f, l);
}
else if (myKPart == 2)
{
TopLoc_Location L;
occ::handle<Geom_Surface> S = BRep_Tool::Surface(myFace1, L);
if (!L.IsIdentity())
{
S = occ::down_cast<Geom_Surface>(S->Transformed(L.Transformation()));
}
if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
{
S = occ::down_cast<Geom_RectangularTrimmedSurface>(S)->BasisSurface();
}
occ::handle<Geom_Plane> Plane = occ::down_cast<Geom_Plane>(S);
// eval the 3d curve corresponding to the bissectrice.
gp_Pnt2d P = myBis.Line().Location();
gp_Dir2d D = myBis.Line().Direction();
occ::handle<Geom_Line> Line = new Geom_Line(gp_Pnt(P.X(), P.Y(), 0.), gp_Dir(D.X(), D.Y(), 0.));
occ::handle<Geom_TrimmedCurve> TLine =
new Geom_TrimmedCurve(Line, myBis.FirstParameter(), myBis.LastParameter());
Curve = GeomProjLib::ProjectOnPlane(TLine, Plane, gp::DZ(), false);
// eval PCurve1
PCurve1 = GeomProjLib::Curve2d(Curve, Plane);
// eval PCurve2
S = BRep_Tool::Surface(myFace2, L);
if (!L.IsIdentity())
{
S = occ::down_cast<Geom_Surface>(S->Transformed(L.Transformation()));
}
if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
{
S = occ::down_cast<Geom_RectangularTrimmedSurface>(S)->BasisSurface();
}
Plane = occ::down_cast<Geom_Plane>(S);
PCurve2 = GeomProjLib::Curve2d(Curve, Plane);
}
}
//=================================================================================================
double BRepFill_MultiLine::FirstParameter() const
{
return myBis.FirstParameter();
}
//=================================================================================================
double BRepFill_MultiLine::LastParameter() const
{
return myBis.LastParameter();
}
//=================================================================================================
gp_Pnt BRepFill_MultiLine::Value(const double U) const
{
occ::handle<Geom_Surface> S;
TopLoc_Location L;
S = BRep_Tool::Surface(myFace1, L);
gp_Pnt2d P2d = ValueOnF1(U);
gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
P3d.Transform(L.Transformation());
return P3d;
}
//=================================================================================================
static gp_Pnt2d ValueOnFace(const double U,
const Geom2dAdaptor_Curve& TheBis,
const Geom2dAdaptor_Curve& TheU,
const Geom2dAdaptor_Curve& TheV,
const bool IsIsoU)
{
gp_Pnt2d P = TheBis.Value(U);
Geom2dAPI_ProjectPointOnCurve Ext(P, TheU.Curve(), TheU.FirstParameter(), TheU.LastParameter());
//
constexpr double mult = 5.;
constexpr double eps = mult * Precision::Confusion();
//
double UU = 0., Dist = Precision::Infinite(), D1, D2;
if (Ext.NbPoints() != 0)
{
UU = Ext.LowerDistanceParameter();
Dist = Ext.LowerDistance();
}
// Control with `ends`
D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
D2 = P.Distance(TheU.Value(TheU.LastParameter()));
if (D1 < Dist || D2 < Dist || std::abs(D1 - Dist) < eps || std::abs(D2 - Dist) < eps)
{
if (std::abs(D1 - D2) < eps)
{
if (TheU.GetType() == GeomAbs_Circle)
{
gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(), 1);
double Ang = Axis.Angle(D12d);
if (!TheU.Circle().IsDirect())
{
Ang = -Ang;
}
UU = ElCLib::InPeriod(Ang, TheU.FirstParameter(), TheU.FirstParameter() + 2 * M_PI);
Dist = TheU.Circle().Radius();
}
else
{
#ifdef OCCT_DEBUG
std::cout << "MultiLine : D1 = D2 and the Curve is not a circle" << std::endl;
std::cout << " ---> ValueOnFace failed at parameter U = " << U << std::endl;
#endif
throw Standard_ConstructionError("BRepFill_MultiLine: ValueOnFace");
}
}
else if (D1 < D2)
{
Dist = D1;
UU = TheU.FirstParameter();
}
else
{
Dist = D2;
UU = TheU.LastParameter();
}
}
constexpr double Tol = Precision::Confusion();
double VV;
gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
gp_Pnt2d PL = TheV.Value(TheV.LastParameter());
if (std::abs(Dist - std::abs(PF.Y())) < Tol)
{
VV = TheV.FirstParameter();
}
else if (std::abs(Dist - std::abs(PL.Y())) < Tol)
{
VV = TheV.LastParameter();
}
else
{
// test if the curve is at the side `negative Y`.
if (std::min(PF.Y(), PL.Y()) < -Tol)
{
Dist = -Dist;
}
occ::handle<Geom2d_Line> Line = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
const Geom2dAdaptor_Curve& Cu1 = TheV;
Geom2dAdaptor_Curve Cu2(Line);
double TolConf = 0.;
Geom2dInt_GInter Intersector(Cu1, Cu2, TolConf, Tol);
if (!Intersector.IsDone())
{
#ifdef OCCT_DEBUG
std::cout << "Intersector not done" << std::endl;
std::cout << " ---> ValueonFace failed at parameter U = " << U << std::endl;
#endif
return gp_Pnt2d(0., 0.);
}
else
{
if (Intersector.NbPoints() > 0)
{
VV = Intersector.Point(1).ParamOnFirst();
}
else if (Intersector.NbSegments() > 0)
{
IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
double VS1 = Seg.FirstPoint().ParamOnFirst();
double VS2 = Seg.LastPoint().ParamOnFirst();
gp_Pnt2d PS1 = TheV.Value(VS1);
gp_Pnt2d PS2 = TheV.Value(VS2);
double Alp = (Dist - PS1.Y()) / (PS2.Y() - PS1.Y());
VV = Alp * (VS2 - VS1) + VS1;
}
else
{
#ifdef OCCT_DEBUG
std::cout << "Intersector done, but no points found" << std::endl;
std::cout << " ---> ValueonFace failed at parameter U = " << U << std::endl;
#endif
if (std::abs(Dist - PL.Y()) < std::abs(Dist - PF.Y()))
{
VV = TheV.LastParameter();
}
else
{
VV = TheV.FirstParameter();
}
}
}
}
if (IsIsoU)
{
return gp_Pnt2d(VV, UU);
}
else
{
return gp_Pnt2d(UU, VV);
}
}
//=================================================================================================
gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const double U) const
{
return ValueOnFace(U, myBis, myU1, myV1, myIsoU1);
}
//=================================================================================================
gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const double U) const
{
return ValueOnFace(U, myBis, myU2, myV2, myIsoU2);
}
//=================================================================================================
void BRepFill_MultiLine::Value3dOnF1OnF2(const double U,
gp_Pnt& P3d,
gp_Pnt2d& PF1,
gp_Pnt2d& PF2) const
{
PF1 = ValueOnFace(U, myBis, myU1, myV1, myIsoU1);
PF2 = ValueOnFace(U, myBis, myU2, myV2, myIsoU2);
occ::handle<Geom_Surface> S;
TopLoc_Location L;
S = BRep_Tool::Surface(myFace1, L);
P3d = S->Value(PF1.X(), PF1.Y());
P3d.Transform(L.Transformation());
}
//=================================================================================================
GeomAbs_Shape BRepFill_MultiLine::Continuity() const
{
return myCont;
}
//=================================================================================================
bool BRepFill_MultiLine::Value(const double theT,
NCollection_Array1<gp_Pnt2d>& thePnt2d,
NCollection_Array1<gp_Pnt>& thePnt) const
{
thePnt(1) = Value(theT);
thePnt2d(1) = ValueOnF1(theT);
thePnt2d(2) = ValueOnF2(theT);
return true;
}
//=================================================================================================
bool BRepFill_MultiLine::D1(const double /*theT*/,
NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
NCollection_Array1<gp_Vec>& /*theVec*/) const
{
return false;
}