700e2c8343ead023b05649e2f8020c6181b3448e
[occt.git] / src / ChFiKPart / ChFiKPart_ComputeData_ChPlnCyl.cxx
1 // Created on: 1995-05-19
2 // Created by: Flore Lantheaume
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <ChFiKPart_ComputeData.jxx>
18
19 #include <Precision.hxx>
20 #include <gp.hxx>
21 #include <gp_Ax22d.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <gp_Dir2d.hxx>
24 #include <gp_Circ2d.hxx>
25 #include <gp_Pnt.hxx>
26 #include <gp_Dir.hxx>
27 #include <gp_Vec.hxx>
28 #include <gp_Circ.hxx>
29 #include <gp_Ax2.hxx>
30 #include <gp_Ax3.hxx>
31 #include <gp_Lin2d.hxx>
32
33 #include <ElCLib.hxx>
34 #include <ElSLib.hxx>
35
36 #include <Geom_ConicalSurface.hxx>
37 #include <Geom2d_Line.hxx>
38 #include <Geom_Line.hxx>
39 #include <Geom2d_Circle.hxx>
40 #include <Geom_Circle.hxx>
41 #include <Geom_Plane.hxx>
42 #include <IntAna_QuadQuadGeo.hxx>
43
44 #include <ChFiKPart_ComputeData_Fcts.hxx>
45
46
47 //pour tester
48
49 #include <Geom_CylindricalSurface.hxx>
50
51
52 //=======================================================================
53 //function : MakeChamfer
54 //purpose  : Compute the chamfer in the particular case Plane/Cylinder
55 //           or Cylinder/Plane
56 //           Compute the SurfData <Data> of the chamfer build on the <Spine>
57 //           between the plane <Pln> and the cylinder <Cyl>, with the 
58 //           distances <Dis1> on <Pln> and <Dis2> on <Cyl>.
59 //           <Or1> and <Or2> are the orientations of <Pln> and <Cyl>
60 //           and <Ofpl> this of the face carried by <Pln>.
61 //           <First> is the start point on the <Spine>
62 //           <Plandab> is equal to True if the plane is the surface S1
63 //           <fu> and <lu> are the first and last u parameters of the
64 //           cylinder
65 //out      : True if the chanfer has been computed
66 //           False else
67 //=======================================================================
68
69 Standard_Boolean ChFiKPart_MakeChamfer(TopOpeBRepDS_DataStructure& DStr,
70                                        const Handle(ChFiDS_SurfData)& Data, 
71                                        const gp_Pln& Pln, 
72                                        const gp_Cylinder& Cyl, 
73                                        const Standard_Real fu,
74                                        const Standard_Real lu,
75                                        const TopAbs_Orientation Or1,
76                                        const TopAbs_Orientation Or2,
77                                        const Standard_Real Dis1, 
78                                        const Standard_Real Dis2,
79                                        const gp_Circ& Spine, 
80                                        const Standard_Real First, 
81                                        const TopAbs_Orientation Ofpl,
82                                        const Standard_Boolean plandab)
83 {
84
85   // compute the chamfer surface(cone)
86
87     // compute the normals to the plane surface & to the plane face
88   gp_Ax3 PosPl = Pln.Position();
89   gp_Dir Dpl = PosPl.XDirection().Crossed(PosPl.YDirection());
90   gp_Dir norf = Dpl;
91   if ( Ofpl == TopAbs_REVERSED) norf.Reverse();
92   if (Or1 == TopAbs_REVERSED) Dpl.Reverse();
93
94     // compute the origin Or of the cone
95   gp_Pnt Or = Cyl.Location();
96   Standard_Real u,v;
97   ElSLib::PlaneParameters(PosPl,Or,u,v);
98   gp_Pnt2d pt2dPln(u,v);
99   ElSLib::PlaneD0(u,v,PosPl,Or);
100   gp_Pnt PtPl = Or;  // projection of the cylinder origin 
101                      //on the plane 
102
103   gp_Pnt PtSp;//start 3d point on the Spine 
104   gp_Vec DSp; //tangent vector to the spine on PtSp
105   ElCLib::D1(First,Spine,PtSp,DSp);
106   gp_Dir Dx(gp_Vec(Or,PtSp));
107   gp_Dir Dy(DSp);
108   ElSLib::Parameters(Cyl,PtSp,u,v);
109   gp_Pnt PtCyl;//point on the cylinder and on the Spine
110   gp_Vec Vu,Vv;
111   ElSLib::D1(u,v,Cyl,PtCyl,Vu,Vv);
112   gp_Dir Dcyl(Vu.Crossed(Vv));//normal to the cylinder in PtSp
113   if (Or2 == TopAbs_REVERSED) Dcyl.Reverse();
114   Standard_Boolean dedans = ( Dcyl.Dot(Dx) <= 0.);
115
116   Standard_Boolean pointu = Standard_False;
117   Standard_Real ConRad, Rad, SemiAngl ;
118   Or.SetCoord(Or.X()+Dis2*Dpl.X(),
119               Or.Y()+Dis2*Dpl.Y(),
120               Or.Z()+Dis2*Dpl.Z());
121
122       // variables used to compute the semiangle of the cone
123   gp_Dir Vec1(Or.X()-PtPl.X(), Or.Y()-PtPl.Y(), Or.Z()-PtPl.Z()); 
124   gp_Pnt Pt(Or.X()+Dis1*PosPl.XDirection().X(),
125             Or.Y()+Dis1*PosPl.XDirection().Y(),
126             Or.Z()+Dis1*PosPl.XDirection().Z());
127   gp_Dir Vec2( Pt.X()-PtPl.X(), Pt.Y()-PtPl.Y(), Pt.Z()-PtPl.Z());
128
129       // compute the parameters of the conical surface
130   if (dedans) {
131     Rad = Cyl.Radius()- Dis1;
132     if ( Abs(Rad) <= Precision::Confusion() ) pointu = Standard_True;
133     if(Rad < 0 ) {
134 #ifdef OCCT_DEBUG
135       cout<<"the chamfer can't pass"<<endl;
136 #endif
137       return Standard_False;
138     }
139   }
140   else {
141     Rad = Cyl.Radius()+Dis1;
142     gp_Dir Dplr = Dpl.Reversed();
143     Dpl = Dplr;
144    }
145   ConRad = Cyl.Radius();
146   SemiAngl = Vec1.Angle(Vec2);
147   gp_Ax3 ConAx3(Or,Dpl,Dx);
148
149   Handle (Geom_ConicalSurface)
150     gcon = new Geom_ConicalSurface( ConAx3, SemiAngl, ConRad );
151
152     // changes due to the fact the parameters of the chamfer must go increasing
153     // from surface S1 to surface S2
154   if ( (dedans && !plandab) || (!dedans && plandab) ) {
155     gcon->VReverse();// be carefull : the SemiAngle was changed
156     ConAx3 = gcon->Position();
157     SemiAngl = gcon->SemiAngle();
158   }
159
160       // changes due to the fact we have reversed the V direction of 
161       // parametrization
162   if (ConAx3.YDirection().Dot(DSp) <= 0.) {
163     ConAx3.YReverse();
164     gcon->SetPosition(ConAx3);
165   }
166
167   Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gcon,DStr));
168
169
170   // compute the chamfer's orientation according to the orientation
171   // of the faces
172
173     //search the normal to the cone
174
175   gp_Vec deru, derv;
176   ElSLib::ConeD1(0.,0.,ConAx3,ConRad,SemiAngl,Pt,deru,derv);
177
178   gp_Dir norCon(deru.Crossed(derv));
179   
180   Standard_Boolean toreverse = ( norCon.Dot(norf) <= 0.);
181   if (toreverse) {
182     Data->ChangeOrientation() = TopAbs_REVERSED; 
183   }
184   else {
185     Data->ChangeOrientation() = TopAbs_FORWARD; 
186   }
187   
188   //we load of the faceInterference with the pcurves and
189   // the 3d curves
190
191     // Case of the plane face
192     // NB: in the case 'pointu', no pcurve on the plane surface
193     // and no intersection plane-chamfer are needed
194   Handle(Geom2d_Circle) GCir2dPln;
195   Handle(Geom_Circle) GCirPln;
196   gp_Ax2 CirAx2 = ConAx3.Ax2();
197   CirAx2.SetLocation(PtPl);
198
199   if (!pointu) {
200
201       // intersection plane-chamfer
202     gp_Circ CirPln(CirAx2,Rad);
203     GCirPln = new Geom_Circle(CirPln);
204
205       //pcurve on the plane
206     ElSLib::PlaneParameters(PosPl,Pt ,u,v);
207     gp_Pnt2d p2dPln(u,v);
208     gp_Dir2d d2d(DSp.Dot(PosPl.XDirection()),DSp.Dot(PosPl.YDirection()));
209     gp_Ax22d ax2dPln(pt2dPln, gp_Dir2d(gp_Vec2d(pt2dPln,p2dPln)),d2d);
210     gp_Circ2d cir2dPln(ax2dPln,Rad);
211     GCir2dPln = new Geom2d_Circle(cir2dPln);
212   }
213
214       //pcurve on the chamfer
215   gp_Pnt2d p2dch;
216   if (plandab) 
217     v= -sqrt(Dis1*Dis1+Dis2*Dis2);
218   else 
219     v = sqrt(Dis1*Dis1+Dis2*Dis2);
220   p2dch.SetCoord(0.,v);
221   ElSLib::ConeD1(0.,v,ConAx3,ConRad,SemiAngl,Pt,deru,derv);
222   gp_Lin2d lin2dch(p2dch,gp::DX2d());
223   Handle(Geom2d_Line) GLin2dCh1 = new Geom2d_Line(lin2dch);
224
225       //orientation
226   TopAbs_Orientation trans; 
227   gp_Dir norpl = PosPl.XDirection().Crossed(PosPl.YDirection());
228   toreverse = ( norCon.Dot(norpl) <= 0. );
229   if ((toreverse && plandab) || (!toreverse && !plandab)){ 
230     trans = TopAbs_FORWARD;
231   }
232   else { 
233     trans = TopAbs_REVERSED; 
234   }
235
236
237   if(plandab){
238     Data->ChangeInterferenceOnS1().
239       SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
240                       trans,GCir2dPln,GLin2dCh1);
241   }
242   else{
243     Data->ChangeInterferenceOnS2().
244       SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
245                       trans,GCir2dPln,GLin2dCh1);
246   }
247
248     // Case of the cylindrical face
249
250       //intersection cylinder-chamfer
251   CirAx2.SetLocation(Or);
252   gp_Circ CirCyl(CirAx2,ConRad);
253   Handle(Geom_Circle) GCirCyl = new Geom_Circle(CirCyl);
254
255       //pcurve on the chamfer
256   p2dch.SetCoord(0.,0.);
257   ElSLib::ConeD1(0.,0.,ConAx3,ConRad,SemiAngl,Pt,deru,derv);
258   lin2dch.SetLocation(p2dch);
259   Handle(Geom2d_Line) GLin2dCh2 = new Geom2d_Line(lin2dch);
260
261       //pcurve on the cylinder
262   norCon.SetXYZ (deru.Crossed(derv).XYZ());
263
264   Pt.SetCoord(Or.X()+ConRad*Dx.X(),
265               Or.Y()+ConRad*Dx.Y(),
266               Or.Z()+ConRad*Dx.Z());
267   ElSLib::Parameters(Cyl,Pt ,u,v);
268   Standard_Real tol = Precision::PConfusion();
269   Standard_Boolean careaboutsens = 0;
270   if(Abs(lu - fu - 2*M_PI) < tol) careaboutsens = 1;
271   if(u >= fu - tol && u < fu) u = fu;
272   if(u <= lu + tol && u > lu) u = lu;
273   if(u < fu || u > lu) u = ChFiKPart_InPeriod(u,fu,fu + 2*M_PI,tol);
274
275   ElSLib::D1(u,v,Cyl,Pt,deru,derv);
276   gp_Dir norcyl = deru.Crossed(derv);
277   gp_Dir2d d2dCyl = gp::DX2d();
278   if( deru.Dot(Dy) < 0. ){
279     d2dCyl.Reverse(); 
280     if(careaboutsens && Abs(fu-u)<tol) u = lu;
281   }
282   else if(careaboutsens && Abs(lu-u)<tol) u = fu;
283   gp_Pnt2d p2dCyl(u,v);
284   gp_Lin2d lin2dCyl(p2dCyl,d2dCyl);
285   Handle(Geom2d_Line) GLin2dCyl = new Geom2d_Line(lin2dCyl);
286
287       //orientation
288   toreverse = ( norCon.Dot(norcyl) <= 0. );
289   if ((toreverse && plandab) || (!toreverse && !plandab) ) {
290     trans = TopAbs_REVERSED;
291   }
292   else {
293     trans = TopAbs_FORWARD;
294   }
295
296
297   if(plandab){
298     Data->ChangeInterferenceOnS2().
299       SetInterference(ChFiKPart_IndexCurveInDS(GCirCyl,DStr),
300                       trans,GLin2dCyl,GLin2dCh2);
301   }
302   else{
303     Data->ChangeInterferenceOnS1().
304       SetInterference(ChFiKPart_IndexCurveInDS(GCirCyl,DStr),
305                       trans,GLin2dCyl,GLin2dCh2);
306   }
307
308   return Standard_True;
309 }
310
311 //=======================================================================
312 //function : MakeChamfer
313 //purpose  : case cylinder/plane or plane/cylinder.
314 //=======================================================================
315
316 Standard_Boolean ChFiKPart_MakeChamfer(TopOpeBRepDS_DataStructure& DStr,
317                                       const Handle(ChFiDS_SurfData)& Data, 
318                                        const gp_Pln& Pln, 
319                                        const gp_Cylinder& Cyl, 
320                                        const Standard_Real /*fu*/,
321                                        const Standard_Real /*lu*/,
322                                        const TopAbs_Orientation Or1,
323                                        const TopAbs_Orientation Or2,
324                                        const Standard_Real Dis1,
325                                        const Standard_Real Dis2,
326                                        const gp_Lin& Spine, 
327                                        const Standard_Real First, 
328                                        const TopAbs_Orientation Ofpl,
329                                        const Standard_Boolean plandab)
330 {
331   // calculation of the fillet plane.
332   // or1 and or2 permit to determine in which of four sides created by
333   // intersection of 2 surfaces we are
334   //        _|_          Ofpl is orientation of the plane face allowing
335   //         |4          to determine the side of the material
336
337
338   Standard_Real dis1=Dis1, dis2=Dis2; 
339   if (!plandab){
340       dis1 = Dis2;
341       dis2 = Dis1;}
342
343   gp_Pnt OrSpine = ElCLib::Value(First,Spine);
344   gp_Pnt POnCyl, POnPln, OrCyl;
345
346   gp_Dir XDir = Spine.Direction();
347   gp_Ax3 AxPln  = Pln.Position();
348   gp_Dir NorPln = AxPln.XDirection().Crossed(AxPln.YDirection());
349   gp_Dir NorF(NorPln);
350   if (Or1 == TopAbs_REVERSED)
351     {NorF.Reverse();} 
352
353   gp_Ax3 AxCyl = Cyl.Position();
354   // OrCyl is the point on axis of cylinder in the plane normal to the
355   // axis containing OrSpine
356   // Project <OrSpine> onto <AxCyl>
357   gp_XYZ AxLoc = AxCyl.Location().XYZ(); //aLine.Location().XYZ();
358   gp_XYZ AxDir = AxCyl.Direction().XYZ();
359   Standard_Real Parameter = (OrSpine.XYZ() - AxLoc) * AxDir;
360   OrCyl.SetXYZ( AxLoc + Parameter * AxDir );
361  
362   //construction of POnPln
363   gp_Vec VecTranslPln,tmp;
364
365   tmp = gp_Vec(OrSpine,OrCyl);
366   if ((Or2 == TopAbs_FORWARD && Cyl.Direct()) ||
367       (Or2 == TopAbs_REVERSED && !Cyl.Direct()))
368     {tmp.Reverse();}
369
370   VecTranslPln = gp_Vec( XDir.Crossed(NorPln) );
371   if( VecTranslPln.Dot(tmp) <= 0. )
372      {VecTranslPln.Reverse();}
373   VecTranslPln.Multiply(dis1);
374
375   POnPln.SetXYZ( (OrSpine.XYZ()).Added(VecTranslPln.XYZ()) );
376
377   //construction of POnCyl 
378   Standard_Real alpha = ( 2*ASin(dis2*0.5/Cyl.Radius()) );
379 //  gp_Vec VecTranslCyl;
380 //  VecTranslCyl = gp_Vec(OrSpine,OrCyl);
381  
382 //  if ( ( XDir.Crossed(gp_Dir(VecTranslCyl)) ).Dot(NorF) <=0. )
383 //    {VecTranslCyl.Rotate(gp_Ax1(OrSpine,XDir),alpha);}
384 //  else
385 //    {VecTranslCyl.Rotate(gp_Ax1(OrSpine,XDir.Reversed()),alpha);}
386
387 //  POnCyl.SetXYZ( OrCyl.XYZ().Added(VecTranslCyl.XYZ()) );
388
389   gp_Vec  VecCylTransl = gp_Vec(OrCyl,OrSpine);
390
391   if ( ( XDir.Crossed(gp_Dir(VecCylTransl)) ).Dot(NorF) > 0.) {
392     VecCylTransl.Rotate(gp_Ax1(OrCyl,XDir),alpha);
393   }
394   else { 
395     VecCylTransl.Rotate(gp_Ax1(OrCyl,XDir.Reversed()),alpha);}
396
397   POnCyl.SetXYZ( OrCyl.XYZ().Added(VecCylTransl.XYZ()) );
398
399   //construction of chamfer  
400   Standard_Real UOnCyl,VOnCyl,UOnPln,VOnPln;
401   ElSLib::Parameters(Cyl,POnCyl,UOnCyl,VOnCyl);
402   POnCyl = ElSLib::CylinderValue(UOnCyl,VOnCyl,AxCyl,Cyl.Radius());             
403   ElSLib::Parameters(Pln,POnPln,UOnPln,VOnPln);
404   POnPln = ElSLib::PlaneValue(UOnPln,VOnPln,AxPln);
405
406   //construction of YDir to go to face1 from face2.
407   gp_Vec YDir(POnPln,POnCyl);
408   if (!plandab){ 
409     YDir.Reverse();
410   }
411   gp_Ax3 AxCh(POnPln,XDir.Crossed(YDir),XDir);
412
413   Handle(Geom_Plane) Chamfer = new Geom_Plane(AxCh);
414   Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(Chamfer,DStr));
415
416   // FaceInterferences are loaded with pcurves and curves 3d.
417      //----------- edge plane-Chamfer
418   gp_Pnt2d PPln2d(UOnPln,VOnPln);
419   gp_Dir2d VPln2d(XDir.Dot(AxPln.XDirection()),
420                   XDir.Dot(AxPln.YDirection()));
421   gp_Lin2d Lin2dPln(PPln2d,VPln2d);
422
423   POnPln = ElSLib::Value(UOnPln,VOnPln,Pln);
424   gp_Lin   C3d(POnPln,XDir);
425
426   Standard_Real U,VOnChamfer;
427   ElSLib::PlaneParameters(AxCh,POnPln,U,VOnChamfer);
428   gp_Lin2d LOnChamfer(gp_Pnt2d(U,VOnChamfer),gp::DX2d());
429
430   Handle(Geom_Line)   L3d  = new Geom_Line  (C3d);
431   Handle(Geom2d_Line) LFac = new Geom2d_Line(Lin2dPln);
432   Handle(Geom2d_Line) LFil = new Geom2d_Line(LOnChamfer);
433
434   gp_Dir NorFil=AxCh.Direction();
435   Standard_Boolean toreverse = ( NorFil.Dot(NorPln) <= 0. );
436
437   gp_Dir DirPlnCyl(gp_Vec(POnPln, POnCyl));
438   gp_Dir DirSPln(gp_Vec(OrSpine, POnPln));
439   Standard_Boolean PosChamfPln = DirPlnCyl.Dot(DirSPln) > 0;
440
441   if (PosChamfPln )
442     toreverse = !toreverse; 
443   // It is checked if the orientation of the Chamfer is the same as of the plane
444   if (toreverse)
445     {Data->ChangeOrientation() = TopAbs::Reverse(Ofpl);}
446   else          
447     {Data->ChangeOrientation() = Ofpl;}
448
449   TopAbs_Orientation trans = TopAbs_FORWARD;
450   if ((!plandab && toreverse) || (plandab && !toreverse))
451     {trans=TopAbs_REVERSED;}
452   
453   //trans permits to determine the "material" side on S1(2) limited by L3d
454   if (plandab) 
455     {Data->ChangeInterferenceOnS1().
456      SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);}
457   else    
458     {Data->ChangeInterferenceOnS2().
459      SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);}
460   
461      //------------edge cylinder-Chamfer        
462   gp_Pnt2d PCyl2d(UOnCyl,VOnCyl);
463   gp_Dir2d VCyl2d=gp::DY2d();
464   if ( XDir.Dot(AxCyl.Direction())<0 )
465     {VCyl2d.Reverse();}
466   gp_Lin2d Lin2dCyl(PCyl2d,VCyl2d);
467
468   POnCyl = ElSLib::Value(UOnCyl,VOnCyl,Cyl);
469   C3d = gp_Lin(POnCyl,XDir);
470
471   ElSLib::PlaneParameters(AxCh,POnCyl,U,VOnChamfer);
472   LOnChamfer = gp_Lin2d(gp_Pnt2d(U,VOnChamfer),gp::DX2d());
473
474   L3d  = new Geom_Line  (C3d);
475   LFac = new Geom2d_Line(Lin2dCyl);
476   LFil = new Geom2d_Line(LOnChamfer);
477
478   gp_Vec deru,derv;            
479   ElSLib::CylinderD1(UOnCyl,VOnCyl,AxCyl,Cyl.Radius(),POnCyl,deru,derv);
480   gp_Dir NorCyl(deru.Crossed(derv));    
481
482   toreverse = ( NorFil.Dot(NorCyl) <= 0. );
483
484   gp_Dir DirSCyl(gp_Vec(OrSpine, POnCyl));
485   Standard_Boolean PosChamfCyl = DirPlnCyl.Dot(DirSCyl) < 0;
486
487
488   if (PosChamfCyl) 
489      toreverse = !toreverse; 
490
491   trans = TopAbs_REVERSED;
492   if ((!plandab && toreverse) || (plandab && !toreverse))
493     {trans=TopAbs_FORWARD;}
494
495   if (plandab) 
496     Data->ChangeInterferenceOnS2().
497     SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);
498   else    
499     Data->ChangeInterferenceOnS1().
500     SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);
501   return Standard_True;
502 }       
503   
504
505
506