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