1 // Created on: 1998-06-18
2 // Created by: Philippe NOUAILLE
3 // Copyright (c) 1998-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 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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <ChFiKPart_ComputeData.ixx>
19 #include <Precision.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <gp_Dir2d.hxx>
23 #include <gp_Lin2d.hxx>
30 #include <gp_Circ.hxx>
35 #include <Geom2d_Line.hxx>
36 #include <Geom2d_Circle.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_ConicalSurface.hxx>
39 #include <Geom_CylindricalSurface.hxx>
41 #include <ChFiKPart_ComputeData_Fcts.hxx>
44 //=======================================================================
45 //function : MakeChAsym
46 //purpose : Compute the chamfer in the particular case Plane/Cone or
48 // Compute the SurfData <Data> of the chamfer build on the <Spine>
49 // between the plane <Pln> and the cone <Con>, with the
50 // distances <Dis1> on <Pln> and <Dis2> on <Con>.
51 // <Or1> and <Or2> are the orientations of <Pln> and <Con>
52 // and <Ofpl> this of the face carried by <Pln>.
53 // <First> is the start point on the <Spine>
54 // <Plandab> is equal to True if the plane is the surface S1
55 // <fu> and <lu> are the first and last u parameters of the
57 //out : True if the chanfer has been computed
59 //=======================================================================
61 Standard_Boolean ChFiKPart_MakeChAsym(TopOpeBRepDS_DataStructure& DStr,
62 const Handle(ChFiDS_SurfData)& Data,
65 const Standard_Real fu,
66 const Standard_Real lu,
67 const TopAbs_Orientation Or1,
68 const TopAbs_Orientation Or2,
69 const Standard_Real Dis,
70 const Standard_Real Angle,
72 const Standard_Real First,
73 const TopAbs_Orientation Ofpl,
74 const Standard_Boolean plandab,
75 const Standard_Boolean DisOnP)
77 // Compute the chamfer surface(cone)
78 gp_Ax3 PosPl = Pln.Position();
79 gp_Dir Dpl = PosPl.XDirection().Crossed(PosPl.YDirection());
81 if (Ofpl == TopAbs_REVERSED ) norf.Reverse();
82 if ( Or1 == TopAbs_REVERSED ) Dpl.Reverse();
84 // compute the origin of the conical chamfer PtPl
85 gp_Pnt Or = Con.Location();
87 ElSLib::PlaneParameters(PosPl,Or,u,v);
88 gp_Pnt2d pt2dPln(u,v);
89 ElSLib::PlaneD0(u,v,PosPl,Or);
94 ElCLib::D1(First,Spine,PtSp,DSp);
95 gp_Dir Dx(gp_Vec(PtPl,PtSp));
97 //compute the normal to the cone in PtSp
100 ElSLib::Parameters(Con,PtSp,u,v);
101 ElSLib::D1(u,v,Con,PtCon ,deru,derv);
102 gp_Dir Dcon( deru.Crossed(derv) );
103 if ( Or2 == TopAbs_REVERSED ) Dcon.Reverse();
105 Standard_Boolean dedans = ( Dx.Dot(Dcon) <= 0.);
106 Standard_Boolean ouvert = ( Dpl.Dot(Dcon) >= 0.);
108 // variables used to compute the semiangle of the chamfer
109 Standard_Real angCon = Con.SemiAngle();
111 Standard_Real ChamfRad,SemiAngl;
112 Standard_Boolean pointu = Standard_False;
114 Standard_Boolean iscylinder = Standard_False;
115 Standard_Boolean isConPar = Standard_False;
117 if ( (plandab && DisOnP) || (!plandab && !DisOnP) ) {
118 Standard_Real tgang = Tan(Angle), Dis11;
119 Standard_Real tgCon = Abs(Tan(angCon));
121 move = Dis * tgang / (1. - tgCon * tgang);
122 Dis11 = move * tgCon;
126 move = Dis * tgang / (1. + tgCon * tgang);
127 Dis11 = move * tgCon;
131 // compute the parameters of the conical chamfer
133 ChamfRad = Spine.Radius() - Dis;
134 if ( Abs(ChamfRad) < Precision::Confusion() ) pointu = Standard_True;
137 cout<<"the chamfer can't pass"<<endl;
139 return Standard_False;
141 SemiAngl = M_PI / 2. - Angle;
144 ChamfRad = Spine.Radius() + Dis;
145 SemiAngl = Angle - M_PI / 2.;
149 if (Abs(angCon) - Abs(SemiAngl) > -Precision::Confusion() ) {
151 cout<<"wrong choice of angle for the chamfer"<<endl;
153 return Standard_False;
159 move = Dis * Cos(angCon);
161 SemiAngl = Abs(angCon) + Angle;
163 if ( (M_PI / 2. - SemiAngl) < Precision::Confusion() ) {
165 cout <<"wrong choice of angle for the chamfer"<<endl;
167 return Standard_False;
169 Dis1 = move * Tan(SemiAngl) - Dis * Abs(Sin(angCon));
171 if (!dedans) SemiAngl = -SemiAngl;
175 SemiAngl = Abs(angCon) - Angle;
177 if ( Abs(SemiAngl) < Precision::Confusion() ) {
178 iscylinder = Standard_True;
179 Dis1 = Dis * Abs(Sin(angCon));
182 Dis1 = Dis * Abs(Sin(angCon)) - move * Tan(SemiAngl);
185 if (SemiAngl > Precision::Confusion())
186 isConPar = Standard_True;
188 if (dedans) SemiAngl = -SemiAngl;
192 // compute the parameters of the conical chamfer
194 ChamfRad = Spine.Radius() - Dis1;
196 if ( Abs(ChamfRad) < Precision::Confusion() ) pointu = Standard_True;
199 cout<<"the chamfer can't pass"<<endl;
201 return Standard_False;
205 ChamfRad = Spine.Radius() + Dis1;
210 dis = Dis1 + Dis * Abs(Sin(angCon));
212 dis = Dis1 - Dis * Abs(Sin(angCon));
215 Or.SetCoord( Or.X()+ move*Dpl.X(),
216 Or.Y()+ move*Dpl.Y(),
217 Or.Z()+ move*Dpl.Z());
218 gp_Pnt Pt(Or.X()+dis*PosPl.XDirection().X(),
219 Or.Y()+dis*PosPl.XDirection().Y(),
220 Or.Z()+dis*PosPl.XDirection().Z());
222 gp_Ax3 ChamfAx3(PtPl,Dpl,Dx);
226 Handle (Geom_CylindricalSurface)
227 gcyl = new Geom_CylindricalSurface( ChamfAx3, ChamfRad );
229 // changes due to the fact the parameters of the chamfer must go increasing
230 // from surface S1 to surface S2
232 gcyl->VReverse();// be carefull : the SemiAngle was changed
233 ChamfAx3 = gcyl->Position();
236 // changes due to the fact we have reversed the V direction of
238 if (ChamfAx3.YDirection().Dot(DSp) <= 0.) {
240 gcyl->SetPosition(ChamfAx3);
243 Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gcyl,DStr));
245 Standard_Boolean torevcha = !ChamfAx3.Direct();
246 gp_Dir cylaxe = (ChamfAx3.Axis()).Direction();
247 torevcha = ( (torevcha && !plandab) || (!torevcha && plandab));
249 if (torevcha) cylaxe.Reverse();
250 Standard_Boolean toreverse = (norf.Dot(cylaxe) < 0.);
252 if ((toreverse && dedans) || (!toreverse && !dedans))
253 Data->ChangeOrientation() = TopAbs_REVERSED;
255 Data->ChangeOrientation() = TopAbs_FORWARD;
257 //we load the faceInterference with the pcurves and
260 // Case of the plane face
261 // NB: in the case 'pointu', no pcurve on the plane surface
262 // and no intersection plane-chamfer are needed
264 // intersection plane-chamfer
265 Handle(Geom_Circle) GCirPln;
266 Handle(Geom2d_Circle) GCir2dPln;
267 gp_Ax2 CirAx2 = ChamfAx3.Ax2();
268 CirAx2.SetLocation(PtPl);
270 Pt.SetCoord(PtPl.X()+ChamfRad*Dx.X(),
271 PtPl.Y()+ChamfRad*Dx.Y(),
272 PtPl.Z()+ChamfRad*Dx.Z());
273 gp_Circ CirPln(CirAx2,ChamfRad);
274 GCirPln = new Geom_Circle(CirPln);
276 //pcurve on the plane
277 ElSLib::PlaneParameters(PosPl,Pt ,u,v);
278 gp_Pnt2d p2dPln(u,v);
279 gp_Dir2d d2d(DSp.Dot(PosPl.XDirection()),DSp.Dot(PosPl.YDirection()));
280 gp_Ax22d ax2dPln(pt2dPln, gp_Dir2d(gp_Vec2d(pt2dPln,p2dPln)),d2d);
281 gp_Circ2d cir2dPln(ax2dPln,ChamfRad);
282 GCir2dPln = new Geom2d_Circle(cir2dPln);
286 p2dch.SetCoord(0.,0.);
287 // ElSLib::CylinderD1(0.,0.,ChamfAx3,ChamfRad,Pt,deru,derv);
288 gp_Lin2d lin2dch(p2dch,gp::DX2d());
289 Handle(Geom2d_Line) GLin2dCh1 = new Geom2d_Line(lin2dch);
292 TopAbs_Orientation trans;
293 gp_Dir norpl = PosPl.XDirection().Crossed(PosPl.YDirection());
294 toreverse = (norpl.Dot(cylaxe) < 0.);
296 toreverse = (toreverse && plandab) || (!toreverse && !plandab);
298 if ((toreverse && dedans) || (!toreverse && !dedans)) {
299 trans = TopAbs_FORWARD;
302 trans = TopAbs_REVERSED;
306 Data->ChangeInterferenceOnS1().
307 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
308 trans,GCir2dPln,GLin2dCh1);
311 Data->ChangeInterferenceOnS2().
312 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
313 trans,GCir2dPln,GLin2dCh1);
316 // Case of the conical face
318 //intersection cone-chamfer
321 Rad = ChamfRad + dis;
323 Rad = ChamfRad - dis;
325 CirAx2.SetLocation(Or);
326 gp_Circ CirCon(CirAx2, Rad);
327 Handle(Geom_Circle) GCirCon = new Geom_Circle(CirCon);
331 v = sqrt(dis*dis + move*move);
333 v = - sqrt(dis*dis + move*move);
334 p2dch.SetCoord(0.,v);
335 ElSLib::CylinderD1(0.,v,ChamfAx3,ChamfRad,Pt,deru,derv);
336 lin2dch.SetLocation(p2dch);
337 Handle(Geom2d_Line) GLin2dCh2 = new Geom2d_Line(lin2dch);
340 Pt.SetCoord(Or.X()+Rad*Dx.X(),
343 ElSLib::Parameters(Con,Pt ,u,v);
344 Standard_Real tol = Precision::PConfusion();
345 if(u >= 2*M_PI - tol && u <= 2*M_PI) u = 0.;
346 if(u >= fu - tol && u < fu) u = fu;
347 if(u <= lu + tol && u > lu) u = lu;
348 if(u < fu || u > lu) u = ElCLib::InPeriod(u,fu,fu + 2*M_PI);
349 ElSLib::D1(u,v,Con,Pt,deru,derv);
350 gp_Pnt2d p2dCon(u,v);
352 if ( deru.Dot(DSp)<=0. )
353 d2dCon = - gp::DX2d();
356 gp_Lin2d lin2dCon(p2dCon,d2dCon);
357 Handle(Geom2d_Line) GLin2dCon = new Geom2d_Line(lin2dCon);
360 gp_Dir norcon = deru.Crossed(derv);
362 gp_Dir DirCon = (Con.Axis()).Direction();
363 if (angCon > Precision::Confusion()) DirCon.Reverse();
364 Standard_Boolean torevcon = ( norcon.Dot(DirCon) < 0. );
366 if ((torevcon && dedans) || (!torevcon && !dedans) ) {
367 trans = TopAbs_REVERSED;
370 trans = TopAbs_FORWARD;
374 Data->ChangeInterferenceOnS2().
375 SetInterference(ChFiKPart_IndexCurveInDS(GCirCon,DStr),
376 trans,GLin2dCon,GLin2dCh2);
379 Data->ChangeInterferenceOnS1().
380 SetInterference(ChFiKPart_IndexCurveInDS(GCirCon,DStr),
381 trans,GLin2dCon,GLin2dCh2);
385 Handle (Geom_ConicalSurface)
386 gcon = new Geom_ConicalSurface( ChamfAx3, SemiAngl, ChamfRad );
388 // changes due to the fact the parameters of the chamfer must go increasing
389 // from surface S1 to surface S2
391 gcon->VReverse();// be carefull : the SemiAngle was changed
392 ChamfAx3 = gcon->Position();
393 SemiAngl = gcon->SemiAngle();
396 // changes due to the fact we have reversed the V direction of
398 if (ChamfAx3.YDirection().Dot(DSp) <= 0.) {
400 gcon->SetPosition(ChamfAx3);
403 Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gcon,DStr));
405 //compute the chamfer's orientation according to the orientation
408 //search the normal to the conical chamfer
412 v = sqrt(dis*dis + move*move);
414 v = - sqrt(dis*dis + move*move);
416 ElSLib::ConeD1(u,v,ChamfAx3,ChamfRad,SemiAngl,P,deru,derv);
417 gp_Dir norchamf(deru.Crossed(derv));
419 Standard_Boolean toreverse = (norf.Dot(norchamf) < 0.);
421 if (isConPar) toreverse = !toreverse;
424 Data->ChangeOrientation() = TopAbs_REVERSED;
426 Data->ChangeOrientation() = TopAbs_FORWARD;
428 //we load the faceInterference with the pcurves and
431 // Case of the plane face
432 // NB: in the case 'pointu', no pcurve on the plane surface
433 // and no intersection plane-chamfer are needed
435 // intersection plane-chamfer
436 Handle(Geom_Circle) GCirPln;
437 Handle(Geom2d_Circle) GCir2dPln;
438 gp_Ax2 CirAx2 = ChamfAx3.Ax2();
439 CirAx2.SetLocation(PtPl);
442 Pt.SetCoord(PtPl.X()+ChamfRad*Dx.X(),
443 PtPl.Y()+ChamfRad*Dx.Y(),
444 PtPl.Z()+ChamfRad*Dx.Z());
445 gp_Circ CirPln(CirAx2,ChamfRad);
446 GCirPln = new Geom_Circle(CirPln);
448 //pcurve on the plane
449 ElSLib::PlaneParameters(PosPl,Pt ,u,v);
450 gp_Pnt2d p2dPln(u,v);
451 gp_Dir2d d2d(DSp.Dot(PosPl.XDirection()),DSp.Dot(PosPl.YDirection()));
452 gp_Ax22d ax2dPln(pt2dPln, gp_Dir2d(gp_Vec2d(pt2dPln,p2dPln)),d2d);
453 gp_Circ2d cir2dPln(ax2dPln,ChamfRad);
454 GCir2dPln = new Geom2d_Circle(cir2dPln);
459 p2dch.SetCoord(0.,0.);
460 ElSLib::ConeD1(0.,0.,ChamfAx3,ChamfRad,SemiAngl,Pt,deru,derv);
461 gp_Lin2d lin2dch(p2dch,gp::DX2d());
462 Handle(Geom2d_Line) GLin2dCh1 = new Geom2d_Line(lin2dch);
465 TopAbs_Orientation trans;
466 gp_Dir norpl = PosPl.XDirection().Crossed(PosPl.YDirection());
468 norchamf.SetXYZ (deru.Crossed(derv).XYZ());
469 toreverse = ( norchamf.Dot(norpl) <= 0. );
471 if (isConPar) toreverse = !toreverse;
473 if ((toreverse && plandab) || (!toreverse && !plandab)){
474 trans = TopAbs_FORWARD;
477 trans = TopAbs_REVERSED;
481 Data->ChangeInterferenceOnS1().
482 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
483 trans,GCir2dPln,GLin2dCh1);
486 Data->ChangeInterferenceOnS2().
487 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
488 trans,GCir2dPln,GLin2dCh1);
491 // Case of the conical face
493 //intersection cone-chamfer
496 Rad = ChamfRad + dis;
498 Rad = ChamfRad - dis;
500 CirAx2.SetLocation(Or);
501 gp_Circ CirCon(CirAx2, Rad);
502 Handle(Geom_Circle) GCirCon = new Geom_Circle(CirCon);
506 v = sqrt(dis*dis + move*move);
508 v = - sqrt(dis*dis + move*move);
509 p2dch.SetCoord(0.,v);
510 ElSLib::ConeD1(0.,v,ChamfAx3,ChamfRad,SemiAngl,Pt,deru,derv);
511 lin2dch.SetLocation(p2dch);
512 Handle(Geom2d_Line) GLin2dCh2 = new Geom2d_Line(lin2dch);
515 norchamf.SetXYZ (deru.Crossed(derv).XYZ());
517 Pt.SetCoord(Or.X()+Rad*Dx.X(),
520 ElSLib::Parameters(Con,Pt ,u,v);
521 Standard_Real tol = Precision::PConfusion();
522 if (u >= 2*M_PI - tol && u <= 2*M_PI) u = 0.;
523 if (u >= fu - tol && u < fu) u = fu;
524 if (u <= lu + tol && u > lu) u = lu;
525 if (u < fu || u > lu) u = ElCLib::InPeriod(u,fu,fu + 2*M_PI);
526 ElSLib::D1(u,v,Con,Pt,deru,derv);
527 gp_Pnt2d p2dCon(u,v);
529 if ( deru.Dot(DSp)<=0. )
530 d2dCon = - gp::DX2d();
533 gp_Lin2d lin2dCon(p2dCon,d2dCon);
534 Handle(Geom2d_Line) GLin2dCon = new Geom2d_Line(lin2dCon);
537 gp_Dir norcon = deru.Crossed(derv);
539 gp_Dir DirCon = (Con.Axis()).Direction();
540 gp_Dir DirChamf = (gcon->Axis()).Direction();
541 if (angCon > Precision::Confusion()) DirCon.Reverse();
542 if (SemiAngl > Precision::Confusion()) DirChamf.Reverse();
544 Standard_Boolean torevcon = ( norcon.Dot(DirCon) > 0. );
545 Standard_Boolean torevcha = ( norchamf.Dot(DirChamf) > 0. );
547 toreverse = ( (torevcon && !torevcha) || (!torevcon && torevcha) );
549 if ((toreverse && plandab) || (!toreverse && !plandab) ) {
550 trans = TopAbs_REVERSED;
553 trans = TopAbs_FORWARD;
557 Data->ChangeInterferenceOnS2().
558 SetInterference(ChFiKPart_IndexCurveInDS(GCirCon,DStr),
559 trans,GLin2dCon,GLin2dCh2);
562 Data->ChangeInterferenceOnS1().
563 SetInterference(ChFiKPart_IndexCurveInDS(GCirCon,DStr),
564 trans,GLin2dCon,GLin2dCh2);
568 return Standard_True;