affc307819abdb043793fed6d896dbe6d2435777
[occt.git] / src / ChFiKPart / ChFiKPart_ComputeData_FilPlnCyl.cxx
1 // File:        ChFiKPart_CompData_PlnCyl.gxx
2 // Created:     Thu Feb  3 15:03:17 1994
3 // Author:      Isabelle GRIGNON
4 //              <isg@zerox>
5
6 #include <ChFiKPart_ComputeData.jxx>
7 #include <Precision.hxx>
8 #include <gp.hxx>
9 #include <gp_Pnt2d.hxx>
10 #include <gp_Dir2d.hxx>
11 #include <gp_Lin2d.hxx>
12 #include <gp_Pnt.hxx>
13 #include <gp_Dir.hxx>
14 #include <gp_Vec.hxx>
15 #include <gp_Lin.hxx>
16 #include <gp_Ax2.hxx>
17 #include <gp_Ax3.hxx>
18 #include <gp_Circ.hxx>
19 #include <gp_Pln.hxx>
20 #include <gp_Cylinder.hxx>
21
22 #include <ElCLib.hxx>
23 #include <ElSLib.hxx>
24
25 #include <Geom2d_Line.hxx>
26 #include <Geom2d_Circle.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Circle.hxx>
29 #include <Geom_ToroidalSurface.hxx>
30 #include <Geom_SphericalSurface.hxx>
31 #include <Geom_CylindricalSurface.hxx>
32 #include <IntAna_QuadQuadGeo.hxx>
33
34 #include <ChFiKPart_ComputeData_Fcts.hxx>
35
36
37 //=======================================================================
38 //function : MakeFillet
39 //purpose  : case cylinder/plane or plane/cylinder.
40 //=======================================================================
41
42 Standard_Boolean ChFiKPart_MakeFillet(TopOpeBRepDS_DataStructure& DStr,
43                                       const Handle(ChFiDS_SurfData)& Data, 
44                                       const gp_Pln& Pln, 
45                                       const gp_Cylinder& Cyl, 
46                                       const Standard_Real fu,
47                                       const Standard_Real lu,
48                                       const TopAbs_Orientation Or1,
49                                       const TopAbs_Orientation Or2,
50                                       const Standard_Real Radius, 
51                                       const gp_Lin& Spine, 
52                                       const Standard_Real First, 
53                                       const TopAbs_Orientation Ofpl,
54                                       const Standard_Boolean plandab)
55 {
56   //calculate the cylinder fillet.
57
58   //plane deviated from radius
59   gp_Ax3 AxPln  = Pln.Position();
60   gp_Dir NorPln = AxPln.XDirection().Crossed(AxPln.YDirection());
61   gp_Dir NorF(NorPln);
62   gp_Ax3 AxCyl = Cyl.Position();
63
64   if (Or1 == TopAbs_REVERSED) { NorF.Reverse(); } 
65   gp_Pln PlanOffset = Pln.Translated(Radius*gp_Vec(NorF));
66
67   // Parallel cylinder
68   Standard_Real    ROff = Cyl.Radius();
69   Standard_Boolean dedans = Standard_False;
70
71   if ((Or2 == TopAbs_FORWARD  &&  Cyl.Direct()) ||
72       (Or2 == TopAbs_REVERSED && !Cyl.Direct()))
73       ROff+=Radius;
74   else if (Radius < ROff)  {
75     ROff-=Radius;dedans = Standard_True;
76   }
77   else {
78 #ifdef DEB
79     cout<<"the fillet does not pass"<<endl; 
80 #endif
81     return Standard_False;
82   }
83   // intersection of the parallel plane and of the parallel cylinder.
84   gp_Cylinder CylOffset(Cyl.Position(),ROff);
85   IntAna_QuadQuadGeo LInt(PlanOffset,CylOffset,
86                           Precision::Angular(),Precision::Confusion());
87   gp_Pnt OrSpine = ElCLib::Value(First,Spine);
88   gp_Pnt OrFillet;
89   gp_Dir DirFillet;
90   if (LInt.IsDone()) {
91     DirFillet = LInt.Line(1).Direction();
92     gp_Pnt P1 = ElCLib::Value(ElCLib::Parameter
93                               (LInt.Line(1),OrSpine),LInt.Line(1));
94     if(LInt.NbSolutions() == 2){
95       gp_Pnt P2 = ElCLib::Value(ElCLib::Parameter
96                                 (LInt.Line(2),OrSpine),LInt.Line(2));
97       if (P1.SquareDistance(OrSpine) < P2.SquareDistance(OrSpine)) {
98         OrFillet = P1;
99       }
100       else { OrFillet = P2;}
101     }
102     else { OrFillet = P1;}
103   }
104   else {return Standard_False;}
105
106   // Construction fillet
107   if (DirFillet.Dot(Spine.Direction()) < 0.) {DirFillet.Reverse();}
108
109   Standard_Real UOnCyl,VOnCyl,UOnPln,VOnPln;
110   ElSLib::Parameters(Cyl,OrFillet,UOnCyl,VOnCyl);
111   Standard_Real tesp = Precision::Confusion();
112   if(UOnCyl < fu - tesp || UOnCyl > lu + tesp) 
113     UOnCyl = ElCLib::InPeriod(UOnCyl,fu,fu+2*PI);
114   ElSLib::Parameters(Pln,OrFillet,UOnPln,VOnPln);
115
116   gp_Vec XDir,OtherDir;
117   XDir     = NorF.Reversed();
118   OtherDir = gp_Dir(gp_Vec(OrFillet,ElSLib::Value(UOnCyl,VOnCyl,Cyl)));
119
120   if (!plandab) {
121     gp_Vec tmp = XDir;
122     XDir     = OtherDir;
123     OtherDir = tmp;
124   }
125   gp_Ax3 AxFil (OrFillet,DirFillet,XDir);
126   // construction YDir to go from face1 to face2.
127   if ((XDir^OtherDir).Dot(DirFillet) < 0.)
128     AxFil.YReverse();
129
130   Handle(Geom_CylindricalSurface) 
131     Fillet = new Geom_CylindricalSurface(AxFil,Radius);
132   Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(Fillet,DStr));
133
134   // FaceInterferences are loaded with pcurves and curves 3D.
135   // edge plane-Fillet
136   gp_Pnt2d PPln2d(UOnPln,VOnPln);
137   gp_Dir2d VPln2d(DirFillet.Dot(AxPln.XDirection()),
138                   DirFillet.Dot(AxPln.YDirection()));
139   gp_Lin2d Lin2dPln(PPln2d,VPln2d);
140   gp_Pnt   POnPln = ElSLib::Value(UOnPln,VOnPln,Pln);
141   gp_Lin   C3d(POnPln,DirFillet);
142   Standard_Real UOnFillet,V;
143   ElSLib::CylinderParameters(AxFil,Radius,POnPln,UOnFillet,V);
144   if(UOnFillet > PI) UOnFillet = 0.;
145   gp_Lin2d LOnFillet(gp_Pnt2d(UOnFillet,V),gp::DY2d());
146   Handle(Geom_Line)   L3d  = new Geom_Line  (C3d);
147   Handle(Geom2d_Line) LFac = new Geom2d_Line(Lin2dPln);
148   Handle(Geom2d_Line) LFil = new Geom2d_Line(LOnFillet);
149   gp_Pnt P;
150   gp_Vec deru,derv;
151   ElSLib::CylinderD1(UOnFillet,V,AxFil,Radius,P,deru,derv);
152   gp_Dir NorFil(deru.Crossed(derv));
153   Standard_Boolean toreverse = ( NorFil.Dot(NorPln) <= 0. );
154   // It is checked if the orientation of the cylinder is the same as of the plane.
155   if (toreverse) {Data->ChangeOrientation() = TopAbs::Reverse(Ofpl);}
156   else           {Data->ChangeOrientation() = Ofpl;}
157
158   TopAbs_Orientation trans; 
159   if ((toreverse && plandab) || (!toreverse && !plandab) ){ 
160     trans = TopAbs_REVERSED; 
161   }
162   else { 
163     trans = TopAbs_FORWARD; 
164   }
165   if (plandab) 
166     Data->ChangeInterferenceOnS1().
167     SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),
168                     trans,LFac,LFil);
169   else    
170     Data->ChangeInterferenceOnS2().
171     SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),
172                     trans,LFac,LFil);
173
174   // edge cylinder-Fillet.
175   gp_Pnt2d PCyl2d(UOnCyl,VOnCyl);
176   gp_Dir2d DPC = gp::DY2d();
177   if (DirFillet.Dot(AxCyl.Direction()) < 0.) DPC.Reverse();
178   gp_Lin2d Lin2dCyl(PCyl2d,DPC);
179   gp_Pnt POnCyl = ElSLib::Value(UOnCyl,VOnCyl,Cyl);
180   C3d = gp_Lin(POnCyl,DirFillet);
181   ElSLib::CylinderParameters(AxFil,Radius,POnCyl,UOnFillet,V);
182   if(UOnFillet > PI) UOnFillet = 0.;
183   LOnFillet = gp_Lin2d(gp_Pnt2d(UOnFillet,V),gp::DY2d());
184   L3d  = new Geom_Line  (C3d);
185   LFac = new Geom2d_Line(Lin2dCyl);
186   LFil = new Geom2d_Line(LOnFillet);  
187   
188   ElSLib::CylinderD1(UOnFillet,V,AxFil,Radius,P,deru,derv);
189   NorFil= gp_Dir(deru.Crossed(derv));
190   ElSLib::CylinderD1(UOnCyl,VOnCyl,AxCyl,Cyl.Radius(),P,deru,derv);
191   gp_Dir NorCyl(deru.Crossed(derv));
192
193   toreverse = ( NorFil.Dot(NorCyl) <= 0. );
194   if ((toreverse && plandab) || (!toreverse && !plandab) ){ 
195     trans = TopAbs_FORWARD; 
196   }
197   else { 
198     trans = TopAbs_REVERSED; 
199   }
200   if (plandab) 
201     Data->ChangeInterferenceOnS2().
202     SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),
203                     trans,LFac,LFil);
204   else    
205     Data->ChangeInterferenceOnS1().
206     SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),
207                     trans,LFac,LFil);
208   return Standard_True;
209 }
210
211 //=======================================================================
212 //function : MakeFillet
213 //purpose  : case cylinder/plane or plane/cylinder.
214 //=======================================================================
215
216 Standard_Boolean ChFiKPart_MakeFillet(TopOpeBRepDS_DataStructure& DStr,
217                                       const Handle(ChFiDS_SurfData)& Data, 
218                                       const gp_Pln& Pln, 
219                                       const gp_Cylinder& Cyl, 
220                                       const Standard_Real fu,
221                                       const Standard_Real lu,
222                                       const TopAbs_Orientation Or1,
223                                       const TopAbs_Orientation Or2,
224                                       const Standard_Real Radius, 
225                                       const gp_Circ& Spine, 
226                                       const Standard_Real First, 
227                                       const TopAbs_Orientation Ofpl,
228                                       const Standard_Boolean plandab)
229 {
230
231 //calculation of the fillet (torus or sphere).
232   Standard_Boolean c1sphere = Standard_False;
233   gp_Ax3 PosPl = Pln.Position();
234   gp_Dir Dpnat = PosPl.XDirection().Crossed(PosPl.YDirection());
235   gp_Dir Dp = Dpnat;
236   gp_Dir Df = Dp;
237   if (Or1 == TopAbs_REVERSED) { Dp.Reverse(); }
238   if (Ofpl == TopAbs_REVERSED) { Df.Reverse(); }
239
240   gp_Pnt Or = Cyl.Location();
241   Standard_Real u,v;
242   ElSLib::PlaneParameters(PosPl,Or,u,v);
243   gp_Pnt2d c2dPln(u,v);
244   ElSLib::PlaneD0(u,v,PosPl,Or);
245   gp_Pnt cPln = Or;
246   Or.SetCoord(Or.X()+Radius*Dp.X(),
247               Or.Y()+Radius*Dp.Y(),
248               Or.Z()+Radius*Dp.Z());
249   gp_Pnt PtSp;
250   gp_Vec DSp;
251  // Modification for the PtSp found at the wrong side of the sewing edge.
252   gp_Pnt PtSp2;
253   gp_Vec DSp2;
254   Standard_Real acote = 1e-7;
255   ElCLib::D1(First,Spine,PtSp,DSp);
256   ElSLib::Parameters(Cyl,PtSp,u,v);
257   if ((Abs(u)<acote) || (Abs(u-(2*PI))<acote)){
258     ElCLib::D1(First+0.2,Spine,PtSp2,DSp2);
259     Standard_Real u2,v2;
260     ElSLib::Parameters(Cyl,PtSp2,u2,v2);
261     if (Abs(u2-u)>PI){
262       u = (2*PI)-u;
263       PtSp = ElSLib::Value(u,v,Cyl);
264       Standard_Real PR;
265       PR = ElCLib::Parameter(Spine,PtSp);
266       ElCLib::D1(PR,Spine,PtSp2,DSp);
267     }
268   }
269   // end of modif
270   gp_Dir Dx(gp_Vec(Or,PtSp));
271   Dx = Dp.Crossed(Dx.Crossed(Dp));
272   gp_Dir Dy(DSp);
273   gp_Pnt PtCyl;
274   gp_Vec Vu,Vv;
275   ElSLib::D1(u,v,Cyl,PtCyl,Vu,Vv);
276   gp_Dir Dc(Vu.Crossed(Vv));
277   if (Or2 == TopAbs_REVERSED) { Dc.Reverse(); }
278   gp_Dir Dz = Dp;
279   Standard_Real Rad,cylrad = Cyl.Radius();
280   Standard_Boolean dedans = (Dx.Dot(Dc) <= 0.);
281   if(dedans){ 
282     if (!plandab){ Dz.Reverse(); } 
283     Rad = cylrad - Radius;
284     if(Abs(Rad) <= Precision::Confusion()){ c1sphere = Standard_True; }
285     else if(Rad < 0){ 
286 #ifdef DEB
287       cout<<"the fillet can't pass"<<endl; 
288 #endif
289       return Standard_False;
290     }
291   }
292   else { 
293     if (plandab){ Dz.Reverse(); } 
294     Rad = cylrad + Radius; 
295   }
296   gp_Ax3 FilAx3(Or,Dz,Dx);
297   if (FilAx3.YDirection().Dot(Dy) <= 0.){ FilAx3.YReverse(); }
298
299   if(c1sphere) {
300     Handle(Geom_SphericalSurface) 
301       gsph = new Geom_SphericalSurface(FilAx3,Radius);
302     Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gsph,DStr));
303   }
304   else{
305     Handle(Geom_ToroidalSurface) 
306       gtor = new Geom_ToroidalSurface(FilAx3,Rad,Radius);
307     Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gtor,DStr));
308   }
309   
310   // It is checked if the orientation of the fillet is the same as of faces.
311   gp_Pnt P,PP;
312   gp_Vec deru,derv;
313   P.SetCoord(cPln.X()+Rad*Dx.X(),
314              cPln.Y()+Rad*Dx.Y(),
315              cPln.Z()+Rad*Dx.Z());
316   u = 0.;
317   if ((dedans && plandab) || (!dedans && !plandab)){ 
318     if (c1sphere) { v = - PI / 2; }
319     else { v = 3 * PI / 2; }
320   }
321   else { v = PI / 2; }
322   gp_Dir norFil;
323   if(c1sphere){
324     ElSLib::SphereD1(u,v,FilAx3,cylrad,PP,deru,derv);
325     norFil = FilAx3.XDirection().Crossed(FilAx3.YDirection());
326     if(v < 0.) norFil.Reverse();
327   }  
328   else{
329     ElSLib::TorusD1(u,v,FilAx3,Rad,Radius,PP,deru,derv);
330     norFil = gp_Dir(deru.Crossed(derv));
331   }  
332   gp_Pnt2d p2dFil(0.,v);
333   Standard_Boolean toreverse = ( norFil.Dot(Df) <= 0. );
334   if (toreverse) { Data->ChangeOrientation() = TopAbs_REVERSED; }
335   else { Data->ChangeOrientation() = TopAbs_FORWARD; }
336
337   // FaceInterferences are loaded with pcurves and curves 3d.
338
339   // The plane face.
340   Handle(Geom2d_Circle) GCirc2dPln;
341   Handle(Geom_Circle) GCircPln;
342   gp_Ax2 circAx2 = FilAx3.Ax2();
343   if(!c1sphere){
344     ElSLib::PlaneParameters(PosPl,P,u,v);
345     gp_Pnt2d p2dPln(u,v);
346     gp_Dir2d d2d(DSp.Dot(PosPl.XDirection()),DSp.Dot(PosPl.YDirection()));
347     gp_Ax22d ax2dPln(c2dPln,gp_Dir2d(gp_Vec2d(c2dPln,p2dPln)),d2d);
348     gp_Circ2d circ2dPln(ax2dPln,Rad);
349     GCirc2dPln = new Geom2d_Circle(circ2dPln);
350     circAx2.SetLocation(cPln);
351     gp_Circ circPln(circAx2,Rad);
352     GCircPln = new Geom_Circle(circPln);
353   }
354   else {
355     ElSLib::PlaneParameters(PosPl,P,u,v);
356     gp_Pnt2d p2dPln(u,v),pbid;
357     if(plandab){
358       Data->Set2dPoints(p2dPln,p2dPln,pbid,pbid);
359     }
360     else {
361       Data->Set2dPoints(pbid,pbid,p2dPln,p2dPln);
362     }
363   }
364   gp_Lin2d lin2dFil(p2dFil,gp::DX2d());
365   Handle(Geom2d_Line) GLin2dFil1 = new Geom2d_Line(lin2dFil);
366   toreverse = ( norFil.Dot(Dpnat) <= 0. );
367   TopAbs_Orientation trans; 
368   if ((toreverse && plandab) || (!toreverse && !plandab) ){ 
369     trans = TopAbs_FORWARD; 
370   }
371   else { 
372     trans = TopAbs_REVERSED; 
373   }
374   if(plandab){
375     Data->ChangeInterferenceOnS1().
376       SetInterference(ChFiKPart_IndexCurveInDS(GCircPln,DStr),
377                       trans,GCirc2dPln,GLin2dFil1);
378   }
379   else{
380     Data->ChangeInterferenceOnS2().
381       SetInterference(ChFiKPart_IndexCurveInDS(GCircPln,DStr),
382                       trans,GCirc2dPln,GLin2dFil1);
383   }
384
385   // The cylindrical face.
386   P.SetCoord(Or.X()+cylrad*Dx.X(),
387              Or.Y()+cylrad*Dx.Y(),
388              Or.Z()+cylrad*Dx.Z());
389   u = 0.;
390   if (dedans) {
391     if (plandab && !c1sphere) { v = 2 * PI; }
392     else { v = 0. ; }
393   }
394   else { v = PI; }
395   p2dFil.SetCoord(u,v);
396   if(c1sphere){
397     ElSLib::SphereD1(u,v,FilAx3,cylrad,PP,deru,derv);
398   }  
399   else{
400     ElSLib::TorusD1(u,v,FilAx3,Rad,Radius,PP,deru,derv);
401   }  
402   norFil = deru.Crossed(derv);
403   lin2dFil.SetLocation(p2dFil);
404   Handle(Geom2d_Line) GLin2dFil2 = new Geom2d_Line(lin2dFil);
405   ElSLib::Parameters(Cyl,P,u,v);
406   Standard_Real tol = Precision::PConfusion();
407   Standard_Boolean careaboutsens = 0;
408   if(Abs(lu - fu - 2*PI) < tol) careaboutsens = 1;
409   if(u >= fu - tol && u < fu) u = fu;
410   if(u <= lu + tol && u > lu) u = lu;
411   if(u < fu || u > lu) u = ChFiKPart_InPeriod(u,fu,fu + 2*PI,tol);
412   ElSLib::D1(u,v,Cyl,PP,deru,derv);
413   gp_Dir norcyl = deru.Crossed(derv);
414   gp_Dir2d d2dCyl = gp::DX2d();
415   if( deru.Dot(Dy) < 0. ){
416     d2dCyl.Reverse(); 
417     if(careaboutsens && Abs(fu-u)<tol) u = lu;
418   }
419   else if(careaboutsens && Abs(lu-u)<tol) u = fu;
420   gp_Pnt2d p2dCyl(u,v);
421   gp_Lin2d lin2dCyl(p2dCyl,d2dCyl);
422   Handle(Geom2d_Line) GLin2dCyl = new Geom2d_Line(lin2dCyl);
423   circAx2.SetLocation(Or);
424   gp_Circ circCyl(circAx2,cylrad);
425   Handle(Geom_Circle) GCircCyl = new Geom_Circle(circCyl);
426   toreverse = ( norFil.Dot(norcyl) <= 0. );
427   if ((toreverse && plandab) || (!toreverse && !plandab) ){ 
428     trans = TopAbs_REVERSED; 
429   }
430   else { 
431     trans = TopAbs_FORWARD; 
432   }
433   if(plandab){
434     Data->ChangeInterferenceOnS2().
435       SetInterference(ChFiKPart_IndexCurveInDS(GCircCyl,DStr),
436                       trans,GLin2dCyl,GLin2dFil2);
437     
438   }
439   else{
440     Data->ChangeInterferenceOnS1().
441       SetInterference(ChFiKPart_IndexCurveInDS(GCircCyl,DStr),
442                       trans,GLin2dCyl,GLin2dFil2);
443   }
444   return Standard_True;
445 }
446
447