0031939: Coding - correction of spelling errors in comments
[occt.git] / src / GeomFill / GeomFill_DiscreteTrihedron.cxx
1 // Created on: 2013-02-05
2 // Created by: Julia GERASIMOVA
3 // Copyright (c) 2001-2013 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <Adaptor3d_HCurve.hxx>
18 #include <GeomAbs_CurveType.hxx>
19 #include <GeomFill_DiscreteTrihedron.hxx>
20 #include <GeomFill_Frenet.hxx>
21 #include <GeomFill_HSequenceOfAx2.hxx>
22 #include <GeomFill_TrihedronLaw.hxx>
23 #include <gp_Vec.hxx>
24 #include <Standard_ConstructionError.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <Standard_Type.hxx>
27 #include <TColStd_Array1OfReal.hxx>
28 #include <TColStd_HSequenceOfReal.hxx>
29
30 IMPLEMENT_STANDARD_RTTIEXT(GeomFill_DiscreteTrihedron,GeomFill_TrihedronLaw)
31
32 static const Standard_Real TolConf = Precision::Confusion();
33
34 //=======================================================================
35 //function : GeomFill_DiscreteTrihedron
36 //purpose  : Constructor
37 //=======================================================================
38
39 GeomFill_DiscreteTrihedron::GeomFill_DiscreteTrihedron() :
40     myUseFrenet(Standard_False)
41 {
42   myFrenet = new GeomFill_Frenet();
43   myKnots      = new TColStd_HSequenceOfReal();
44   myTrihedrons = new GeomFill_HSequenceOfAx2();
45 }
46
47 //=======================================================================
48 //function : Copy
49 //purpose  : 
50 //=======================================================================
51
52 Handle(GeomFill_TrihedronLaw) GeomFill_DiscreteTrihedron::Copy() const
53 {
54   Handle(GeomFill_DiscreteTrihedron) copy = new (GeomFill_DiscreteTrihedron)();
55   if (!myCurve.IsNull()) copy->SetCurve(myCurve);
56   return copy;
57 }
58
59 //=======================================================================
60 //function : SetCurve
61 //purpose  : 
62 //=======================================================================
63
64 void GeomFill_DiscreteTrihedron::SetCurve(const Handle(Adaptor3d_HCurve)& C) 
65 {
66   GeomFill_TrihedronLaw::SetCurve(C);
67   if (! C.IsNull()) {
68     GeomAbs_CurveType type;
69     type = C->GetType();
70     switch  (type) {
71     case GeomAbs_Circle:
72     case GeomAbs_Ellipse:
73     case GeomAbs_Hyperbola:
74     case GeomAbs_Parabola:
75     case GeomAbs_Line:
76       {
77         // No probleme
78         myUseFrenet = Standard_True;
79         myFrenet->SetCurve(C);
80         break;
81       }
82     default :
83       {
84         myUseFrenet = Standard_False;
85         // We have to fill <myKnots> and <myTrihedrons>
86         Init();
87         break;
88       }
89     }
90   }
91 }
92
93 //=======================================================================
94 //function : Init
95 //purpose  : 
96 //=======================================================================
97
98 void GeomFill_DiscreteTrihedron::Init()
99 {
100   Standard_Integer NbIntervals = myTrimmed->NbIntervals(GeomAbs_CN);
101   TColStd_Array1OfReal Knots(1, NbIntervals+1);
102   myTrimmed->Intervals(Knots, GeomAbs_CN);
103
104   //Standard_Real Tol = Precision::Confusion();
105   Standard_Integer NbSamples = 10;
106
107   Standard_Integer i, j;
108   for (i = 1; i <= NbIntervals; i++)
109   {
110     Standard_Real delta = (Knots(i+1) - Knots(i))/NbSamples;
111     for (j = 0; j < NbSamples; j++)
112     {
113       Standard_Real Param = Knots(i) + j*delta;
114       myKnots->Append(Param);
115     }
116   }
117   myKnots->Append(Knots(NbIntervals+1));
118   
119   
120   gp_Pnt Origin(0.,0.,0.), Pnt, SubPnt;
121   gp_Vec Tangent;
122   gp_Dir TangDir;
123   Standard_Real norm;
124   for (i = 1; i <= myKnots->Length(); i++)
125   {
126     Standard_Real Param = myKnots->Value(i);
127     myTrimmed->D1(Param, Pnt, Tangent);
128     norm = Tangent.Magnitude();
129     if (norm < TolConf)
130     {
131       Standard_Real subdelta = (myKnots->Value(i+1) - myKnots->Value(i))/NbSamples;
132       if (subdelta < Precision::PConfusion())
133         subdelta = myKnots->Value(i+1) - myKnots->Value(i);
134       SubPnt = myTrimmed->Value(Param + subdelta);
135       Tangent.SetXYZ(SubPnt.XYZ() - Pnt.XYZ());
136     }
137     //Tangent.Normalize();
138     TangDir = Tangent; //normalize;
139     Tangent = TangDir;
140     if (i == 1) //first point
141     {
142       gp_Ax2 FirstAxis(Origin, TangDir);
143       myTrihedrons->Append(FirstAxis);
144     }
145     else
146     {
147       gp_Ax2 LastAxis = myTrihedrons->Value(myTrihedrons->Length());
148       gp_Vec LastTangent = LastAxis.Direction();
149       gp_Vec AxisOfRotation = LastTangent ^ Tangent;
150       if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal or opposite
151       {
152         Standard_Real ScalarProduct = LastTangent * Tangent;
153         if (ScalarProduct > 0.) //tangents are equal
154           myTrihedrons->Append(LastAxis);
155         else //tangents are opposite
156         {
157           Standard_Real NewParam = (myKnots->Value(i-1) + myKnots->Value(i))/2.;
158           if (NewParam - myKnots->Value(i-1) < gp::Resolution())
159             throw Standard_ConstructionError("GeomFill_DiscreteTrihedron : impassable singularities on path curve");
160           myKnots->InsertBefore(i, NewParam);
161           i--;
162         }
163       }
164       else //good value of angle
165       {
166         Standard_Real theAngle = LastTangent.AngleWithRef(Tangent, AxisOfRotation);
167         gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
168         gp_Ax2 NewAxis = LastAxis.Rotated(theAxisOfRotation, theAngle);
169         NewAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
170         myTrihedrons->Append(NewAxis);
171       }
172     }
173   }
174 }
175
176 //=======================================================================
177 //function : D0
178 //purpose  : 
179 //=======================================================================
180
181 Standard_Boolean GeomFill_DiscreteTrihedron::D0(const Standard_Real Param,
182                                                 gp_Vec& Tangent,
183                                                 gp_Vec& Normal,
184                                                 gp_Vec& BiNormal)
185 {
186   if (myUseFrenet)
187   {
188     myFrenet->D0(Param, Tangent, Normal, BiNormal);
189   }
190   else
191   {
192     //Locate <Param> in the sequence <myKnots>
193     Standard_Integer Index = -1;
194     Standard_Real TolPar = Precision::PConfusion();
195     //Standard_Real TolConf = Precision::Confusion();
196     Standard_Integer NbSamples = 10;
197     gp_Pnt Origin(0.,0.,0.);
198     
199     Standard_Integer i;
200     //gp_Ax2 PrevAxis;
201     //Standard_Real PrevParam;
202
203     Standard_Integer I1, I2;
204     I1 = 1;
205     I2 = myKnots->Length();
206     for (;;)
207     {
208       i = (I1 + I2)/2;
209       if (Param <= myKnots->Value(i))
210         I2 = i;
211       else
212         I1 = i;
213       if (I2 - I1 <= 1)
214         break;
215     }
216     Index = I1;
217     if (Abs(Param - myKnots->Value(I2)) < TolPar)
218       Index = I2;
219
220     Standard_Real PrevParam = myKnots->Value(Index);
221     gp_Ax2        PrevAxis  = myTrihedrons->Value(Index);
222     gp_Ax2 theAxis;
223     if (Abs(Param - PrevParam) < TolPar)
224       theAxis = PrevAxis;
225     else //<Param> is between knots
226     {
227       myTrimmed->D1(Param, myPoint, Tangent);
228       Standard_Real norm = Tangent.Magnitude();
229       if (norm < TolConf)
230       {
231         Standard_Real subdelta = (myKnots->Value(Index+1) - Param)/NbSamples;
232         if (subdelta < Precision::PConfusion())
233           subdelta = myKnots->Value(Index+1) - Param;
234         gp_Pnt SubPnt = myTrimmed->Value(Param + subdelta);
235         Tangent.SetXYZ(SubPnt.XYZ() - myPoint.XYZ());
236       }
237       //Tangent.Normalize();
238       gp_Dir TangDir(Tangent); //normalize;
239       Tangent = TangDir;
240       gp_Vec PrevTangent = PrevAxis.Direction();
241       gp_Vec AxisOfRotation = PrevTangent ^ Tangent;
242       if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal
243       {
244         //we assume that tangents can not be opposite
245         theAxis = PrevAxis;
246       }
247       else //good value of angle
248       {
249         Standard_Real theAngle = PrevTangent.AngleWithRef(Tangent, AxisOfRotation);
250         gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation);
251         theAxis = PrevAxis.Rotated(theAxisOfRotation, theAngle);
252       }
253       theAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error
254     } //end of else (Param is between knots)
255
256     Tangent  = theAxis.Direction();
257     Normal   = theAxis.XDirection();
258     BiNormal = theAxis.YDirection();
259   }
260   return Standard_True;
261 }
262
263 //=======================================================================
264 //function : D1
265 //purpose  : 
266 //=======================================================================
267
268 Standard_Boolean GeomFill_DiscreteTrihedron::D1(const Standard_Real Param,
269                                                 gp_Vec& Tangent,
270                                                 gp_Vec& DTangent,
271                                                 gp_Vec& Normal,
272                                                 gp_Vec& DNormal,
273                                                 gp_Vec& BiNormal,
274                                                 gp_Vec& DBiNormal) 
275 {
276   if (myUseFrenet)
277   {
278     myFrenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal);
279   }
280   else
281   {
282     D0(Param, Tangent, Normal, BiNormal);
283
284     DTangent.SetCoord(0.,0.,0.);
285     DNormal.SetCoord(0.,0.,0.);
286     DBiNormal.SetCoord(0.,0.,0.);
287   }
288   return Standard_True;
289 }
290
291 //=======================================================================
292 //function : D2
293 //purpose  : 
294 //=======================================================================
295
296 Standard_Boolean GeomFill_DiscreteTrihedron::D2(const Standard_Real Param,
297                                                 gp_Vec& Tangent,
298                                                 gp_Vec& DTangent,
299                                                 gp_Vec& D2Tangent,
300                                                 gp_Vec& Normal,
301                                                 gp_Vec& DNormal,
302                                                 gp_Vec& D2Normal,
303                                                 gp_Vec& BiNormal,
304                                                 gp_Vec& DBiNormal,
305                                                 gp_Vec& D2BiNormal) 
306 {
307   if (myUseFrenet)
308   {
309     myFrenet->D2(Param, Tangent, DTangent, D2Tangent,
310                  Normal, DNormal, D2Normal,
311                  BiNormal, DBiNormal, D2BiNormal);
312   }
313   else
314   {
315     D0(Param, Tangent, Normal, BiNormal);
316     
317     DTangent.SetCoord(0.,0.,0.);
318     DNormal.SetCoord(0.,0.,0.);
319     DBiNormal.SetCoord(0.,0.,0.);
320     D2Tangent.SetCoord(0.,0.,0.);
321     D2Normal.SetCoord(0.,0.,0.);
322     D2BiNormal.SetCoord(0.,0.,0.);
323   }
324   return Standard_True;
325 }
326
327 //=======================================================================
328 //function : NbIntervals
329 //purpose  : 
330 //=======================================================================
331
332 Standard_Integer GeomFill_DiscreteTrihedron::NbIntervals(const GeomAbs_Shape) const
333 {
334   return (myTrimmed->NbIntervals(GeomAbs_CN));
335 }
336
337 //=======================================================================
338 //function : Intervals
339 //purpose  : 
340 //=======================================================================
341
342 void GeomFill_DiscreteTrihedron::Intervals(TColStd_Array1OfReal& T,
343                                            const GeomAbs_Shape) const
344 {
345   myTrimmed->Intervals(T, GeomAbs_CN);
346 }
347
348  void GeomFill_DiscreteTrihedron::GetAverageLaw(gp_Vec& ATangent,
349                                      gp_Vec& ANormal,
350                                      gp_Vec& ABiNormal) 
351 {
352   Standard_Integer Num = 20; //order of digitalization
353   gp_Vec T, N, BN;
354   ATangent = gp_Vec(0, 0, 0);
355   ANormal = gp_Vec(0, 0, 0);
356   ABiNormal = gp_Vec(0, 0, 0);
357   Standard_Real Step = (myTrimmed->LastParameter() - 
358                         myTrimmed->FirstParameter()) / Num;
359   Standard_Real Param;
360   for (Standard_Integer i = 0; i <= Num; i++) {
361     Param = myTrimmed->FirstParameter() + i*Step;
362     if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter();
363     D0(Param, T, N, BN);
364     ATangent += T;
365     ANormal += N;
366     ABiNormal += BN;
367   }
368   ATangent /= Num + 1;
369   ANormal /= Num + 1;
370
371   ATangent.Normalize();
372   ABiNormal = ATangent.Crossed(ANormal).Normalized();
373   ANormal = ABiNormal.Crossed(ATangent);
374 }
375
376 //=======================================================================
377 //function : IsConstant
378 //purpose  : 
379 //=======================================================================
380
381  Standard_Boolean GeomFill_DiscreteTrihedron::IsConstant() const
382 {
383   return (myCurve->GetType() == GeomAbs_Line);
384 }
385
386 //=======================================================================
387 //function : IsOnlyBy3dCurve
388 //purpose  : 
389 //=======================================================================
390
391  Standard_Boolean GeomFill_DiscreteTrihedron::IsOnlyBy3dCurve() const
392 {
393   return Standard_True;
394 }