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 throw Standard_ConstructionError("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)
113 const Standard_Real mult = 5.;
114 const Standard_Real eps = mult * Precision::Confusion();
119 // eval if myedges are IsoU or not
120 myIsoU1 = isIsoU(Face1, Edge1);
121 myIsoU2 = isIsoU(Face2, Edge2);
123 // eval myU1, myV1, myU2, myV2;
124 Handle(Geom_Plane) RefPlane;
125 Handle(Geom_Plane) BasisPlane = new Geom_Plane(0.,0.,1.,0.);
129 Standard_Real Umin = 0.,Vmin = 0.,Umax = 0.,Vmax = 0.,U,V;
135 Standard_Boolean First = Standard_True;
136 for (Exp.Init(myFace1,TopAbs_EDGE);Exp.More(); Exp.Next()) {
137 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
138 BRep_Tool::UVPoints(CurEdge,myFace1,P1,P2);
140 First = Standard_False;
141 Umin = Min(P1.X(),P2.X());
142 Umax = Max(P1.X(),P2.X());
144 Vmin = Min(P1.Y(),P2.Y());
145 Vmax = Max(P1.Y(),P2.Y());
148 U = Min(P1.X(),P2.X());
150 U = Max(P1.X(),P2.X());
153 V = Min(P1.Y(),P2.Y());
155 V = Max(P1.Y(),P2.Y());
160 // return isos in their domain of restriction.
161 Handle(Geom_Curve) UU1, UU2, VV1, VV2;
162 Handle(Geom_Surface) S;
163 S = BRep_Tool::Surface(myFace1,L);
165 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
168 if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
170 GeomAdaptor_Curve Dummy(UU1);
171 if (Dummy.GetType() == GeomAbs_Circle &&
172 Dummy.Circle().Radius() < eps) {
178 GeomAdaptor_Curve Dummy(UU1);
179 if (Dummy.GetType() == GeomAbs_Circle &&
180 Dummy.Circle().Radius() < eps) {
187 if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
189 GeomAdaptor_Curve Dummy(UU1);
190 if (Dummy.GetType() == GeomAbs_Circle &&
191 Dummy.Circle().Radius() < eps) {
197 GeomAdaptor_Curve Dummy(UU1);
198 if (Dummy.GetType() == GeomAbs_Circle &&
199 Dummy.Circle().Radius() < eps) {
207 Standard_Real dummyUmin = Umin, dummyUmax = Umax;
215 GeomAdaptor_Surface GAS1(S);
216 GeomAbs_SurfaceType Type1 = GAS1.GetType();
218 if ( UU1->IsPeriodic()) {
219 ElCLib::AdjustPeriodic(UU1->FirstParameter(),
220 UU1->LastParameter(),
221 Precision::PConfusion(),
224 if ( VV1->IsPeriodic()) {
225 ElCLib::AdjustPeriodic(VV1->FirstParameter(),
226 VV1->LastParameter(),
227 Precision::PConfusion(),
230 if (GAS1.GetType() == GeomAbs_Sphere) {
232 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
233 Precision::PConfusion(),
236 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
237 Precision::PConfusion(),
240 // end try duplication
242 myU1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU1, BasisPlane),
245 UU1->D1(Umin, P, DZ);
246 RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
248 myV1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV1, RefPlane),
252 First = Standard_True;
253 for (Exp.Init(myFace2,TopAbs_EDGE);Exp.More(); Exp.Next()) {
254 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
255 BRep_Tool::UVPoints(CurEdge,myFace2,P1,P2);
257 First = Standard_False;
258 Umin = Min(P1.X(),P2.X());
259 Umax = Max(P1.X(),P2.X());
261 Vmin = Min(P1.Y(),P2.Y());
262 Vmax = Max(P1.Y(),P2.Y());
265 U = Min(P1.X(),P2.X());
267 U = Max(P1.X(),P2.X());
270 V = Min(P1.Y(),P2.Y());
272 V = Max(P1.Y(),P2.Y());
277 // return isos in their domain of restriction.
278 S = BRep_Tool::Surface(myFace2,L);
281 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
284 if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
286 GeomAdaptor_Curve Dummy(UU2);
287 if (Dummy.GetType() == GeomAbs_Circle &&
288 Dummy.Circle().Radius() < eps) {
294 GeomAdaptor_Curve Dummy(UU2);
295 if (Dummy.GetType() == GeomAbs_Circle &&
296 Dummy.Circle().Radius() < eps) {
303 if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
305 GeomAdaptor_Curve Dummy(UU2);
306 if (Dummy.GetType() == GeomAbs_Circle &&
307 Dummy.Circle().Radius() < eps) {
313 GeomAdaptor_Curve Dummy(UU2);
314 if (Dummy.GetType() == GeomAbs_Circle &&
315 Dummy.Circle().Radius() < eps) {
323 Standard_Real dummyUmin = Umin, dummyUmax = Umax;
331 GeomAdaptor_Surface GAS2(S);
332 GeomAbs_SurfaceType Type2 = GAS2.GetType();
334 if ( UU2->IsPeriodic()) {
335 ElCLib::AdjustPeriodic(UU2->FirstParameter(),
336 UU2->LastParameter(),
337 Precision::PConfusion(),
340 if ( VV2->IsPeriodic()) {
341 ElCLib::AdjustPeriodic(VV2->FirstParameter(),
342 VV2->LastParameter(),
343 Precision::PConfusion(),
346 if (GAS2.GetType() == GeomAbs_Sphere) {
348 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
349 Precision::PConfusion(),
352 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
353 Precision::PConfusion(),
356 // end try duplication
358 myU2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU2, BasisPlane),
361 UU2->D1(Umin, P, DZ);
362 RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
363 myV2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV2, RefPlane),
366 // eval if in a particular case.
367 // Particular case if :
368 // 1) - Straight Bissectrice
369 // - Bissectrice orthogonal to the base element.
370 // ==> Iso on 2 faces.
371 // 2) - Straight Bissectrice
372 // - 2 surfaces are planes.
375 if ( myBis.GetType() == GeomAbs_Line) {
376 Standard_Real DeltaU = myBis.LastParameter() - myBis.FirstParameter();
377 gp_Pnt2d aPnt1 = ValueOnF1(myBis.FirstParameter() + 0.1*DeltaU);
378 gp_Pnt2d aPnt2 = ValueOnF1(myBis.FirstParameter() + 0.9*DeltaU);
380 if ( Abs(aPnt1.Y() - aPnt2.Y()) < eps)
384 if ( Abs(aPnt1.X() - aPnt2.X()) < eps)
391 if ( (Type1 == GeomAbs_Plane) && (Type2 == GeomAbs_Plane)) {
398 //=======================================================================
399 //function : IsParticularCase
401 //=======================================================================
403 Standard_Boolean BRepFill_MultiLine::IsParticularCase() const
405 return ( myKPart != 0);
409 //=======================================================================
412 //=======================================================================
414 void BRepFill_MultiLine::Curves(Handle(Geom_Curve)& Curve,
415 Handle(Geom2d_Curve)& PCurve1,
416 Handle(Geom2d_Curve)& PCurve2) const
422 P1 = ValueOnF1(myBis.FirstParameter());
423 P2 = ValueOnF1(myBis.LastParameter());
425 // find value of the with medium point
426 // the ends can be degenerated points.
428 PMil = ValueOnF1(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
431 Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
433 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
435 Standard_Boolean Sens;
437 Curve = S->UIso(PMil.X());
438 Sens = P1.Y() < P2.Y();
440 Curve = new Geom_TrimmedCurve(Curve, P1.Y(), P2.Y(), Sens);
442 Curve = new Geom_TrimmedCurve(Curve, P2.Y(), P1.Y(), Sens);
444 f = Curve->FirstParameter();
445 l = Curve->LastParameter();
447 PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() - f), gp::DY2d());
449 PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() + f),-gp::DY2d());
450 PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
453 Curve = S->VIso(PMil.Y());
454 Sens = P1.X() < P2.X();
456 Curve = new Geom_TrimmedCurve(Curve, P1.X(), P2.X(), Sens);
458 Curve = new Geom_TrimmedCurve(Curve, P2.X(), P1.X(), Sens);
460 f = Curve->FirstParameter();
461 l = Curve->LastParameter();
463 PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() - f,PMil.Y()), gp::DX2d());
465 PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() + f,PMil.Y()), -gp::DX2d());
466 PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
469 P1 = ValueOnF2(myBis.FirstParameter());
470 P2 = ValueOnF2(myBis.LastParameter());
471 PMil = ValueOnF2(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
474 Sens = P1.Y() < P2.Y();
476 PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() - f)), gp::DY2d());
478 PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() + f)), -gp::DY2d());
481 Sens = P1.X() < P2.X();
483 PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() - f ,PMil.Y()), gp::DX2d());
485 PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() + f ,PMil.Y()), -gp::DX2d());
487 PCurve2 = new Geom2d_TrimmedCurve( PCurve2 ,f ,l);
489 else if ( myKPart == 2) {
492 Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
494 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
496 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
497 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
499 Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(S);
500 // eval the 3d curve corresponding to the bissectrice.
501 gp_Pnt2d P = myBis.Line().Location();
502 gp_Dir2d D = myBis.Line().Direction();
503 Handle(Geom_Line) Line = new Geom_Line(gp_Pnt(P.X(),P.Y(),0.),
504 gp_Dir(D.X(),D.Y(),0.) );
505 Handle(Geom_TrimmedCurve) TLine =
506 new Geom_TrimmedCurve(Line, myBis.FirstParameter(),
507 myBis.LastParameter());
508 Curve = GeomProjLib::ProjectOnPlane(TLine, Plane,
509 gp::DZ(), Standard_False);
514 sprintf(name,"C2_%d",NbProj);
515 DrawTrSurf::Set(name,TLine);
516 sprintf(name,"C3_%d",NbProj);
517 DrawTrSurf::Set(name,Curve);
518 sprintf(name,"SS_%d",NbProj);
519 DrawTrSurf::Set(name,Plane);
525 PCurve1 = GeomProjLib::Curve2d(Curve,Plane);
528 S = BRep_Tool::Surface(myFace2,L);
530 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
531 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
532 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
533 Plane = Handle(Geom_Plane)::DownCast(S);
534 PCurve2 = GeomProjLib::Curve2d(Curve,Plane);
539 //=======================================================================
540 //function : FirstParameter
542 //=======================================================================
544 Standard_Real BRepFill_MultiLine::FirstParameter() const
546 return myBis.FirstParameter();
550 //=======================================================================
551 //function : LastParameter
553 //=======================================================================
555 Standard_Real BRepFill_MultiLine::LastParameter() const
557 return myBis.LastParameter();
561 //=======================================================================
564 //=======================================================================
566 gp_Pnt BRepFill_MultiLine::Value(const Standard_Real U) const
568 Handle(Geom_Surface) S;
571 S = BRep_Tool::Surface(myFace1,L);
573 gp_Pnt2d P2d = ValueOnF1(U);
575 gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
576 P3d.Transform(L.Transformation());
582 //=======================================================================
583 //function : ValueOnFace
585 //=======================================================================
587 static gp_Pnt2d ValueOnFace(const Standard_Real U,
588 const Geom2dAdaptor_Curve& TheBis,
589 const Geom2dAdaptor_Curve& TheU,
590 const Geom2dAdaptor_Curve& TheV,
591 const Standard_Boolean IsIsoU)
593 gp_Pnt2d P = TheBis.Value(U);
595 Geom2dAPI_ProjectPointOnCurve Ext(P,TheU.Curve(),
596 TheU.FirstParameter(),
597 TheU.LastParameter());
600 char* TheUname = "TheU";
601 char* PP1name = "PP1";
602 DrawTrSurf::Set(TheUname,TheU.Curve());
603 DrawTrSurf::Set(PP1name,P);
604 // DrawTrSurf::Set("TheU",TheU.Curve());
605 // DrawTrSurf::Set("PP1",P);
609 const Standard_Real mult = 5.;
610 const Standard_Real eps = mult * Precision::Confusion();
612 Standard_Real UU =0., Dist = Precision::Infinite(), D1, D2;
614 if ( Ext.NbPoints() != 0 ) {
615 UU = Ext.LowerDistanceParameter();
616 Dist = Ext.LowerDistance();
618 // Control with `ends`
619 D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
620 D2 = P.Distance(TheU.Value(TheU.LastParameter()));
622 if (D1 < Dist || D2 < Dist || Abs(D1 - Dist) < eps || Abs(D2 - Dist) < eps) {
623 if ( Abs( D1 - D2) < eps) {
624 if ( TheU.GetType() == GeomAbs_Circle) {
625 gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
626 gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(),1);
627 Standard_Real Ang = Axis.Angle(D12d);
628 if ( !TheU.Circle().IsDirect()) Ang = -Ang;
629 UU = ElCLib::InPeriod( Ang, TheU.FirstParameter(),
630 TheU.FirstParameter() + 2*M_PI);
631 Dist = TheU.Circle().Radius();
635 cout << "MultiLine : D1 = D2 and the Curve is not a circle" << endl;
636 cout << " ---> ValueOnFace failed at parameter U = " << U << endl;
638 throw Standard_ConstructionError("BRepFill_MultiLine: ValueOnFace");
643 UU = TheU.FirstParameter();
647 UU = TheU.LastParameter();
651 const Standard_Real Tol = Precision::Confusion();
654 gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
655 gp_Pnt2d PL = TheV.Value(TheV.LastParameter());
657 if (Abs(Dist - Abs(PF.Y())) < Tol) {
658 VV = TheV.FirstParameter();
660 else if (Abs(Dist - Abs(PL.Y())) < Tol) {
661 VV = TheV.LastParameter();
664 // test if the curve is at the side `negative Y`.
665 if ( Min( PF.Y(),PL.Y()) < -Tol) Dist = -Dist;
667 Handle(Geom2d_Line) Line
668 = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
672 static Standard_CString aTheV = "TheV" ;
673 DrawTrSurf::Set(aTheV,TheV.Curve());
674 static Standard_CString aLINF1 = "LINF1" ;
675 DrawTrSurf::Set(aLINF1,Line);
679 Geom2dAdaptor_Curve Cu1 = TheV;
680 Geom2dAdaptor_Curve Cu2( Line);
682 Standard_Real TolConf = 0.;
684 Geom2dInt_GInter Intersector(Cu1,Cu2,TolConf,Tol);
686 if ( !Intersector.IsDone()) {
688 cout << "Intersector not done" << endl;
689 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
691 return gp_Pnt2d(0.,0.);
694 if ( Intersector.NbPoints() > 0) {
695 VV = Intersector.Point(1).ParamOnFirst();
697 else if ( Intersector.NbSegments() > 0) {
698 IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
699 Standard_Real VS1 = Seg.FirstPoint().ParamOnFirst();
700 Standard_Real VS2 = Seg.LastPoint().ParamOnFirst();
701 gp_Pnt2d PS1 = TheV.Value(VS1);
702 gp_Pnt2d PS2 = TheV.Value(VS2);
703 Standard_Real Alp = (Dist - PS1.Y())/(PS2.Y() - PS1.Y());
704 VV = Alp*(VS2 - VS1) + VS1;
708 cout << "Intersector done, but no points found" << endl;
709 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
711 if (Abs(Dist - PL.Y()) < Abs(Dist - PF.Y()))
712 VV = TheV.LastParameter();
714 VV = TheV.FirstParameter();
720 return gp_Pnt2d(VV,UU);
722 return gp_Pnt2d(UU,VV);
725 //=======================================================================
726 //function : ValueOnF1
728 //=======================================================================
730 gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const Standard_Real U) const
732 return ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
736 //=======================================================================
737 //function : ValueOnF2
739 //=======================================================================
741 gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const Standard_Real U) const
743 return ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
746 //=======================================================================
747 //function : Value3dOnF1OnF2
749 //=======================================================================
751 void BRepFill_MultiLine::Value3dOnF1OnF2(const Standard_Real U,
757 PF1 = ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
758 PF2 = ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
760 Handle(Geom_Surface) S;
763 S = BRep_Tool::Surface(myFace1,L);
764 P3d = S->Value(PF1.X(), PF1.Y());
765 P3d.Transform(L.Transformation());
768 //=======================================================================
769 //function : Continuity
771 //=======================================================================
773 GeomAbs_Shape BRepFill_MultiLine::Continuity() const
778 //=======================================================================
781 //=======================================================================
783 Standard_Boolean BRepFill_MultiLine::Value(const Standard_Real theT,
784 NCollection_Array1<gp_Pnt2d>& thePnt2d,
785 NCollection_Array1<gp_Pnt>& thePnt) const
787 thePnt(1) = Value(theT);
788 thePnt2d(1) = ValueOnF1(theT);
789 thePnt2d(2) = ValueOnF2(theT);
790 return Standard_True;
793 //=======================================================================
796 //=======================================================================
798 Standard_Boolean BRepFill_MultiLine::D1(const Standard_Real /*theT*/,
799 NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
800 NCollection_Array1<gp_Vec>& /*theVec*/) const
802 return Standard_False;