1 // Created on: 1994-11-14
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
23 #include <BRepFill_MultiLine.ixx>
25 #include <BRepIntCurveSurface_Inter.hxx>
29 #include <gp_Lin2d.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <Precision.hxx>
32 #include <BRep_Tool.hxx>
33 #include <Geom_Line.hxx>
34 #include <Geom_Plane.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <Geom2d_TrimmedCurve.hxx>
37 #include <Geom_Surface.hxx>
38 #include <Geom_RectangularTrimmedSurface.hxx>
39 #include <Geom2d_Line.hxx>
40 #include <GeomProjLib.hxx>
41 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
42 #include <Geom2dInt_GInter.hxx>
43 #include <IntRes2d_IntersectionPoint.hxx>
44 #include <Standard_ConstructionError.hxx>
45 #include <IntRes2d_IntersectionSegment.hxx>
46 #include <TopExp_Explorer.hxx>
51 #include <GeomAdaptor_Surface.hxx>
52 #include <GeomAbs_SurfaceType.hxx>
55 #include <DrawTrSurf.hxx>
59 static Standard_Boolean AffichCurve = Standard_False;
60 static Standard_Integer NbProj = 1;
65 //=======================================================================
68 //=======================================================================
70 static Standard_Boolean isIsoU(const TopoDS_Face& Face,
71 const TopoDS_Edge& Edge )
73 Handle(Geom2d_Curve) C;
74 Handle(Geom2d_Line) Li;
77 C = BRep_Tool::CurveOnSurface(Edge,Face, f, l);
79 Standard_ConstructionError::Raise ("BRepFill_MultiLine : Edge without PCurve");
82 gp_Dir2d D = C->DN(f,1);
84 if (Abs(D.Dot(gp::DX2d())) < Abs(D.Dot(gp::DY2d())))
87 return Standard_False;
93 //=======================================================================
94 //function : BRepFill_MultiLine
96 //=======================================================================
98 BRepFill_MultiLine::BRepFill_MultiLine()
103 //=======================================================================
104 //function : BRepFill_MultiLine
106 //=======================================================================
108 BRepFill_MultiLine::BRepFill_MultiLine(const TopoDS_Face& Face1,
109 const TopoDS_Face& Face2,
110 const TopoDS_Edge& Edge1,
111 const TopoDS_Edge& Edge2,
112 const Standard_Boolean Inv1,
113 const Standard_Boolean Inv2,
114 const Handle(Geom2d_Curve)& Bissec) :
120 // eval if myedges are IsoU or not
121 myIsoU1 = isIsoU(Face1, Edge1);
122 myIsoU2 = isIsoU(Face2, Edge2);
124 // eval myU1, myV1, myU2, myV2;
125 Handle(Geom_Plane) RefPlane;
126 Handle(Geom_Plane) BasisPlane = new Geom_Plane(0.,0.,1.,0.);
130 Standard_Real Umin = 0.,Vmin = 0.,Umax = 0.,Vmax = 0.,U,V;
136 Standard_Boolean First = Standard_True;
137 for (Exp.Init(myFace1,TopAbs_EDGE);Exp.More(); Exp.Next()) {
138 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
139 BRep_Tool::UVPoints(CurEdge,myFace1,P1,P2);
141 First = Standard_False;
142 Umin = Min(P1.X(),P2.X());
143 Umax = Max(P1.X(),P2.X());
145 Vmin = Min(P1.Y(),P2.Y());
146 Vmax = Max(P1.Y(),P2.Y());
149 U = Min(P1.X(),P2.X());
151 U = Max(P1.X(),P2.X());
154 V = Min(P1.Y(),P2.Y());
156 V = Max(P1.Y(),P2.Y());
162 // return isos in their domain of restriction.
163 Handle(Geom_Curve) UU1, UU2, VV1, VV2;
164 Handle(Geom_Surface) S;
165 S = BRep_Tool::Surface(myFace1,L);
167 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
170 if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
172 GeomAdaptor_Curve Dummy(UU1);
173 if (Dummy.GetType() == GeomAbs_Circle &&
174 Dummy.Circle().Radius() < Precision::Confusion()) {
180 GeomAdaptor_Curve Dummy(UU1);
181 if (Dummy.GetType() == GeomAbs_Circle &&
182 Dummy.Circle().Radius() < Precision::Confusion()) {
189 if (!BRep_Tool::Degenerated(Edge1) && !Inv1) {
191 GeomAdaptor_Curve Dummy(UU1);
192 if (Dummy.GetType() == GeomAbs_Circle &&
193 Dummy.Circle().Radius() < Precision::Confusion()) {
199 GeomAdaptor_Curve Dummy(UU1);
200 if (Dummy.GetType() == GeomAbs_Circle &&
201 Dummy.Circle().Radius() < Precision::Confusion()) {
209 Standard_Real dummyUmin = Umin, dummyUmax = Umax;
217 GeomAdaptor_Surface GAS1(S);
218 GeomAbs_SurfaceType Type1 = GAS1.GetType();
220 if ( UU1->IsPeriodic()) {
221 ElCLib::AdjustPeriodic(UU1->FirstParameter(),
222 UU1->LastParameter(),
223 Precision::PConfusion(),
226 if ( VV1->IsPeriodic()) {
227 ElCLib::AdjustPeriodic(VV1->FirstParameter(),
228 VV1->LastParameter(),
229 Precision::PConfusion(),
232 if (GAS1.GetType() == GeomAbs_Sphere) {
234 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
235 Precision::PConfusion(),
238 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
239 Precision::PConfusion(),
242 // end try duplication
244 myU1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU1, BasisPlane),
247 UU1->D1(Umin, P, DZ);
248 RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
250 myV1 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV1, RefPlane),
254 First = Standard_True;
255 for (Exp.Init(myFace2,TopAbs_EDGE);Exp.More(); Exp.Next()) {
256 TopoDS_Edge CurEdge = TopoDS::Edge(Exp.Current());
257 BRep_Tool::UVPoints(CurEdge,myFace2,P1,P2);
259 First = Standard_False;
260 Umin = Min(P1.X(),P2.X());
261 Umax = Max(P1.X(),P2.X());
263 Vmin = Min(P1.Y(),P2.Y());
264 Vmax = Max(P1.Y(),P2.Y());
267 U = Min(P1.X(),P2.X());
269 U = Max(P1.X(),P2.X());
272 V = Min(P1.Y(),P2.Y());
274 V = Max(P1.Y(),P2.Y());
279 // return isos in their domain of restriction.
280 S = BRep_Tool::Surface(myFace2,L);
283 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
286 if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
288 GeomAdaptor_Curve Dummy(UU2);
289 if (Dummy.GetType() == GeomAbs_Circle &&
290 Dummy.Circle().Radius() < Precision::Confusion()) {
296 GeomAdaptor_Curve Dummy(UU2);
297 if (Dummy.GetType() == GeomAbs_Circle &&
298 Dummy.Circle().Radius() < Precision::Confusion()) {
305 if (!BRep_Tool::Degenerated(Edge2) && !Inv2) {
307 GeomAdaptor_Curve Dummy(UU2);
308 if (Dummy.GetType() == GeomAbs_Circle &&
309 Dummy.Circle().Radius() < Precision::Confusion()) {
315 GeomAdaptor_Curve Dummy(UU2);
316 if (Dummy.GetType() == GeomAbs_Circle &&
317 Dummy.Circle().Radius() < Precision::Confusion()) {
325 Standard_Real dummyUmin = Umin, dummyUmax = Umax;
333 GeomAdaptor_Surface GAS2(S);
334 GeomAbs_SurfaceType Type2 = GAS2.GetType();
336 if ( UU2->IsPeriodic()) {
337 ElCLib::AdjustPeriodic(UU2->FirstParameter(),
338 UU2->LastParameter(),
339 Precision::PConfusion(),
342 if ( VV2->IsPeriodic()) {
343 ElCLib::AdjustPeriodic(VV2->FirstParameter(),
344 VV2->LastParameter(),
345 Precision::PConfusion(),
348 if (GAS2.GetType() == GeomAbs_Sphere) {
350 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
351 Precision::PConfusion(),
354 ElCLib::AdjustPeriodic(-M_PI/2.,M_PI/2.,
355 Precision::PConfusion(),
358 // end try duplication
360 myU2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(UU2, BasisPlane),
363 UU2->D1(Umin, P, DZ);
364 RefPlane = new Geom_Plane(gp_Ax3(P,DZ,gp::DZ()));
365 myV2 = Geom2dAdaptor_Curve(GeomProjLib::Curve2d(VV2, RefPlane),
368 // eval if in a particular case.
369 // Particular case if :
370 // 1) - Straight Bissectrice
371 // - Bissectrice orthogonal to the base element.
372 // ==> Iso on 2 faces.
373 // 2) - Straight Bissectrice
374 // - 2 surfaces are planes.
377 if ( myBis.GetType() == GeomAbs_Line) {
378 Standard_Real DeltaU = myBis.LastParameter() - myBis.FirstParameter();
379 gp_Pnt2d P1 = ValueOnF1(myBis.FirstParameter() + 0.1*DeltaU);
380 gp_Pnt2d P2 = ValueOnF1(myBis.FirstParameter() + 0.9*DeltaU);
382 if ( Abs(P1.Y() - P2.Y()) < Precision::Confusion())
386 if ( Abs(P1.X() - P2.X()) < Precision::Confusion())
393 if ( (Type1 == GeomAbs_Plane) && (Type2 == GeomAbs_Plane)) {
400 //=======================================================================
401 //function : IsParticularCase
403 //=======================================================================
405 Standard_Boolean BRepFill_MultiLine::IsParticularCase() const
407 return ( myKPart != 0);
411 //=======================================================================
414 //=======================================================================
416 void BRepFill_MultiLine::Curves(Handle(Geom_Curve)& Curve,
417 Handle(Geom2d_Curve)& PCurve1,
418 Handle(Geom2d_Curve)& PCurve2) const
424 P1 = ValueOnF1(myBis.FirstParameter());
425 P2 = ValueOnF1(myBis.LastParameter());
427 // find value of the with medium point
428 // the ends can be degenerated points.
430 PMil = ValueOnF1(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
433 Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
435 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
437 Standard_Boolean Sens;
439 Curve = S->UIso(PMil.X());
440 Sens = P1.Y() < P2.Y();
442 Curve = new Geom_TrimmedCurve(Curve, P1.Y(), P2.Y(), Sens);
444 Curve = new Geom_TrimmedCurve(Curve, P2.Y(), P1.Y(), Sens);
446 f = Curve->FirstParameter();
447 l = Curve->LastParameter();
449 PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() - f), gp::DY2d());
451 PCurve1 = new Geom2d_Line(gp_Pnt2d(PMil.X(),P1.Y() + f),-gp::DY2d());
452 PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
455 Curve = S->VIso(PMil.Y());
456 Sens = P1.X() < P2.X();
458 Curve = new Geom_TrimmedCurve(Curve, P1.X(), P2.X(), Sens);
460 Curve = new Geom_TrimmedCurve(Curve, P2.X(), P1.X(), Sens);
462 f = Curve->FirstParameter();
463 l = Curve->LastParameter();
465 PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() - f,PMil.Y()), gp::DX2d());
467 PCurve1 = new Geom2d_Line(gp_Pnt2d(P1.X() + f,PMil.Y()), -gp::DX2d());
468 PCurve1 = new Geom2d_TrimmedCurve( PCurve1 ,f ,l);
471 P1 = ValueOnF2(myBis.FirstParameter());
472 P2 = ValueOnF2(myBis.LastParameter());
473 PMil = ValueOnF2(0.5*(myBis.FirstParameter() + myBis.LastParameter()));
476 Sens = P1.Y() < P2.Y();
478 PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() - f)), gp::DY2d());
480 PCurve2 = new Geom2d_Line(gp_Pnt2d(PMil.X(),(P1.Y() + f)), -gp::DY2d());
483 Sens = P1.X() < P2.X();
485 PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() - f ,PMil.Y()), gp::DX2d());
487 PCurve2 = new Geom2d_Line(gp_Pnt2d(P1.X() + f ,PMil.Y()), -gp::DX2d());
489 PCurve2 = new Geom2d_TrimmedCurve( PCurve2 ,f ,l);
491 else if ( myKPart == 2) {
494 Handle(Geom_Surface) S = BRep_Tool::Surface(myFace1,L);
496 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
498 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
499 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
501 Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast(S);
502 // eval the 3d curve corresponding to the bissectrice.
503 gp_Pnt2d P = myBis.Line().Location();
504 gp_Dir2d D = myBis.Line().Direction();
505 Handle(Geom_Line) Line = new Geom_Line(gp_Pnt(P.X(),P.Y(),0.),
506 gp_Dir(D.X(),D.Y(),0.) );
507 Handle(Geom_TrimmedCurve) TLine =
508 new Geom_TrimmedCurve(Line, myBis.FirstParameter(),
509 myBis.LastParameter());
510 Curve = GeomProjLib::ProjectOnPlane(TLine, Plane,
511 gp::DZ(), Standard_False);
517 char* name = new char[100];
518 sprintf(name,"C2_%d",NbProj);
519 DrawTrSurf::Set(name,TLine);
520 sprintf(name,"C3_%d",NbProj);
521 DrawTrSurf::Set(name,Curve);
522 sprintf(name,"SS_%d",NbProj);
523 DrawTrSurf::Set(name,Plane);
529 PCurve1 = GeomProjLib::Curve2d(Curve,Plane);
532 S = BRep_Tool::Surface(myFace2,L);
534 S = Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
535 if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
536 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
537 Plane = Handle(Geom_Plane)::DownCast(S);
538 PCurve2 = GeomProjLib::Curve2d(Curve,Plane);
543 //=======================================================================
544 //function : FirstParameter
546 //=======================================================================
548 Standard_Real BRepFill_MultiLine::FirstParameter() const
550 return myBis.FirstParameter();
554 //=======================================================================
555 //function : LastParameter
557 //=======================================================================
559 Standard_Real BRepFill_MultiLine::LastParameter() const
561 return myBis.LastParameter();
565 //=======================================================================
568 //=======================================================================
570 gp_Pnt BRepFill_MultiLine::Value(const Standard_Real U) const
572 Handle(Geom_Surface) S;
575 S = BRep_Tool::Surface(myFace1,L);
577 gp_Pnt2d P2d = ValueOnF1(U);
579 gp_Pnt P3d = S->Value(P2d.X(), P2d.Y());
580 P3d.Transform(L.Transformation());
586 //=======================================================================
587 //function : ValueOnFace
589 //=======================================================================
591 static gp_Pnt2d ValueOnFace(const Standard_Real U,
592 const Geom2dAdaptor_Curve& TheBis,
593 const Geom2dAdaptor_Curve& TheU,
594 const Geom2dAdaptor_Curve& TheV,
595 const Standard_Boolean IsIsoU)
597 gp_Pnt2d P = TheBis.Value(U);
599 Geom2dAPI_ProjectPointOnCurve Ext(P,TheU.Curve(),
600 TheU.FirstParameter(),
601 TheU.LastParameter());
604 char* TheUname = "TheU";
605 char* PP1name = "PP1";
606 DrawTrSurf::Set(TheUname,TheU.Curve());
607 DrawTrSurf::Set(PP1name,P);
608 // DrawTrSurf::Set("TheU",TheU.Curve());
609 // DrawTrSurf::Set("PP1",P);
613 Standard_Real UU =0., Dist = Precision::Infinite(), D1, D2;
615 if ( !Ext.NbPoints() == 0 ) {
616 UU = Ext.LowerDistanceParameter();
617 Dist = Ext.LowerDistance();
619 // Control with `ends`
620 D1 = P.Distance(TheU.Value(TheU.FirstParameter()));
621 D2 = P.Distance(TheU.Value(TheU.LastParameter()));
623 if (D1 < Dist || D2 < Dist) {
624 if ( Abs( D1 - D2) < Precision::Confusion()) {
625 if ( TheU.GetType() == GeomAbs_Circle) {
626 gp_Vec2d Axis = TheU.Circle().XAxis().Direction();
627 gp_Vec2d D12d = TheBis.DN(TheBis.FirstParameter(),1);
628 Standard_Real Ang = Axis.Angle(D12d);
629 if ( !TheU.Circle().IsDirect()) Ang = -Ang;
630 UU = ElCLib::InPeriod( Ang, TheU.FirstParameter(),
631 TheU.FirstParameter() + 2*M_PI);
632 Dist = TheU.Circle().Radius();
636 cout << "MultiLine : D1 = D2 and the Curve is not a circle" << endl;
637 cout << " ---> ValueOnFace failed at parameter U = " << U << endl;
639 Standard_ConstructionError::Raise("BRepFill_MultiLine: ValueOnFace");
644 UU = TheU.FirstParameter();
648 UU = TheU.LastParameter();
652 Standard_Real Tol = Precision::Confusion();
655 gp_Pnt2d PF = TheV.Value(TheV.FirstParameter());
656 gp_Pnt2d PL = TheV.Value(TheV.LastParameter());
658 if (Abs(Dist - Abs(PF.Y())) < Tol) {
659 VV = TheV.FirstParameter();
661 else if (Abs(Dist - Abs(PL.Y())) < Tol) {
662 VV = TheV.LastParameter();
665 // test if the curve is at the side `negative Y`.
666 if ( Min( PF.Y(),PL.Y()) < -Tol) Dist = -Dist;
668 Handle(Geom2d_Line) Line
669 = new Geom2d_Line(gp_Pnt2d(0., Dist), gp::DX2d());
673 static Standard_CString aTheV = "TheV" ;
674 DrawTrSurf::Set(aTheV,TheV.Curve());
675 static Standard_CString aLINF1 = "LINF1" ;
676 DrawTrSurf::Set(aLINF1,Line);
680 Geom2dAdaptor_Curve Cu1 = TheV;
681 Geom2dAdaptor_Curve Cu2( Line);
683 Standard_Real TolConf = 0.;
685 Geom2dInt_GInter Intersector(Cu1,Cu2,TolConf,Tol);
687 if ( !Intersector.IsDone()) {
689 cout << "Intersector not done" << endl;
690 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
692 return gp_Pnt2d(0.,0.);
695 if ( Intersector.NbPoints() > 0) {
696 VV = Intersector.Point(1).ParamOnFirst();
698 else if ( Intersector.NbSegments() > 0) {
699 IntRes2d_IntersectionSegment Seg = Intersector.Segment(1);
700 Standard_Real VS1 = Seg.FirstPoint().ParamOnFirst();
701 Standard_Real VS2 = Seg.LastPoint().ParamOnFirst();
702 gp_Pnt2d PS1 = TheV.Value(VS1);
703 gp_Pnt2d PS2 = TheV.Value(VS2);
704 Standard_Real Alp = (Dist - PS1.Y())/(PS2.Y() - PS1.Y());
705 VV = Alp*(VS2 - VS1) + VS1;
709 cout << "Intersector done, but no points found" << endl;
710 cout << " ---> ValueonFace failed at parameter U = " << U << endl;
712 if (Abs(Dist - PL.Y()) < Abs(Dist - PF.Y()))
713 VV = TheV.LastParameter();
715 VV = TheV.FirstParameter();
721 return gp_Pnt2d(VV,UU);
723 return gp_Pnt2d(UU,VV);
726 //=======================================================================
727 //function : ValueOnF1
729 //=======================================================================
731 gp_Pnt2d BRepFill_MultiLine::ValueOnF1(const Standard_Real U) const
733 return ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
737 //=======================================================================
738 //function : ValueOnF2
740 //=======================================================================
742 gp_Pnt2d BRepFill_MultiLine::ValueOnF2(const Standard_Real U) const
744 return ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
747 //=======================================================================
748 //function : Value3dOnF1OnF2
750 //=======================================================================
752 void BRepFill_MultiLine::Value3dOnF1OnF2(const Standard_Real U,
758 PF1 = ValueOnFace(U,myBis,myU1,myV1,myIsoU1);
759 PF2 = ValueOnFace(U,myBis,myU2,myV2,myIsoU2);
761 Handle(Geom_Surface) S;
764 S = BRep_Tool::Surface(myFace1,L);
765 P3d = S->Value(PF1.X(), PF1.Y());
766 P3d.Transform(L.Transformation());
769 //=======================================================================
770 //function : Continuity
772 //=======================================================================
774 GeomAbs_Shape BRepFill_MultiLine::Continuity() const