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