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