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
9 // under the terms of the GNU Lesser General Public 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.ixx>
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>
45 #include <GeomAdaptor_Surface.hxx>
46 #include <GeomAbs_SurfaceType.hxx>
49 #include <DrawTrSurf.hxx>
53 static Standard_Boolean AffichCurve = Standard_False;
54 static Standard_Integer NbProj = 1;
59 //=======================================================================
62 //=======================================================================
64 static Standard_Boolean isIsoU(const TopoDS_Face& Face,
65 const TopoDS_Edge& Edge )
67 Handle(Geom2d_Curve) C;
68 Handle(Geom2d_Line) Li;
71 C = BRep_Tool::CurveOnSurface(Edge,Face, f, l);
73 Standard_ConstructionError::Raise ("BRepFill_MultiLine : Edge without PCurve");
76 gp_Dir2d D = C->DN(f,1);
78 if (Abs(D.Dot(gp::DX2d())) < Abs(D.Dot(gp::DY2d())))
81 return Standard_False;
87 //=======================================================================
88 //function : BRepFill_MultiLine
90 //=======================================================================
92 BRepFill_MultiLine::BRepFill_MultiLine()
97 //=======================================================================
98 //function : BRepFill_MultiLine
100 //=======================================================================
102 BRepFill_MultiLine::BRepFill_MultiLine(const TopoDS_Face& Face1,
103 const TopoDS_Face& Face2,
104 const TopoDS_Edge& Edge1,
105 const TopoDS_Edge& Edge2,
106 const Standard_Boolean Inv1,
107 const Standard_Boolean Inv2,
108 const Handle(Geom2d_Curve)& Bissec) :
114 // eval if myedges are IsoU or not
115 myIsoU1 = isIsoU(Face1, Edge1);
116 myIsoU2 = isIsoU(Face2, Edge2);
118 // eval myU1, myV1, myU2, myV2;
119 Handle(Geom_Plane) RefPlane;
120 Handle(Geom_Plane) BasisPlane = new Geom_Plane(0.,0.,1.,0.);
124 Standard_Real Umin = 0.,Vmin = 0.,Umax = 0.,Vmax = 0.,U,V;
130 Standard_Boolean First = Standard_True;
131 for (Exp.Init(myFace1,TopAbs_EDGE);Exp.More(); Exp.Next()) {
132 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
133 BRep_Tool::UVPoints(CurEdge,myFace1,P1,P2);
135 First = Standard_False;
136 Umin = Min(P1.X(),P2.X());
137 Umax = Max(P1.X(),P2.X());
139 Vmin = Min(P1.Y(),P2.Y());
140 Vmax = Max(P1.Y(),P2.Y());
143 U = Min(P1.X(),P2.X());
145 U = Max(P1.X(),P2.X());
148 V = Min(P1.Y(),P2.Y());
150 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);
511 char* name = new char[100];
512 sprintf(name,"C2_%d",NbProj);
513 DrawTrSurf::Set(name,TLine);
514 sprintf(name,"C3_%d",NbProj);
515 DrawTrSurf::Set(name,Curve);
516 sprintf(name,"SS_%d",NbProj);
517 DrawTrSurf::Set(name,Plane);
523 PCurve1 = GeomProjLib::Curve2d(Curve,Plane);
526 S = BRep_Tool::Surface(myFace2,L);
528 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
529 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
530 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
531 Plane = Handle(Geom_Plane)::DownCast(S);
532 PCurve2 = GeomProjLib::Curve2d(Curve,Plane);
537 //=======================================================================
538 //function : FirstParameter
540 //=======================================================================
542 Standard_Real BRepFill_MultiLine::FirstParameter() const
544 return myBis.FirstParameter();
548 //=======================================================================
549 //function : LastParameter
551 //=======================================================================
553 Standard_Real BRepFill_MultiLine::LastParameter() const
555 return myBis.LastParameter();
559 //=======================================================================
562 //=======================================================================
564 gp_Pnt BRepFill_MultiLine::Value(const Standard_Real U) const
566 Handle(Geom_Surface) S;
569 S = BRep_Tool::Surface(myFace1,L);
571 gp_Pnt2d P2d = ValueOnF1(U);
573 gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
574 P3d.Transform(L.Transformation());
580 //=======================================================================
581 //function : ValueOnFace
583 //=======================================================================
585 static gp_Pnt2d ValueOnFace(const Standard_Real U,
586 const Geom2dAdaptor_Curve& TheBis,
587 const Geom2dAdaptor_Curve& TheU,
588 const Geom2dAdaptor_Curve& TheV,
589 const Standard_Boolean IsIsoU)
591 gp_Pnt2d P = TheBis.Value(U);
593 Geom2dAPI_ProjectPointOnCurve Ext(P,TheU.Curve(),
594 TheU.FirstParameter(),
595 TheU.LastParameter());
598 char* TheUname = "TheU";
599 char* PP1name = "PP1";
600 DrawTrSurf::Set(TheUname,TheU.Curve());
601 DrawTrSurf::Set(PP1name,P);
602 // DrawTrSurf::Set("TheU",TheU.Curve());
603 // DrawTrSurf::Set("PP1",P);
607 Standard_Real UU =0., Dist = Precision::Infinite(), D1, D2;
609 if ( !Ext.NbPoints() == 0 ) {
610 UU = Ext.LowerDistanceParameter();
611 Dist = Ext.LowerDistance();
613 // Control with `ends`
614 D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
615 D2 = P.Distance(TheU.Value(TheU.LastParameter()));
617 if (D1 < Dist || D2 < Dist) {
618 if ( Abs( D1 - D2) < Precision::Confusion()) {
619 if ( TheU.GetType() == GeomAbs_Circle) {
620 gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
621 gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(),1);
622 Standard_Real Ang = Axis.Angle(D12d);
623 if ( !TheU.Circle().IsDirect()) Ang = -Ang;
624 UU = ElCLib::InPeriod( Ang, TheU.FirstParameter(),
625 TheU.FirstParameter() + 2*M_PI);
626 Dist = TheU.Circle().Radius();
630 cout << "MultiLine : D1 = D2 and the Curve is not a circle" << endl;
631 cout << " ---> ValueOnFace failed at parameter U = " << U << endl;
633 Standard_ConstructionError::Raise("BRepFill_MultiLine: ValueOnFace");
638 UU = TheU.FirstParameter();
642 UU = TheU.LastParameter();
646 Standard_Real Tol = Precision::Confusion();
649 gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
650 gp_Pnt2d PL = TheV.Value(TheV.LastParameter());
652 if (Abs(Dist - Abs(PF.Y())) < Tol) {
653 VV = TheV.FirstParameter();
655 else if (Abs(Dist - Abs(PL.Y())) < Tol) {
656 VV = TheV.LastParameter();
659 // test if the curve is at the side `negative Y`.
660 if ( Min( PF.Y(),PL.Y()) < -Tol) Dist = -Dist;
662 Handle(Geom2d_Line) Line
663 = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
667 static Standard_CString aTheV = "TheV" ;
668 DrawTrSurf::Set(aTheV,TheV.Curve());
669 static Standard_CString aLINF1 = "LINF1" ;
670 DrawTrSurf::Set(aLINF1,Line);
674 Geom2dAdaptor_Curve Cu1 = TheV;
675 Geom2dAdaptor_Curve Cu2( Line);
677 Standard_Real TolConf = 0.;
679 Geom2dInt_GInter Intersector(Cu1,Cu2,TolConf,Tol);
681 if ( !Intersector.IsDone()) {
683 cout << "Intersector not done" << endl;
684 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
686 return gp_Pnt2d(0.,0.);
689 if ( Intersector.NbPoints() > 0) {
690 VV = Intersector.Point(1).ParamOnFirst();
692 else if ( Intersector.NbSegments() > 0) {
693 IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
694 Standard_Real VS1 = Seg.FirstPoint().ParamOnFirst();
695 Standard_Real VS2 = Seg.LastPoint().ParamOnFirst();
696 gp_Pnt2d PS1 = TheV.Value(VS1);
697 gp_Pnt2d PS2 = TheV.Value(VS2);
698 Standard_Real Alp = (Dist - PS1.Y())/(PS2.Y() - PS1.Y());
699 VV = Alp*(VS2 - VS1) + VS1;
703 cout << "Intersector done, but no points found" << endl;
704 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
706 if (Abs(Dist - PL.Y()) < Abs(Dist - PF.Y()))
707 VV = TheV.LastParameter();
709 VV = TheV.FirstParameter();
715 return gp_Pnt2d(VV,UU);
717 return gp_Pnt2d(UU,VV);
720 //=======================================================================
721 //function : ValueOnF1
723 //=======================================================================
725 gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const Standard_Real U) const
727 return ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
731 //=======================================================================
732 //function : ValueOnF2
734 //=======================================================================
736 gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const Standard_Real U) const
738 return ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
741 //=======================================================================
742 //function : Value3dOnF1OnF2
744 //=======================================================================
746 void BRepFill_MultiLine::Value3dOnF1OnF2(const Standard_Real U,
752 PF1 = ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
753 PF2 = ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
755 Handle(Geom_Surface) S;
758 S = BRep_Tool::Surface(myFace1,L);
759 P3d = S->Value(PF1.X(), PF1.Y());
760 P3d.Transform(L.Transformation());
763 //=======================================================================
764 //function : Continuity
766 //=======================================================================
768 GeomAbs_Shape BRepFill_MultiLine::Continuity() const