1 // Created on: 1994-11-14
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepFill_MultiLine.hxx>
19 #include <BRepIntCurveSurface_Inter.hxx>
23 #include <gp_Lin2d.hxx>
24 #include <gp_Circ2d.hxx>
25 #include <Precision.hxx>
26 #include <BRep_Tool.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Plane.hxx>
29 #include <Geom_TrimmedCurve.hxx>
30 #include <Geom2d_TrimmedCurve.hxx>
31 #include <Geom_Surface.hxx>
32 #include <Geom_RectangularTrimmedSurface.hxx>
33 #include <Geom2d_Line.hxx>
34 #include <GeomProjLib.hxx>
35 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
36 #include <Geom2dInt_GInter.hxx>
37 #include <IntRes2d_IntersectionPoint.hxx>
38 #include <Standard_ConstructionError.hxx>
39 #include <IntRes2d_IntersectionSegment.hxx>
40 #include <TopExp_Explorer.hxx>
43 #include <GeomAdaptor_Curve.hxx>
45 #include <GeomAdaptor_Surface.hxx>
46 #include <GeomAbs_SurfaceType.hxx>
49 #include <DrawTrSurf.hxx>
50 static Standard_Boolean AffichCurve = Standard_False;
51 static Standard_Integer NbProj = 1;
57 //=======================================================================
60 //=======================================================================
62 static Standard_Boolean isIsoU(const TopoDS_Face& Face,
63 const TopoDS_Edge& Edge )
65 Handle(Geom2d_Curve) C;
66 Handle(Geom2d_Line) Li;
69 C = BRep_Tool::CurveOnSurface(Edge,Face, f, l);
71 Standard_ConstructionError::Raise ("BRepFill_MultiLine : Edge without PCurve");
74 gp_Dir2d D = C->DN(f,1);
76 if (Abs(D.Dot(gp::DX2d())) < Abs(D.Dot(gp::DY2d())))
79 return Standard_False;
83 //=======================================================================
84 //function : BRepFill_MultiLine
86 //=======================================================================
88 BRepFill_MultiLine::BRepFill_MultiLine()
95 //=======================================================================
96 //function : BRepFill_MultiLine
98 //=======================================================================
100 BRepFill_MultiLine::BRepFill_MultiLine(const TopoDS_Face& Face1,
101 const TopoDS_Face& Face2,
102 const TopoDS_Edge& Edge1,
103 const TopoDS_Edge& Edge2,
104 const Standard_Boolean Inv1,
105 const Standard_Boolean Inv2,
106 const Handle(Geom2d_Curve)& Bissec)
115 // eval if myedges are IsoU or not
116 myIsoU1 = isIsoU(Face1, Edge1);
117 myIsoU2 = isIsoU(Face2, Edge2);
119 // eval myU1, myV1, myU2, myV2;
120 Handle(Geom_Plane) RefPlane;
121 Handle(Geom_Plane) BasisPlane = new Geom_Plane(0.,0.,1.,0.);
125 Standard_Real Umin = 0.,Vmin = 0.,Umax = 0.,Vmax = 0.,U,V;
131 Standard_Boolean First = Standard_True;
132 for (Exp.Init(myFace1,TopAbs_EDGE);Exp.More(); Exp.Next()) {
133 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
134 BRep_Tool::UVPoints(CurEdge,myFace1,P1,P2);
136 First = Standard_False;
137 Umin = Min(P1.X(),P2.X());
138 Umax = Max(P1.X(),P2.X());
140 Vmin = Min(P1.Y(),P2.Y());
141 Vmax = Max(P1.Y(),P2.Y());
144 U = Min(P1.X(),P2.X());
146 U = Max(P1.X(),P2.X());
149 V = Min(P1.Y(),P2.Y());
151 V = Max(P1.Y(),P2.Y());
156 // return isos in their domain of restriction.
157 Handle(Geom_Curve) UU1, UU2, VV1, VV2;
158 Handle(Geom_Surface) S;
159 S = BRep_Tool::Surface(myFace1,L);
161 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
164 if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
166 GeomAdaptor_Curve Dummy(UU1);
167 if (Dummy.GetType() == GeomAbs_Circle &&
168 Dummy.Circle().Radius() < Precision::Confusion()) {
174 GeomAdaptor_Curve Dummy(UU1);
175 if (Dummy.GetType() == GeomAbs_Circle &&
176 Dummy.Circle().Radius() < Precision::Confusion()) {
183 if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
185 GeomAdaptor_Curve Dummy(UU1);
186 if (Dummy.GetType() == GeomAbs_Circle &&
187 Dummy.Circle().Radius() < Precision::Confusion()) {
193 GeomAdaptor_Curve Dummy(UU1);
194 if (Dummy.GetType() == GeomAbs_Circle &&
195 Dummy.Circle().Radius() < Precision::Confusion()) {
203 Standard_Real dummyUmin = Umin, dummyUmax = Umax;
211 GeomAdaptor_Surface GAS1(S);
212 GeomAbs_SurfaceType Type1 = GAS1.GetType();
214 if ( UU1->IsPeriodic()) {
215 ElCLib::AdjustPeriodic(UU1->FirstParameter(),
216 UU1->LastParameter(),
217 Precision::PConfusion(),
220 if ( VV1->IsPeriodic()) {
221 ElCLib::AdjustPeriodic(VV1->FirstParameter(),
222 VV1->LastParameter(),
223 Precision::PConfusion(),
226 if (GAS1.GetType() == GeomAbs_Sphere) {
228 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
229 Precision::PConfusion(),
232 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
233 Precision::PConfusion(),
236 // end try duplication
238 myU1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU1, BasisPlane),
241 UU1->D1(Umin, P, DZ);
242 RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
244 myV1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV1, RefPlane),
248 First = Standard_True;
249 for (Exp.Init(myFace2,TopAbs_EDGE);Exp.More(); Exp.Next()) {
250 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
251 BRep_Tool::UVPoints(CurEdge,myFace2,P1,P2);
253 First = Standard_False;
254 Umin = Min(P1.X(),P2.X());
255 Umax = Max(P1.X(),P2.X());
257 Vmin = Min(P1.Y(),P2.Y());
258 Vmax = Max(P1.Y(),P2.Y());
261 U = Min(P1.X(),P2.X());
263 U = Max(P1.X(),P2.X());
266 V = Min(P1.Y(),P2.Y());
268 V = Max(P1.Y(),P2.Y());
273 // return isos in their domain of restriction.
274 S = BRep_Tool::Surface(myFace2,L);
277 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
280 if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
282 GeomAdaptor_Curve Dummy(UU2);
283 if (Dummy.GetType() == GeomAbs_Circle &&
284 Dummy.Circle().Radius() < Precision::Confusion()) {
290 GeomAdaptor_Curve Dummy(UU2);
291 if (Dummy.GetType() == GeomAbs_Circle &&
292 Dummy.Circle().Radius() < Precision::Confusion()) {
299 if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
301 GeomAdaptor_Curve Dummy(UU2);
302 if (Dummy.GetType() == GeomAbs_Circle &&
303 Dummy.Circle().Radius() < Precision::Confusion()) {
309 GeomAdaptor_Curve Dummy(UU2);
310 if (Dummy.GetType() == GeomAbs_Circle &&
311 Dummy.Circle().Radius() < Precision::Confusion()) {
319 Standard_Real dummyUmin = Umin, dummyUmax = Umax;
327 GeomAdaptor_Surface GAS2(S);
328 GeomAbs_SurfaceType Type2 = GAS2.GetType();
330 if ( UU2->IsPeriodic()) {
331 ElCLib::AdjustPeriodic(UU2->FirstParameter(),
332 UU2->LastParameter(),
333 Precision::PConfusion(),
336 if ( VV2->IsPeriodic()) {
337 ElCLib::AdjustPeriodic(VV2->FirstParameter(),
338 VV2->LastParameter(),
339 Precision::PConfusion(),
342 if (GAS2.GetType() == GeomAbs_Sphere) {
344 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
345 Precision::PConfusion(),
348 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
349 Precision::PConfusion(),
352 // end try duplication
354 myU2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU2, BasisPlane),
357 UU2->D1(Umin, P, DZ);
358 RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
359 myV2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV2, RefPlane),
362 // eval if in a particular case.
363 // Particular case if :
364 // 1) - Straight Bissectrice
365 // - Bissectrice orthogonal to the base element.
366 // ==> Iso on 2 faces.
367 // 2) - Straight Bissectrice
368 // - 2 surfaces are planes.
371 if ( myBis.GetType() == GeomAbs_Line) {
372 Standard_Real DeltaU = myBis.LastParameter() - myBis.FirstParameter();
373 gp_Pnt2d P1 = ValueOnF1(myBis.FirstParameter() + 0.1*DeltaU);
374 gp_Pnt2d P2 = ValueOnF1(myBis.FirstParameter() + 0.9*DeltaU);
376 if ( Abs(P1.Y() - P2.Y()) < Precision::Confusion())
380 if ( Abs(P1.X() - P2.X()) < Precision::Confusion())
387 if ( (Type1 == GeomAbs_Plane) && (Type2 == GeomAbs_Plane)) {
394 //=======================================================================
395 //function : IsParticularCase
397 //=======================================================================
399 Standard_Boolean BRepFill_MultiLine::IsParticularCase() const
401 return ( myKPart != 0);
405 //=======================================================================
408 //=======================================================================
410 void BRepFill_MultiLine::Curves(Handle(Geom_Curve)& Curve,
411 Handle(Geom2d_Curve)& PCurve1,
412 Handle(Geom2d_Curve)& PCurve2) const
418 P1 = ValueOnF1(myBis.FirstParameter());
419 P2 = ValueOnF1(myBis.LastParameter());
421 // find value of the with medium point
422 // the ends can be degenerated points.
424 PMil = ValueOnF1(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
427 Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
429 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
431 Standard_Boolean Sens;
433 Curve = S->UIso(PMil.X());
434 Sens = P1.Y() < P2.Y();
436 Curve = new Geom_TrimmedCurve(Curve, P1.Y(), P2.Y(), Sens);
438 Curve = new Geom_TrimmedCurve(Curve, P2.Y(), P1.Y(), Sens);
440 f = Curve->FirstParameter();
441 l = Curve->LastParameter();
443 PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() - f), gp::DY2d());
445 PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() + f),-gp::DY2d());
446 PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
449 Curve = S->VIso(PMil.Y());
450 Sens = P1.X() < P2.X();
452 Curve = new Geom_TrimmedCurve(Curve, P1.X(), P2.X(), Sens);
454 Curve = new Geom_TrimmedCurve(Curve, P2.X(), P1.X(), Sens);
456 f = Curve->FirstParameter();
457 l = Curve->LastParameter();
459 PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() - f,PMil.Y()), gp::DX2d());
461 PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() + f,PMil.Y()), -gp::DX2d());
462 PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
465 P1 = ValueOnF2(myBis.FirstParameter());
466 P2 = ValueOnF2(myBis.LastParameter());
467 PMil = ValueOnF2(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
470 Sens = P1.Y() < P2.Y();
472 PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() - f)), gp::DY2d());
474 PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() + f)), -gp::DY2d());
477 Sens = P1.X() < P2.X();
479 PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() - f ,PMil.Y()), gp::DX2d());
481 PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() + f ,PMil.Y()), -gp::DX2d());
483 PCurve2 = new Geom2d_TrimmedCurve( PCurve2 ,f ,l);
485 else if ( myKPart == 2) {
488 Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
490 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
492 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
493 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
495 Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(S);
496 // eval the 3d curve corresponding to the bissectrice.
497 gp_Pnt2d P = myBis.Line().Location();
498 gp_Dir2d D = myBis.Line().Direction();
499 Handle(Geom_Line) Line = new Geom_Line(gp_Pnt(P.X(),P.Y(),0.),
500 gp_Dir(D.X(),D.Y(),0.) );
501 Handle(Geom_TrimmedCurve) TLine =
502 new Geom_TrimmedCurve(Line, myBis.FirstParameter(),
503 myBis.LastParameter());
504 Curve = GeomProjLib::ProjectOnPlane(TLine, Plane,
505 gp::DZ(), Standard_False);
510 sprintf(name,"C2_%d",NbProj);
511 DrawTrSurf::Set(name,TLine);
512 sprintf(name,"C3_%d",NbProj);
513 DrawTrSurf::Set(name,Curve);
514 sprintf(name,"SS_%d",NbProj);
515 DrawTrSurf::Set(name,Plane);
521 PCurve1 = GeomProjLib::Curve2d(Curve,Plane);
524 S = BRep_Tool::Surface(myFace2,L);
526 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
527 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
528 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
529 Plane = Handle(Geom_Plane)::DownCast(S);
530 PCurve2 = GeomProjLib::Curve2d(Curve,Plane);
535 //=======================================================================
536 //function : FirstParameter
538 //=======================================================================
540 Standard_Real BRepFill_MultiLine::FirstParameter() const
542 return myBis.FirstParameter();
546 //=======================================================================
547 //function : LastParameter
549 //=======================================================================
551 Standard_Real BRepFill_MultiLine::LastParameter() const
553 return myBis.LastParameter();
557 //=======================================================================
560 //=======================================================================
562 gp_Pnt BRepFill_MultiLine::Value(const Standard_Real U) const
564 Handle(Geom_Surface) S;
567 S = BRep_Tool::Surface(myFace1,L);
569 gp_Pnt2d P2d = ValueOnF1(U);
571 gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
572 P3d.Transform(L.Transformation());
578 //=======================================================================
579 //function : ValueOnFace
581 //=======================================================================
583 static gp_Pnt2d ValueOnFace(const Standard_Real U,
584 const Geom2dAdaptor_Curve& TheBis,
585 const Geom2dAdaptor_Curve& TheU,
586 const Geom2dAdaptor_Curve& TheV,
587 const Standard_Boolean IsIsoU)
589 gp_Pnt2d P = TheBis.Value(U);
591 Geom2dAPI_ProjectPointOnCurve Ext(P,TheU.Curve(),
592 TheU.FirstParameter(),
593 TheU.LastParameter());
596 char* TheUname = "TheU";
597 char* PP1name = "PP1";
598 DrawTrSurf::Set(TheUname,TheU.Curve());
599 DrawTrSurf::Set(PP1name,P);
600 // DrawTrSurf::Set("TheU",TheU.Curve());
601 // DrawTrSurf::Set("PP1",P);
605 Standard_Real UU =0., Dist = Precision::Infinite(), D1, D2;
607 if ( Ext.NbPoints() != 0 ) {
608 UU = Ext.LowerDistanceParameter();
609 Dist = Ext.LowerDistance();
611 // Control with `ends`
612 D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
613 D2 = P.Distance(TheU.Value(TheU.LastParameter()));
615 if (D1 < Dist || D2 < Dist) {
616 if ( Abs( D1 - D2) < Precision::Confusion()) {
617 if ( TheU.GetType() == GeomAbs_Circle) {
618 gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
619 gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(),1);
620 Standard_Real Ang = Axis.Angle(D12d);
621 if ( !TheU.Circle().IsDirect()) Ang = -Ang;
622 UU = ElCLib::InPeriod( Ang, TheU.FirstParameter(),
623 TheU.FirstParameter() + 2*M_PI);
624 Dist = TheU.Circle().Radius();
628 cout << "MultiLine : D1 = D2 and the Curve is not a circle" << endl;
629 cout << " ---> ValueOnFace failed at parameter U = " << U << endl;
631 Standard_ConstructionError::Raise("BRepFill_MultiLine: ValueOnFace");
636 UU = TheU.FirstParameter();
640 UU = TheU.LastParameter();
644 Standard_Real Tol = Precision::Confusion();
647 gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
648 gp_Pnt2d PL = TheV.Value(TheV.LastParameter());
650 if (Abs(Dist - Abs(PF.Y())) < Tol) {
651 VV = TheV.FirstParameter();
653 else if (Abs(Dist - Abs(PL.Y())) < Tol) {
654 VV = TheV.LastParameter();
657 // test if the curve is at the side `negative Y`.
658 if ( Min( PF.Y(),PL.Y()) < -Tol) Dist = -Dist;
660 Handle(Geom2d_Line) Line
661 = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
665 static Standard_CString aTheV = "TheV" ;
666 DrawTrSurf::Set(aTheV,TheV.Curve());
667 static Standard_CString aLINF1 = "LINF1" ;
668 DrawTrSurf::Set(aLINF1,Line);
672 Geom2dAdaptor_Curve Cu1 = TheV;
673 Geom2dAdaptor_Curve Cu2( Line);
675 Standard_Real TolConf = 0.;
677 Geom2dInt_GInter Intersector(Cu1,Cu2,TolConf,Tol);
679 if ( !Intersector.IsDone()) {
681 cout << "Intersector not done" << endl;
682 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
684 return gp_Pnt2d(0.,0.);
687 if ( Intersector.NbPoints() > 0) {
688 VV = Intersector.Point(1).ParamOnFirst();
690 else if ( Intersector.NbSegments() > 0) {
691 IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
692 Standard_Real VS1 = Seg.FirstPoint().ParamOnFirst();
693 Standard_Real VS2 = Seg.LastPoint().ParamOnFirst();
694 gp_Pnt2d PS1 = TheV.Value(VS1);
695 gp_Pnt2d PS2 = TheV.Value(VS2);
696 Standard_Real Alp = (Dist - PS1.Y())/(PS2.Y() - PS1.Y());
697 VV = Alp*(VS2 - VS1) + VS1;
701 cout << "Intersector done, but no points found" << endl;
702 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
704 if (Abs(Dist - PL.Y()) < Abs(Dist - PF.Y()))
705 VV = TheV.LastParameter();
707 VV = TheV.FirstParameter();
713 return gp_Pnt2d(VV,UU);
715 return gp_Pnt2d(UU,VV);
718 //=======================================================================
719 //function : ValueOnF1
721 //=======================================================================
723 gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const Standard_Real U) const
725 return ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
729 //=======================================================================
730 //function : ValueOnF2
732 //=======================================================================
734 gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const Standard_Real U) const
736 return ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
739 //=======================================================================
740 //function : Value3dOnF1OnF2
742 //=======================================================================
744 void BRepFill_MultiLine::Value3dOnF1OnF2(const Standard_Real U,
750 PF1 = ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
751 PF2 = ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
753 Handle(Geom_Surface) S;
756 S = BRep_Tool::Surface(myFace1,L);
757 P3d = S->Value(PF1.X(), PF1.Y());
758 P3d.Transform(L.Transformation());
761 //=======================================================================
762 //function : Continuity
764 //=======================================================================
766 GeomAbs_Shape BRepFill_MultiLine::Continuity() const
771 //=======================================================================
774 //=======================================================================
776 Standard_Boolean BRepFill_MultiLine::Value(const Standard_Real theT,
777 NCollection_Array1<gp_Pnt2d>& thePnt2d,
778 NCollection_Array1<gp_Pnt>& thePnt) const
780 thePnt(1) = Value(theT);
781 thePnt2d(1) = ValueOnF1(theT);
782 thePnt2d(2) = ValueOnF2(theT);
783 return Standard_True;
786 //=======================================================================
789 //=======================================================================
791 Standard_Boolean BRepFill_MultiLine::D1(const Standard_Real /*theT*/,
792 NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
793 NCollection_Array1<gp_Vec>& /*theVec*/) const
795 return Standard_False;