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
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.jxx>
19 #include <Precision.hxx>
21 #include <gp_Ax22d.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <gp_Dir2d.hxx>
24 #include <gp_Circ2d.hxx>
28 #include <gp_Circ.hxx>
31 #include <gp_Lin2d.hxx>
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>
44 #include <ChFiKPart_ComputeData_Fcts.hxx>
49 #include <Geom_CylindricalSurface.hxx>
52 //=======================================================================
53 //function : MakeChamfer
54 //purpose : Compute the chamfer in the particular case Plane/Cylinder
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
65 //out : True if the chanfer has been computed
67 //=======================================================================
69 Standard_Boolean ChFiKPart_MakeChamfer(TopOpeBRepDS_DataStructure& DStr,
70 const Handle(ChFiDS_SurfData)& Data,
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,
80 const Standard_Real First,
81 const TopAbs_Orientation Ofpl,
82 const Standard_Boolean plandab)
85 // compute the chamfer surface(cone)
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());
91 if ( Ofpl == TopAbs_REVERSED) norf.Reverse();
92 if (Or1 == TopAbs_REVERSED) Dpl.Reverse();
94 // compute the origin Or of the cone
95 gp_Pnt Or = Cyl.Location();
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
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));
108 ElSLib::Parameters(Cyl,PtSp,u,v);
109 gp_Pnt PtCyl;//point on the cylinder and on the Spine
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.);
116 Standard_Boolean pointu = Standard_False;
117 Standard_Real ConRad, Rad, SemiAngl ;
118 Or.SetCoord(Or.X()+Dis2*Dpl.X(),
120 Or.Z()+Dis2*Dpl.Z());
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());
129 // compute the parameters of the conical surface
131 Rad = Cyl.Radius()- Dis1;
132 if ( Abs(Rad) <= Precision::Confusion() ) pointu = Standard_True;
135 cout<<"the chamfer can't pass"<<endl;
137 return Standard_False;
141 Rad = Cyl.Radius()+Dis1;
142 gp_Dir Dplr = Dpl.Reversed();
145 ConRad = Cyl.Radius();
146 SemiAngl = Vec1.Angle(Vec2);
147 gp_Ax3 ConAx3(Or,Dpl,Dx);
149 Handle (Geom_ConicalSurface)
150 gcon = new Geom_ConicalSurface( ConAx3, SemiAngl, ConRad );
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();
160 // changes due to the fact we have reversed the V direction of
162 if (ConAx3.YDirection().Dot(DSp) <= 0.) {
164 gcon->SetPosition(ConAx3);
167 Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(gcon,DStr));
170 // compute the chamfer's orientation according to the orientation
173 //search the normal to the cone
176 ElSLib::ConeD1(0.,0.,ConAx3,ConRad,SemiAngl,Pt,deru,derv);
178 gp_Dir norCon(deru.Crossed(derv));
180 Standard_Boolean toreverse = ( norCon.Dot(norf) <= 0.);
182 Data->ChangeOrientation() = TopAbs_REVERSED;
185 Data->ChangeOrientation() = TopAbs_FORWARD;
188 //we load of the faceInterference with the pcurves and
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);
201 // intersection plane-chamfer
202 gp_Circ CirPln(CirAx2,Rad);
203 GCirPln = new Geom_Circle(CirPln);
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);
214 //pcurve on the chamfer
217 v= -sqrt(Dis1*Dis1+Dis2*Dis2);
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);
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;
233 trans = TopAbs_REVERSED;
238 Data->ChangeInterferenceOnS1().
239 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
240 trans,GCir2dPln,GLin2dCh1);
243 Data->ChangeInterferenceOnS2().
244 SetInterference(ChFiKPart_IndexCurveInDS(GCirPln,DStr),
245 trans,GCir2dPln,GLin2dCh1);
248 // Case of the cylindrical face
250 //intersection cylinder-chamfer
251 CirAx2.SetLocation(Or);
252 gp_Circ CirCyl(CirAx2,ConRad);
253 Handle(Geom_Circle) GCirCyl = new Geom_Circle(CirCyl);
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);
261 //pcurve on the cylinder
262 norCon.SetXYZ (deru.Crossed(derv).XYZ());
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);
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. ){
280 if(careaboutsens && Abs(fu-u)<tol) u = lu;
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);
288 toreverse = ( norCon.Dot(norcyl) <= 0. );
289 if ((toreverse && plandab) || (!toreverse && !plandab) ) {
290 trans = TopAbs_REVERSED;
293 trans = TopAbs_FORWARD;
298 Data->ChangeInterferenceOnS2().
299 SetInterference(ChFiKPart_IndexCurveInDS(GCirCyl,DStr),
300 trans,GLin2dCyl,GLin2dCh2);
303 Data->ChangeInterferenceOnS1().
304 SetInterference(ChFiKPart_IndexCurveInDS(GCirCyl,DStr),
305 trans,GLin2dCyl,GLin2dCh2);
308 return Standard_True;
311 //=======================================================================
312 //function : MakeChamfer
313 //purpose : case cylinder/plane or plane/cylinder.
314 //=======================================================================
316 Standard_Boolean ChFiKPart_MakeChamfer(TopOpeBRepDS_DataStructure& DStr,
317 const Handle(ChFiDS_SurfData)& Data,
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,
327 const Standard_Real First,
328 const TopAbs_Orientation Ofpl,
329 const Standard_Boolean plandab)
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
338 Standard_Real dis1=Dis1, dis2=Dis2;
343 gp_Pnt OrSpine = ElCLib::Value(First,Spine);
344 gp_Pnt POnCyl, POnPln, OrCyl;
346 gp_Dir XDir = Spine.Direction();
347 gp_Ax3 AxPln = Pln.Position();
348 gp_Dir NorPln = AxPln.XDirection().Crossed(AxPln.YDirection());
350 if (Or1 == TopAbs_REVERSED)
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 );
362 //construction of POnPln
363 gp_Vec VecTranslPln,tmp;
365 tmp = gp_Vec(OrSpine,OrCyl);
366 if ((Or2 == TopAbs_FORWARD && Cyl.Direct()) ||
367 (Or2 == TopAbs_REVERSED && !Cyl.Direct()))
370 VecTranslPln = gp_Vec( XDir.Crossed(NorPln) );
371 if( VecTranslPln.Dot(tmp) <= 0. )
372 {VecTranslPln.Reverse();}
373 VecTranslPln.Multiply(dis1);
375 POnPln.SetXYZ( (OrSpine.XYZ()).Added(VecTranslPln.XYZ()) );
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);
382 // if ( ( XDir.Crossed(gp_Dir(VecTranslCyl)) ).Dot(NorF) <=0. )
383 // {VecTranslCyl.Rotate(gp_Ax1(OrSpine,XDir),alpha);}
385 // {VecTranslCyl.Rotate(gp_Ax1(OrSpine,XDir.Reversed()),alpha);}
387 // POnCyl.SetXYZ( OrCyl.XYZ().Added(VecTranslCyl.XYZ()) );
389 gp_Vec VecCylTransl = gp_Vec(OrCyl,OrSpine);
391 if ( ( XDir.Crossed(gp_Dir(VecCylTransl)) ).Dot(NorF) > 0.) {
392 VecCylTransl.Rotate(gp_Ax1(OrCyl,XDir),alpha);
395 VecCylTransl.Rotate(gp_Ax1(OrCyl,XDir.Reversed()),alpha);}
397 POnCyl.SetXYZ( OrCyl.XYZ().Added(VecCylTransl.XYZ()) );
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);
406 //construction of YDir to go to face1 from face2.
407 gp_Vec YDir(POnPln,POnCyl);
411 gp_Ax3 AxCh(POnPln,XDir.Crossed(YDir),XDir);
413 Handle(Geom_Plane) Chamfer = new Geom_Plane(AxCh);
414 Data->ChangeSurf(ChFiKPart_IndexSurfaceInDS(Chamfer,DStr));
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);
423 POnPln = ElSLib::Value(UOnPln,VOnPln,Pln);
424 gp_Lin C3d(POnPln,XDir);
426 Standard_Real U,VOnChamfer;
427 ElSLib::PlaneParameters(AxCh,POnPln,U,VOnChamfer);
428 gp_Lin2d LOnChamfer(gp_Pnt2d(U,VOnChamfer),gp::DX2d());
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);
434 gp_Dir NorFil=AxCh.Direction();
435 Standard_Boolean toreverse = ( NorFil.Dot(NorPln) <= 0. );
437 gp_Dir DirPlnCyl(gp_Vec(POnPln, POnCyl));
438 gp_Dir DirSPln(gp_Vec(OrSpine, POnPln));
439 Standard_Boolean PosChamfPln = DirPlnCyl.Dot(DirSPln) > 0;
442 toreverse = !toreverse;
443 // It is checked if the orientation of the Chamfer is the same as of the plane
445 {Data->ChangeOrientation() = TopAbs::Reverse(Ofpl);}
447 {Data->ChangeOrientation() = Ofpl;}
449 TopAbs_Orientation trans = TopAbs_FORWARD;
450 if ((!plandab && toreverse) || (plandab && !toreverse))
451 {trans=TopAbs_REVERSED;}
453 //trans permits to determine the "material" side on S1(2) limited by L3d
455 {Data->ChangeInterferenceOnS1().
456 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);}
458 {Data->ChangeInterferenceOnS2().
459 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);}
461 //------------edge cylinder-Chamfer
462 gp_Pnt2d PCyl2d(UOnCyl,VOnCyl);
463 gp_Dir2d VCyl2d=gp::DY2d();
464 if ( XDir.Dot(AxCyl.Direction())<0 )
466 gp_Lin2d Lin2dCyl(PCyl2d,VCyl2d);
468 POnCyl = ElSLib::Value(UOnCyl,VOnCyl,Cyl);
469 C3d = gp_Lin(POnCyl,XDir);
471 ElSLib::PlaneParameters(AxCh,POnCyl,U,VOnChamfer);
472 LOnChamfer = gp_Lin2d(gp_Pnt2d(U,VOnChamfer),gp::DX2d());
474 L3d = new Geom_Line (C3d);
475 LFac = new Geom2d_Line(Lin2dCyl);
476 LFil = new Geom2d_Line(LOnChamfer);
479 ElSLib::CylinderD1(UOnCyl,VOnCyl,AxCyl,Cyl.Radius(),POnCyl,deru,derv);
480 gp_Dir NorCyl(deru.Crossed(derv));
482 toreverse = ( NorFil.Dot(NorCyl) <= 0. );
484 gp_Dir DirSCyl(gp_Vec(OrSpine, POnCyl));
485 Standard_Boolean PosChamfCyl = DirPlnCyl.Dot(DirSCyl) < 0;
489 toreverse = !toreverse;
491 trans = TopAbs_REVERSED;
492 if ((!plandab && toreverse) || (plandab && !toreverse))
493 {trans=TopAbs_FORWARD;}
496 Data->ChangeInterferenceOnS2().
497 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);
499 Data->ChangeInterferenceOnS1().
500 SetInterference(ChFiKPart_IndexCurveInDS(L3d,DStr),trans,LFac,LFil);
501 return Standard_True;