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