0023948: Wrong intersection between a surface of revolution and a plane.
[occt.git] / src / UnitsMethods / UnitsMethods.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <UnitsMethods.ixx>
15
16 #include <Geom_Plane.hxx>
17 #include <Geom_Surface.hxx>
18 #include <Geom_ConicalSurface.hxx>
19 #include <Geom_CylindricalSurface.hxx>
20 #include <Geom_SphericalSurface.hxx>
21 #include <Geom_ToroidalSurface.hxx>
22 #include <Geom_SurfaceOfRevolution.hxx>
23 #include <Geom2dConvert.hxx>
24 #include <Geom2d_BSplineCurve.hxx>
25 #include <Geom2d_Circle.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_Ellipse.hxx>
28 #include <Geom2d_Hyperbola.hxx>
29 #include <Geom2d_Line.hxx>
30 #include <Geom2d_Parabola.hxx>
31 #include <gp.hxx>
32 #include <gp_GTrsf2d.hxx>
33 #include <gp_Trsf2d.hxx>
34 #include <gp_Pnt2d.hxx>
35 #include <gp_Dir2d.hxx>
36
37 static Standard_Real theLengthFactor     = 1.;
38 static Standard_Real thePlaneAngleFactor = 1.;
39 static Standard_Real theSolidAngleFactor = 1.;
40 static Standard_Boolean set3d            = Standard_True;
41
42 static Standard_Real FactRD = 1.;
43 static Standard_Real FactDR = 1.;
44
45 static Standard_Real theCasCadeLengthUnit = 1.; // abv 28 Feb 00
46
47 // ============================================================================
48 // Method :
49 // Purpose:
50 // ============================================================================
51
52 void UnitsMethods::InitializeFactors(const Standard_Real LengthFactor, const Standard_Real PlaneAngleFactor, const Standard_Real SolidAngleFactor)
53 {
54   theLengthFactor     = LengthFactor;
55   thePlaneAngleFactor = PlaneAngleFactor;
56   theSolidAngleFactor = SolidAngleFactor;
57   FactRD = 1./PlaneAngleFactor; 
58   FactDR = PlaneAngleFactor;
59 }
60
61 // ============================================================================
62 // Method :
63 // Purpose:
64 // ============================================================================
65
66 Standard_Real UnitsMethods ::LengthFactor()
67 {
68   return theLengthFactor;
69 }
70
71 // ============================================================================
72 // Method :
73 // Purpose:
74 // ============================================================================
75
76 Standard_Real UnitsMethods::PlaneAngleFactor()
77 {
78   return thePlaneAngleFactor;
79 }
80
81 // ============================================================================
82 // Method :
83 // Purpose:
84 // ============================================================================
85
86 Standard_Real UnitsMethods::SolidAngleFactor()
87 {
88   return theSolidAngleFactor;
89 }
90
91 // ============================================================================
92 // Method :
93 // Purpose:
94 // ============================================================================
95
96 void UnitsMethods::Set3dConversion(const Standard_Boolean B)
97 {
98   set3d = B;
99 }
100
101 // ============================================================================
102 // Method :
103 // Purpose:
104 // ============================================================================
105
106 Standard_Boolean UnitsMethods::Convert3d()
107 {
108   return set3d;
109 }
110
111
112 // ============================================================================
113 // Method :
114 // Purpose:
115 // ============================================================================
116
117 Handle(Geom2d_Curve) UnitsMethods::RadianToDegree
118                                    (const Handle(Geom2d_Curve)  & theCurve2d,
119                                     const Handle(Geom_Surface)  & theSurf)
120 {
121   Handle(Geom2d_Curve) aCurve2d = Handle(Geom2d_Curve)::DownCast(theCurve2d->Copy());
122   Standard_Real uFact = 1.;
123   Standard_Real vFact = 1.; 
124   Standard_Real LengthFact  = 1. / UnitsMethods::LengthFactor();
125   Standard_Real AngleFact  = FactRD;    // 180./PI;  pilotable
126   
127   gp_Pnt2d    Pt1;
128   gp_XY       pXY;
129   gp_GTrsf2d  tMatu , tMatv;
130   
131   //  theSurf is a CylindricalSurface or a ConicalSurface or
132   //             a ToroidalSurface or a SphericalSurface or
133   //             a SurfaceOfRevolution
134   if (theSurf->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
135       theSurf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
136     uFact = vFact = AngleFact;
137   }
138   else if (theSurf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
139     uFact = AngleFact;
140     vFact = LengthFact;
141   }
142   else if ( theSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
143     uFact = AngleFact;
144   }
145   else if (theSurf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
146     Handle(Geom_ConicalSurface) conicS = 
147       Handle(Geom_ConicalSurface)::DownCast(theSurf);
148     Standard_Real semAng = conicS->SemiAngle();
149     uFact = AngleFact;
150     vFact = LengthFact * Cos(semAng);
151   }
152   else if (theSurf->IsKind(STANDARD_TYPE(Geom_Plane))) {
153     uFact = vFact = LengthFact;
154     if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
155         aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
156       gp_Trsf2d aT;
157       aT.SetScale (gp::Origin2d(), LengthFact);
158       aCurve2d->Transform (aT);
159       return aCurve2d;
160     }
161   }
162   else {
163 //  debug
164 //    cout <<"UnitsMethods: SurfType = "<< aSurface->DynamicType();
165     return aCurve2d;
166   }
167
168   if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Line))) {
169     Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(aCurve2d);
170
171     gp_Pnt2d myLoc = aLine2d->Location();
172     gp_Dir2d myDir = aLine2d->Direction();
173
174     gp_Pnt2d myNewLoc;
175     myNewLoc.SetCoord(myLoc.X()*uFact, myLoc.Y()*vFact);
176
177     gp_Dir2d myNewDir;
178     myNewDir.SetCoord(myDir.X()*uFact, myDir.Y()*vFact);
179
180     Handle(Geom2d_Line) myNewLine2d = Handle(Geom2d_Line)::DownCast(aLine2d->Copy());
181     myNewLine2d->SetLocation(myNewLoc);
182     myNewLine2d->SetDirection(myNewDir);
183
184     return myNewLine2d;
185   }
186   else if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Conic))) {
187     if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
188         aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
189       Handle(Geom2d_BSplineCurve) aBSpline2d = 
190         Geom2dConvert::CurveToBSplineCurve(aCurve2d);
191       aCurve2d = aBSpline2d;
192     } 
193     else if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
194 #ifdef DEBUG
195       cout << "PCURVE of Parabola type in U or V Periodic Surface" << endl;
196       cout << "Parameters Not transformed to Degree" << endl;
197 #endif
198     }
199     else if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) {
200 #ifdef DEBUG
201       cout << "PCURVE of Hyperbola type in U or V Periodic Surface" << endl;
202       cout << "Parameters Not transformed to Degree" << endl;
203 #endif
204     }
205     
206   }
207   
208   // Compute affinity
209   tMatu.SetAffinity(gp::OY2d(), uFact);
210   tMatv.SetAffinity(gp::OX2d(), vFact);
211   
212   if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve))) {
213     if (aCurve2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
214       Handle(Geom2d_BSplineCurve) aBSpline2d = 
215         Handle(Geom2d_BSplineCurve)::DownCast(aCurve2d);
216       Handle(Geom2d_BSplineCurve) myNewBSpline2d = 
217         Handle(Geom2d_BSplineCurve)::DownCast(aBSpline2d->Copy());
218       Standard_Integer nbPol = aBSpline2d->NbPoles();
219       for (Standard_Integer i = 1; i<=nbPol ; i++) {
220         pXY = aBSpline2d->Pole(i).XY();
221         tMatu.Transforms(pXY);
222         tMatv.Transforms(pXY);
223         Pt1.SetXY(pXY);
224         myNewBSpline2d->SetPole(i, Pt1);
225       }
226       return myNewBSpline2d;
227     }
228     else {
229 #ifdef DEBUG
230       cout << "PCURVE of Other Types of Bounded Curve in U or V Periodic Surface" << endl;
231       cout << "Parameters Not transformed to Degree" << endl;
232 #endif
233     }
234   }
235   return aCurve2d;
236 }
237
238 //=============================================================================
239 // DegreeToRadian: 1. Change definition of the pcurves according to Length
240 //                     Factor                  
241 //                  2. STEP cylinder, torus, cone and sphere are parametrized
242 //                     from 0 to 360 degree
243 //                     Then pcurves parameter have to be transformed 
244 //                     from DEGREE to RADIAN
245 //=============================================================================
246
247 Handle(Geom2d_Curve) UnitsMethods::DegreeToRadian
248                              (const Handle(Geom2d_Curve) & thePcurve,
249                               const Handle(Geom_Surface) & aSurface)
250 {
251   Handle(Geom2d_Curve)  aPcurve = Handle(Geom2d_Curve)::DownCast(thePcurve->Copy());
252   Standard_Real uFact       = 1.;
253   Standard_Real vFact       = 1.; 
254   Standard_Real LengthFact  = UnitsMethods::LengthFactor();
255   Standard_Real AngleFact   = FactDR;  // PI/180.;  pilotable
256
257   gp_Pnt2d    Pt1;
258   gp_XY       pXY;
259   gp_GTrsf2d  tMatu , tMatv;
260
261   // What to change ??
262
263   if (aSurface->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) ||
264       aSurface->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) {
265     uFact = vFact = AngleFact;
266   }
267   else if (aSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
268     uFact = AngleFact;
269     vFact = LengthFact;
270   }
271   else if ( aSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
272     uFact = AngleFact;
273   }
274   else if (aSurface->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) {
275     Handle(Geom_ConicalSurface) conicS = 
276       Handle(Geom_ConicalSurface)::DownCast(aSurface);
277     Standard_Real semAng = conicS->SemiAngle();
278     uFact = AngleFact;
279     vFact = LengthFact / Cos(semAng);
280   }
281   else if (aSurface->IsKind(STANDARD_TYPE(Geom_Plane))) {
282     uFact = vFact = LengthFact;
283     if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_Circle)) ||
284         aPcurve->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
285       gp_Trsf2d aT;
286       aT.SetScale (gp::Origin2d(), LengthFact);
287       aPcurve->Transform (aT);
288       return aPcurve;
289     }
290   }
291   else {
292 //  debug
293 //    cout <<"UnitsMethods: SurfType = "<< aSurface->DynamicType();
294     return aPcurve;
295   }
296
297   if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_Conic))) {
298     if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_Circle)) || 
299         aPcurve->IsKind(STANDARD_TYPE(Geom2d_Ellipse))) {
300       Handle(Geom2d_BSplineCurve) aBSpline2d = 
301         Geom2dConvert::CurveToBSplineCurve(aPcurve);
302       aPcurve = aBSpline2d;
303     }
304     else if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_Parabola))) {
305 #ifdef DEBUG
306       cout << "PCURVE of Parabola type" << endl;
307       cout << "Parameters Not Yet transformed according to LenghtUnit" << endl;
308 #endif
309       return aPcurve;
310     }
311     else if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_Hyperbola))) {
312 #ifdef DEBUG
313       cout << "PCURVE of Hyperbola type" << endl;
314       cout << "Parameters Not Yet transformed according to LenghtUnit" << endl;
315 #endif
316       return aPcurve;
317     }
318   }
319
320   // Compute affinity
321
322   tMatu.SetAffinity(gp::OY2d(), uFact);
323   tMatv.SetAffinity(gp::OX2d(), vFact);
324
325   if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
326     Handle(Geom2d_Line) aLine2d = Handle(Geom2d_Line)::DownCast(aPcurve);
327
328     gp_Pnt2d myLoc = aLine2d->Location();
329     gp_Dir2d myDir = aLine2d->Direction();
330
331     gp_Pnt2d myNewLoc;
332     myNewLoc.SetCoord(myLoc.X()*uFact, myLoc.Y()*vFact);
333
334     gp_Dir2d myNewDir;
335     myNewDir.SetCoord(myDir.X()*uFact, myDir.Y()*vFact);
336
337     aLine2d->SetLocation(myNewLoc);
338     aLine2d->SetDirection(myNewDir);
339
340     aPcurve = aLine2d;
341   }
342   else if (aPcurve->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
343     Handle(Geom2d_BSplineCurve) aBSpline2d = 
344       Handle(Geom2d_BSplineCurve)::DownCast(aPcurve);
345
346 // transform the Poles of the BSplineCurve according to AngleFact and LengthFact
347
348     Standard_Integer nbPol = aBSpline2d->NbPoles();
349     for (Standard_Integer i = 1; i<=nbPol ; i++) {
350       pXY = aBSpline2d->Pole(i).XY();
351       tMatu.Transforms(pXY);
352       tMatv.Transforms(pXY);
353       Pt1.SetXY(pXY);
354       aBSpline2d->SetPole(i, Pt1);
355     }
356     aPcurve = aBSpline2d;
357   }
358   else {
359 #ifdef DEBUG
360     cout << "DegreeToRadian : Type " << aPcurve->DynamicType();
361     cout << " not yet implemented" << endl;
362 #endif
363   }
364   return aPcurve;
365 }
366
367 // ============================================================================
368 // Method :
369 // Purpose:
370 // ============================================================================
371
372 Handle(Geom2d_Curve) UnitsMethods::MirrorPCurve
373 (const Handle(Geom2d_Curve) & C2d) 
374 {
375   Handle(Geom2d_Curve) theMirrored = 
376     Handle(Geom2d_Curve)::DownCast(C2d->Copy());
377   
378   gp_Trsf2d T;
379   gp_Pnt2d  Loc(0.,0.);
380   gp_Dir2d  Dir(1.,0.);
381   gp_Ax2d   ax2(Loc, Dir);
382   T.SetMirror(ax2);
383   theMirrored->Transform(T);
384   return theMirrored;
385 }
386
387 //=======================================================================
388 //function : GetCasCadeLengthUnit
389 //purpose  : 
390 //=======================================================================
391
392 Standard_Real UnitsMethods::GetCasCadeLengthUnit () 
393 {
394   return theCasCadeLengthUnit;
395 }
396
397 //=======================================================================
398 //function : SetCasCadeLengthUnit
399 //purpose  : 
400 //=======================================================================
401
402 void UnitsMethods::SetCasCadeLengthUnit (const Standard_Integer unit) 
403 {
404   theCasCadeLengthUnit = UnitsMethods::GetLengthFactorValue ( unit );
405 }
406
407 //=======================================================================
408 //function : GetLengthFactorValue
409 //purpose  : 
410 //=======================================================================
411
412 Standard_Real UnitsMethods::GetLengthFactorValue (const Standard_Integer par) 
413 {
414   switch ( par ) {
415   case  1 : return 25.4;
416   case  2 : return 1.;
417   
418   case  4 : return 304.8;
419   case  5 : return 1609270.;
420   case  6 : return 1000.;
421   case  7 : return 1000000.;
422   case  8 : return 0.0254;
423   case  9 : return 0.001;
424   case 10 : return 10.;
425   case 11 : return 0.0000254;
426   default : return 1.;
427   }
428 }
429