1 // File: ChFiKPart_ComputeData_ChAsymPlnCyl.cxx
2 // Created: Tue Jun 16 11:22:58 1998
3 // Author: Philippe NOUAILLE
4 // <pne@cleox.paris1.matra-dtv.fr>
7 #include <ChFiKPart_ComputeData.ixx>
9 #include <Precision.hxx>
11 #include <gp_Ax22d.hxx>
12 #include <gp_Pnt2d.hxx>
13 #include <gp_Dir2d.hxx>
14 #include <gp_Circ2d.hxx>
18 #include <gp_Circ.hxx>
21 #include <gp_Lin2d.hxx>
26 #include <Geom_ConicalSurface.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom_Line.hxx>
29 #include <Geom2d_Circle.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Plane.hxx>
32 #include <IntAna_QuadQuadGeo.hxx>
34 #include <ChFiKPart_ComputeData_Fcts.hxx>
39 #include <Geom_CylindricalSurface.hxx>
42 //=======================================================================
43 //function : MakeChAsym
44 //purpose : Compute the chamfer in the particular case Plane/Cylinder
46 // Compute the SurfData <Data> of the chamfer build on the <Spine>
47 // between the plane <Pln> and the cylinder <Cyl>, with the
48 // distances <Dis> and <Angle> on <Pln> on <Cyl>.
49 // <Or1> and <Or2> are the orientations of <Pln> and <Cyl>
50 // and <Ofpl> this of the face carried by <Pln>.
51 // <First> is the start point on the <Spine>
52 // <Plandab> is equal to True if the plane is the surface S1
53 // <fu> and <lu> are the first and last u parameters of the
55 // DisOnPlan is equal to True if Dis on plan, else False
56 //out : True if the chanfer has been computed
58 //=======================================================================
60 Standard_Boolean ChFiKPart_MakeChAsym(TopOpeBRepDS_DataStructure& DStr,
61 const Handle(ChFiDS_SurfData)& Data,
63 const gp_Cylinder& Cyl,
64 const Standard_Real fu,
65 const Standard_Real lu,
66 const TopAbs_Orientation Or1,
67 const TopAbs_Orientation Or2,
68 const Standard_Real Dis,
69 const Standard_Real Angle,
71 const Standard_Real First,
72 const TopAbs_Orientation Ofpl,
73 const Standard_Boolean plandab,
74 const Standard_Boolean DisOnP)
76 // compute the chamfer surface(cone)
78 // compute the normals to the plane surface & to the plane face
79 gp_Ax3 PosPl = Pln.Position();
80 gp_Dir Dpl = PosPl.XDirection().Crossed(PosPl.YDirection());
82 if ( Ofpl == TopAbs_REVERSED) norf.Reverse();
83 if (Or1 == TopAbs_REVERSED) Dpl.Reverse();
85 // compute the origin Or of the cone
86 gp_Pnt Or = Cyl.Location();
88 ElSLib::PlaneParameters(PosPl, Or, u, v);
89 gp_Pnt2d pt2dPln(u, v);
90 ElSLib::PlaneD0(u, v, PosPl, Or);
91 gp_Pnt PtPl = Or; // projection of the cylinder origin
94 gp_Pnt PtSp;//start 3d point on the Spine
95 gp_Vec DSp; //tangent vector to the spine on PtSp
96 ElCLib::D1(First, Spine, PtSp, DSp);
97 gp_Dir Dx(gp_Vec(Or, PtSp));
99 ElSLib::Parameters(Cyl, PtSp, u, v);
100 gp_Pnt PtCyl;//point on the cylinder and on the Spine
102 ElSLib::D1(u, v, Cyl, PtCyl, Vu, Vv);
103 gp_Dir Dcyl(Vu.Crossed(Vv));//normal to the cylinder in PtSp
104 if (Or2 == TopAbs_REVERSED) Dcyl.Reverse();
105 Standard_Boolean dedans = ( Dcyl.Dot(Dx) <= 0.);
107 Standard_Boolean pointu = Standard_False;
108 Standard_Real ConRad, Rad, SemiAngl;
110 //Calculation of distance
111 Standard_Real dis1, dis2, cosNPCyl, sinNPCyl;
113 if ( (plandab && DisOnP) || (!plandab && !DisOnP) ) {
115 cosNPCyl = Dpl.Dot(Dcyl);
116 sinNPCyl = sqrt(1. - cosNPCyl * cosNPCyl);
117 dis2 = Dis / (sinNPCyl / tan(Angle) - cosNPCyl);
121 cosNPCyl = Dpl.Dot(Dcyl);
122 sinNPCyl = sqrt(1. - cosNPCyl * cosNPCyl);
123 dis1 = Dis / (sinNPCyl / tan(Angle) - cosNPCyl);
126 Or.SetCoord(Or.X() + dis2 * Dpl.X(),
127 Or.Y() + dis2 * Dpl.Y(),
128 Or.Z() + dis2 * Dpl.Z());
130 // variables used to compute the semiangle of the cone
131 gp_Dir Vec1(Or.X() - PtPl.X(), Or.Y() - PtPl.Y(), Or.Z() - PtPl.Z());
132 gp_Pnt Pt(Or.X() + dis1*PosPl.XDirection().X(),
133 Or.Y() + dis1*PosPl.XDirection().Y(),
134 Or.Z() + dis1*PosPl.XDirection().Z());
135 gp_Dir Vec2( Pt.X() - PtPl.X(), Pt.Y() - PtPl.Y(), Pt.Z() - PtPl.Z());
137 // compute the parameters of the conical surface
139 Rad = Cyl.Radius() - dis1;
140 if ( Abs(Rad) <= Precision::Confusion() ) pointu = Standard_True;
142 cout<<"the chamfer can't pass"<<endl;
143 return Standard_False;
147 Rad = Cyl.Radius() + dis1;
148 gp_Dir Dplr = Dpl.Reversed();
151 ConRad = Cyl.Radius();
152 SemiAngl = Vec1.Angle(Vec2);
153 gp_Ax3 ConAx3(Or, Dpl, Dx);
155 Handle (Geom_ConicalSurface)
156 gcon = new Geom_ConicalSurface( ConAx3, SemiAngl, ConRad );
158 // changes due to the fact the parameters of the chamfer must go increasing
159 // from surface S1 to surface S2
160 if ( (dedans && !plandab) || (!dedans && plandab) ) {
161 gcon->VReverse();// be carefull : the SemiAngle was changed
162 ConAx3 = gcon->Position();
163 SemiAngl = gcon->SemiAngle();
166 // changes due to the fact we have reversed the V direction of
168 if (ConAx3.YDirection().Dot(DSp) <= 0.) {
170 gcon->SetPosition(ConAx3);
173 Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gcon, DStr));
175 // compute the chamfer's orientation according to the orientation
178 //search the normal to the cone
180 ElSLib::ConeD1(0., 0., ConAx3, ConRad, SemiAngl, Pt, deru, derv);
182 gp_Dir norCon(deru.Crossed(derv));
184 Standard_Boolean toreverse = ( norCon.Dot(norf) <= 0.);
186 Data->ChangeOrientation() = TopAbs_REVERSED;
189 Data->ChangeOrientation() = TopAbs_FORWARD;
192 //we load of the faceInterference with the pcurves and
195 // Case of the plane face
196 // NB: in the case 'pointu', no pcurve on the plane surface
197 // and no intersection plane-chamfer are needed
198 Handle(Geom2d_Circle) GCir2dPln;
199 Handle(Geom_Circle) GCirPln;
200 gp_Ax2 CirAx2 = ConAx3.Ax2();
201 CirAx2.SetLocation(PtPl);
204 // intersection plane-chamfer
205 gp_Circ CirPln(CirAx2, Rad);
206 GCirPln = new Geom_Circle(CirPln);
208 //pcurve on the plane
209 ElSLib::PlaneParameters(PosPl, Pt, u, v);
210 gp_Pnt2d p2dPln(u, v);
211 gp_Dir2d d2d(DSp.Dot(PosPl.XDirection()), DSp.Dot(PosPl.YDirection()));
212 gp_Ax22d ax2dPln(pt2dPln, gp_Dir2d(gp_Vec2d(pt2dPln, p2dPln)), d2d);
213 gp_Circ2d cir2dPln(ax2dPln, Rad);
214 GCir2dPln = new Geom2d_Circle(cir2dPln);
217 //pcurve on the chamfer
220 v= -sqrt(dis1 * dis1 + dis2 * dis2);
222 v = sqrt(dis1 * dis1 + dis2 * dis2);
223 p2dch.SetCoord(0., v);
224 ElSLib::ConeD1(0., v, ConAx3, ConRad, SemiAngl, Pt, deru, derv);
225 gp_Lin2d lin2dch(p2dch, gp::DX2d());
226 Handle(Geom2d_Line) GLin2dCh1 = new Geom2d_Line(lin2dch);
229 TopAbs_Orientation trans;
230 gp_Dir norpl = PosPl.XDirection().Crossed(PosPl.YDirection());
231 toreverse = ( norCon.Dot(norpl) <= 0. );
232 if ((toreverse && plandab) || (!toreverse && !plandab)){
233 trans = TopAbs_FORWARD;
236 trans = TopAbs_REVERSED;
241 Data->ChangeInterferenceOnS1().
242 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln, DStr),
243 trans, GCir2dPln, GLin2dCh1);
246 Data->ChangeInterferenceOnS2().
247 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln, DStr),
248 trans,GCir2dPln, GLin2dCh1);
251 // Case of the cylindrical face
253 //intersection cylinder-chamfer
254 CirAx2.SetLocation(Or);
255 gp_Circ CirCyl(CirAx2, ConRad);
256 Handle(Geom_Circle) GCirCyl = new Geom_Circle(CirCyl);
258 //pcurve on the chamfer
259 p2dch.SetCoord(0., 0.);
260 ElSLib::ConeD1(0., 0., ConAx3, ConRad, SemiAngl, Pt, deru, derv);
261 lin2dch.SetLocation(p2dch);
262 Handle(Geom2d_Line) GLin2dCh2 = new Geom2d_Line(lin2dch);
264 //pcurve on the cylinder
265 norCon.SetXYZ (deru.Crossed(derv).XYZ());
267 Pt.SetCoord(Or.X() + ConRad * Dx.X(),
268 Or.Y() + ConRad * Dx.Y(),
269 Or.Z() + ConRad * Dx.Z());
270 ElSLib::Parameters(Cyl, Pt ,u, v);
271 Standard_Real tol = Precision::PConfusion();
272 Standard_Boolean careaboutsens = 0;
273 if(Abs(lu - fu - 2 * PI) < tol) careaboutsens = 1;
274 if(u >= fu - tol && u < fu) u = fu;
275 if(u <= lu + tol && u > lu) u = lu;
276 if(u < fu || u > lu) u = ChFiKPart_InPeriod(u, fu, fu + 2 * PI, tol);
278 ElSLib::D1(u, v, Cyl, Pt, deru, derv);
279 gp_Dir norcyl = deru.Crossed(derv);
280 gp_Dir2d d2dCyl = gp::DX2d();
281 if( deru.Dot(Dy) < 0. ){
283 if(careaboutsens && Abs(fu - u)<tol) u = lu;
285 else if(careaboutsens && Abs(lu - u)<tol) u = fu;
286 gp_Pnt2d p2dCyl(u, v);
287 gp_Lin2d lin2dCyl(p2dCyl, d2dCyl);
288 Handle(Geom2d_Line) GLin2dCyl = new Geom2d_Line(lin2dCyl);
291 toreverse = ( norCon.Dot(norcyl) <= 0. );
292 if ((toreverse && plandab) || (!toreverse && !plandab) ) {
293 trans = TopAbs_REVERSED;
296 trans = TopAbs_FORWARD;
300 Data->ChangeInterferenceOnS2().
301 SetInterference(ChFiKPart_IndexCurveInDS(GCirCyl, DStr),
302 trans, GLin2dCyl, GLin2dCh2);
305 Data->ChangeInterferenceOnS1().
306 SetInterference(ChFiKPart_IndexCurveInDS(GCirCyl, DStr),
307 trans, GLin2dCyl, GLin2dCh2);
310 return Standard_True;
314 //=======================================================================
315 //function : MakeChAsym
316 //purpose : case cylinder/plane or plane/cylinder.
317 //=======================================================================
319 Standard_Boolean ChFiKPart_MakeChAsym(TopOpeBRepDS_DataStructure& DStr,
320 const Handle(ChFiDS_SurfData)& Data,
322 const gp_Cylinder& Cyl,
323 const Standard_Real fu,
324 const Standard_Real lu,
325 const TopAbs_Orientation Or1,
326 const TopAbs_Orientation Or2,
327 const Standard_Real Dis,
328 const Standard_Real Angle,
330 const Standard_Real First,
331 const TopAbs_Orientation Ofpl,
332 const Standard_Boolean plandab,
333 const Standard_Boolean DisOnP)
335 // calculation of the fillet plane.
336 // or1 and or2 permit to determine in which of four sides created by
337 // intersection of 2 surfaces we are
338 // _|_ Ofpl is orientation of the plane face allowing
339 // |4 to determine the side of the material
341 gp_Pnt OrSpine = ElCLib::Value(First, Spine);
342 gp_Pnt POnCyl, POnPln, OrCyl;
344 gp_Dir XDir = Spine.Direction();
345 gp_Ax3 AxPln = Pln.Position();
346 gp_Dir NorPln = AxPln.XDirection().Crossed(AxPln.YDirection());
348 if (Or1 == TopAbs_REVERSED)
351 gp_Ax3 AxCyl = Cyl.Position();
352 // OrCyl is the point on axis of cylinder in the plane normal to the
353 // axis containing OrSpine
354 gp_Pnt Loc = AxCyl.Location();
355 gp_Vec LocSp(Loc, OrSpine);
356 gp_XYZ temp = AxCyl.Direction().XYZ();
357 temp = temp.Multiplied(LocSp.XYZ().Multiplied(temp) );
358 OrCyl.SetXYZ( (Loc.XYZ()).Added(temp) );
360 //construction of POnPln
361 gp_Vec VecTranslPln,tmp;
363 tmp = gp_Vec(OrSpine,OrCyl);
364 if ((Or2 == TopAbs_FORWARD && Cyl.Direct()) ||
365 (Or2 == TopAbs_REVERSED && !Cyl.Direct()))
368 VecTranslPln = gp_Vec( XDir.Crossed(NorPln) );
369 if( VecTranslPln.Dot(tmp) <= 0. )
370 {VecTranslPln.Reverse();}
373 VecTranslCyl = gp_Vec(OrSpine,OrCyl);
375 // Calculation of distances dis1 and dis2, depending on Dis and Angle
376 gp_Vec DirSOrC = VecTranslCyl.Normalized();
377 Standard_Real cosA1 = DirSOrC.Dot(VecTranslPln.Normalized());
378 Standard_Real sinA1 = Sqrt(1. - cosA1 * cosA1);
380 Standard_Real dis1 = 0.;
384 Standard_Real dis2, ray = Cyl.Radius();
385 Standard_Boolean IsDisOnP = ( (plandab && DisOnP) || (!plandab && !DisOnP) );
389 Standard_Real sinAl = Sin(Angle), cosAl = Cos(Angle);
390 Standard_Real h = dis1 * sinAl;
391 Standard_Real cosAhOC = cosA1 * sinAl + sinA1 * cosAl;
392 Standard_Real sinAhOC = sinA1 * sinAl - cosA1 * cosAl;
393 if (cosA1 > 0) sinAhOC = -sinAhOC;
394 Standard_Real temp1 = h / ray,
395 temp2 = sinAhOC * sinAhOC + temp1 * cosAhOC;
397 dis2 = temp2 + temp1 * (cosAhOC - temp1);
399 if (dis2 < -1.E-09) {
400 cout<<"too great angle of chamfer"<<endl;
401 return Standard_False;
403 else if (dis2 < 1.E-09) {
404 dis2 = ray * Sqrt(2. * temp2);
407 dis2 = ray * Sqrt(2. * (temp2 - sinAhOC * Sqrt(dis2)) );
414 //construction of POnCyl
415 Standard_Real alpha = ( 2*ASin(dis2*0.5/ray) );
416 gp_Vec VecTemp = VecTranslCyl.Reversed();
418 if ( ( XDir.Crossed(gp_Dir(VecTranslCyl)) ).Dot(NorF) < 0.) {
419 VecTemp.Rotate(gp_Ax1(OrCyl,XDir),alpha);
422 VecTemp.Rotate(gp_Ax1(OrCyl,XDir.Reversed()),alpha);}
424 POnCyl.SetXYZ( OrCyl.XYZ().Added(VecTemp.XYZ()) );
425 Standard_Real UOnCyl,VOnCyl,UOnPln,VOnPln;
426 gp_Vec DUOnCyl, DVOnCyl;
427 ElSLib::Parameters(Cyl,POnCyl,UOnCyl,VOnCyl);
428 ElSLib::CylinderD1(UOnCyl, VOnCyl, AxCyl, Cyl.Radius(),
429 POnCyl, DUOnCyl, DVOnCyl);
431 // Construction of the point on the plane
433 gp_Vec Corde(POnCyl, OrSpine);
434 gp_Vec TCyl = DUOnCyl.Crossed(DVOnCyl);
436 TCyl = XDir.Crossed(TCyl);
439 Standard_Real cosCorTan = TCyl.Dot(Corde);
440 Standard_Real tgCorTan = 1. / (cosCorTan * cosCorTan);
441 tgCorTan = Sqrt(tgCorTan - 1.);
443 Standard_Real tgAng = tan(Angle);
444 tgAng = (tgAng + tgCorTan) / (1. - tgAng * tgCorTan);
446 Standard_Real cosA11 = dis2 / (2. * ray);
447 Standard_Real sinA11 = Sqrt(1. - cosA11 * cosA11);
448 if (cosA1 > 0) sinA11 = -sinA11;
449 dis1 = (sinA1 + cosA1 * tgAng) * cosA11;
450 dis1 -= (cosA1 - sinA1 * tgAng) * sinA11;
451 dis1 = (dis2 * tgAng) / dis1;
454 VecTranslPln.Multiply(dis1);
456 POnPln.SetXYZ( (OrSpine.XYZ()).Added(VecTranslPln.XYZ()) );
458 //construction of the chamfer
459 ElSLib::Parameters(Pln,POnPln,UOnPln,VOnPln);
460 POnPln = ElSLib::PlaneValue(UOnPln,VOnPln,AxPln);
462 //construction of YDir to go from face1 to face2.
463 gp_Vec YDir(POnPln,POnCyl);
467 gp_Ax3 AxCh(POnPln,XDir.Crossed(YDir),XDir);
469 Handle(Geom_Plane) Chamfer = new Geom_Plane(AxCh);
470 Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(Chamfer,DStr));
472 // FaceInterferences are loaded with pcurves and curves 3d.
473 //----------- edge plan-Chamfer
474 gp_Pnt2d PPln2d(UOnPln,VOnPln);
475 gp_Dir2d VPln2d(XDir.Dot(AxPln.XDirection()),
476 XDir.Dot(AxPln.YDirection()));
477 gp_Lin2d Lin2dPln(PPln2d,VPln2d);
479 POnPln = ElSLib::Value(UOnPln,VOnPln,Pln);
480 gp_Lin C3d(POnPln,XDir);
482 Standard_Real U,VOnChamfer;
483 ElSLib::PlaneParameters(AxCh,POnPln,U,VOnChamfer);
484 gp_Lin2d LOnChamfer(gp_Pnt2d(U,VOnChamfer),gp::DX2d());
486 Handle(Geom_Line) L3d = new Geom_Line (C3d);
487 Handle(Geom2d_Line) LFac = new Geom2d_Line(Lin2dPln);
488 Handle(Geom2d_Line) LFil = new Geom2d_Line(LOnChamfer);
490 gp_Dir NorFil=AxCh.Direction();
491 Standard_Boolean toreverse = ( NorFil.Dot(NorPln) <= 0. );
492 gp_Dir DirPlnCyl(gp_Vec(POnPln, POnCyl));
493 gp_Dir DirSPln(gp_Vec(OrSpine, POnPln));
494 Standard_Boolean PosChamfPln = DirPlnCyl.Dot(DirSPln) > 0;
496 if ( !IsDisOnP && PosChamfPln )
497 toreverse = !toreverse;
498 // It is checked if the orientation of the Chamfer is the same as of the plane
500 {Data->ChangeOrientation() = TopAbs::Reverse(Ofpl);}
502 {Data->ChangeOrientation() = Ofpl;}
504 TopAbs_Orientation trans = TopAbs_FORWARD;
505 if ((!plandab && toreverse) || (plandab && !toreverse))
506 {trans=TopAbs_REVERSED;}
508 //trans allows to determine the "material" side on S1(2) limited by L3d
510 {Data->ChangeInterferenceOnS1().
511 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);}
513 {Data->ChangeInterferenceOnS2().
514 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);}
516 //------------edge cylindre-Chamfer
517 gp_Pnt2d PCyl2d(UOnCyl,VOnCyl);
518 gp_Dir2d VCyl2d=gp::DY2d();
519 if ( XDir.Dot(AxCyl.Direction())<0 )
521 gp_Lin2d Lin2dCyl(PCyl2d,VCyl2d);
523 POnCyl = ElSLib::Value(UOnCyl,VOnCyl,Cyl);
524 C3d = gp_Lin(POnCyl,XDir);
526 ElSLib::PlaneParameters(AxCh,POnCyl,U,VOnChamfer);
527 LOnChamfer = gp_Lin2d(gp_Pnt2d(U,VOnChamfer),gp::DX2d());
529 L3d = new Geom_Line (C3d);
530 LFac = new Geom2d_Line(Lin2dCyl);
531 LFil = new Geom2d_Line(LOnChamfer);
534 ElSLib::CylinderD1(UOnCyl,VOnCyl,AxCyl,Cyl.Radius(),POnCyl,deru,derv);
535 gp_Dir NorCyl(deru.Crossed(derv));
536 gp_Dir DirSCyl(gp_Vec(OrSpine, POnCyl));
537 Standard_Boolean PosChamfCyl = DirPlnCyl.Dot(DirSCyl) < 0;
538 toreverse = ( NorFil.Dot(NorCyl) <= 0. );
541 if ( IsDisOnP && PosChamfCyl)
542 toreverse = !toreverse;
543 trans = TopAbs_REVERSED;
544 if ((!plandab && toreverse) || (plandab && !toreverse))
545 {trans=TopAbs_FORWARD;}
548 Data->ChangeInterferenceOnS2().
549 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);
551 Data->ChangeInterferenceOnS1().
552 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);
553 return Standard_True;