0026202: Wrong result of chamfer on cylindrical surface: wrong value of chord
[occt.git] / src / ChFiKPart / ChFiKPart_ComputeData_ChPlnCyl.cxx
CommitLineData
b311480e 1// Created on: 1995-05-19
2// Created by: Flore Lantheaume
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 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
69Standard_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 ) {
0797d9d3 134#ifdef OCCT_DEBUG
81bba717 135 cout<<"the chamfer can't pass"<<endl;
63c629aa 136#endif
7fd59977 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;
c6541a0c 270 if(Abs(lu - fu - 2*M_PI) < tol) careaboutsens = 1;
7fd59977 271 if(u >= fu - tol && u < fu) u = fu;
272 if(u <= lu + tol && u > lu) u = lu;
c6541a0c 273 if(u < fu || u > lu) u = ChFiKPart_InPeriod(u,fu,fu + 2*M_PI,tol);
7fd59977 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
7fd59977 311//=======================================================================
312//function : MakeChamfer
81bba717 313//purpose : case cylinder/plane or plane/cylinder.
7fd59977 314//=======================================================================
315
316Standard_Boolean ChFiKPart_MakeChamfer(TopOpeBRepDS_DataStructure& DStr,
317 const Handle(ChFiDS_SurfData)& Data,
318 const gp_Pln& Pln,
319 const gp_Cylinder& Cyl,
35e08fe8 320 const Standard_Real /*fu*/,
321 const Standard_Real /*lu*/,
7fd59977 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{
81bba717 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
7fd59977 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();
81bba717 354 // OrCyl is the point on axis of cylinder in the plane normal to the
355 // axis containing OrSpine
12945d77 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 );
7fd59977 361
81bba717 362 //construction of POnPln
7fd59977 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
81bba717 377 //construction of POnCyl
7fd59977 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
81bba717 399 //construction of chamfer
7fd59977 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
81bba717 406 //construction of YDir to go to face1 from face2.
7fd59977 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
81bba717 416 // FaceInterferences are loaded with pcurves and curves 3d.
417 //----------- edge plane-Chamfer
7fd59977 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;
81bba717 443 // It is checked if the orientation of the Chamfer is the same as of the plane
7fd59977 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
81bba717 453 //trans permits to determine the "material" side on S1(2) limited by L3d
7fd59977 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
81bba717 461 //------------edge cylinder-Chamfer
7fd59977 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