e55208b06da4ced6030089086070a210bf8763ea
[occt.git] / src / VrmlConverter / VrmlConverter_DeflectionCurve.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 #include <VrmlConverter_DeflectionCurve.ixx>
15 #include <gp_Pnt.hxx>
16 #include <gp_Circ.hxx>
17 #include <gp_Dir.hxx>
18 #include <gp_Vec.hxx>
19 #include <Bnd_Box.hxx>
20 #include <Precision.hxx>
21 #include <TColgp_HArray1OfVec.hxx>
22 #include <TColStd_HArray1OfInteger.hxx>
23 #include <Vrml_Material.hxx>
24 #include <VrmlConverter_LineAspect.hxx>
25 #include <Vrml_Separator.hxx>
26 #include <Vrml_Coordinate3.hxx>
27 #include <Vrml_IndexedLineSet.hxx>
28 #include <Precision.hxx>
29 #include <GCPnts_QuasiUniformDeflection.hxx>
30 #include <BndLib_Add3dCurve.hxx>
31
32 //==================================================================
33 // function: FindLimits
34 // purpose:
35 //==================================================================
36 static void FindLimits(const Adaptor3d_Curve& aCurve,
37                        const Standard_Real  aLimit,
38                        Standard_Real&       First,
39                        Standard_Real&       Last)
40 {
41   First = aCurve.FirstParameter();
42   Last  = aCurve.LastParameter();
43   Standard_Boolean firstInf = Precision::IsNegativeInfinite(First);
44   Standard_Boolean lastInf  = Precision::IsPositiveInfinite(Last);
45
46   if (firstInf || lastInf) {
47     gp_Pnt P1,P2;
48     Standard_Real delta = 1;
49     if (firstInf && lastInf) {
50       do {
51         delta *= 2;
52         First = - delta;
53         Last  =   delta;
54         aCurve.D0(First,P1);
55         aCurve.D0(Last,P2);
56       } while (P1.Distance(P2) < aLimit);
57     }
58     else if (firstInf) {
59       aCurve.D0(Last,P2);
60       do {
61         delta *= 2;
62         First = Last - delta;
63         aCurve.D0(First,P1);
64       } while (P1.Distance(P2) < aLimit);
65     }
66     else if (lastInf) {
67       aCurve.D0(First,P1);
68       do {
69         delta *= 2;
70         Last = First + delta;
71         aCurve.D0(Last,P2);
72       } while (P1.Distance(P2) < aLimit);
73     }
74   }    
75 }
76
77
78 //==================================================================
79 // function: DrawCurve
80 // purpose:
81 //==================================================================
82 static void DrawCurve (Adaptor3d_Curve&          aCurve,
83                        const Standard_Real           TheDeflection,
84                        const Standard_Real           U1,
85                        const Standard_Real           U2,
86                        const Handle(VrmlConverter_Drawer)& aDrawer, // for passsing of LineAspect
87                        Standard_OStream&             anOStream) 
88 {
89   Standard_Integer i;
90   Standard_Boolean key = Standard_False;
91   Handle(TColgp_HArray1OfVec) HAV1;
92   Handle(TColStd_HArray1OfInteger) HAI1;
93
94   switch (aCurve.GetType()) {
95   case GeomAbs_Line:
96     {
97      gp_Vec V;
98      key = Standard_True;
99      HAV1 = new TColgp_HArray1OfVec(1, 2);
100      HAI1 = new TColStd_HArray1OfInteger(1,3);
101
102 // array of coordinates of line 
103      gp_Pnt p = aCurve.Value(U1);
104      V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
105      HAV1->SetValue(1,V);
106
107      p = aCurve.Value(U2);
108      V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
109      HAV1->SetValue(2,V);
110
111 // array of indexes of line
112      HAI1->SetValue(1,0);       
113      HAI1->SetValue(2,1);
114      HAI1->SetValue(3,-1);
115
116     }
117     break;
118   case GeomAbs_Circle:
119     {
120       Standard_Real Radius = aCurve.Circle().Radius();
121      if (!Precision::IsInfinite(Radius)) {
122        Standard_Real DU = Sqrt(8.0 * TheDeflection / Radius);
123        Standard_Integer N = Standard_Integer(Abs( U2 - U1) / DU);
124
125        if ( N > 0) {
126
127          gp_Vec V;
128          key = Standard_True;
129          HAV1 = new TColgp_HArray1OfVec(1, N+1);
130          HAI1 = new TColStd_HArray1OfInteger(1,N+2);
131
132          DU = (U2-U1) / N;
133          Standard_Real U;
134          gp_Pnt p;
135
136          for (Standard_Integer Index = 1; Index <= N+1; Index++) {
137            U = U1 + (Index - 1) * DU;
138            p = aCurve.Value(U);
139
140            V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
141            HAV1->SetValue(Index,V);
142            HAI1->SetValue(Index,Index-1);       
143
144          }
145 /*
146          if( HAV1->Value(1).IsEqual( HAV1->Value(N+1),Precision::Confusion(), Precision::Angular() ) )
147            {
148              HAI1->SetValue(N+1, 0);
149            }
150 */       
151          HAI1->SetValue(HAI1->Upper(),-1);
152        }
153      }
154     }
155     break;
156     
157   default:
158     {
159        GCPnts_QuasiUniformDeflection Algo(aCurve,TheDeflection,U1,U2);
160        if(Algo.IsDone()){
161
162          Standard_Integer NumberOfPoints = Algo.NbPoints();
163          if (NumberOfPoints > 0) {
164           
165           gp_Vec V;
166           key = Standard_True;
167           HAV1 = new TColgp_HArray1OfVec(1, NumberOfPoints);
168           HAI1 = new TColStd_HArray1OfInteger(1,NumberOfPoints+1);
169           gp_Pnt p;
170           
171           for (i=1;i<=NumberOfPoints;i++) { 
172             p = Algo.Value(i);
173             V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
174             HAV1->SetValue(i,V);
175           }
176
177           for (i=HAI1->Lower(); i < HAI1->Upper(); i++)
178             {
179               HAI1->SetValue(i,i-1);    
180             }
181           HAI1->SetValue(HAI1->Upper(),-1);
182           
183         }
184       }
185       //else
186       //cannot draw with respect to a maximal chordial deviation
187     }
188   }
189
190 //cout  << " Array HAI1 - coordIndex " << endl;  
191 //     
192 //for ( i=HAI1->Lower(); i <= HAI1->Upper(); i++ )
193 //  {
194 //    cout << HAI1->Value(i) << endl;
195 //  } 
196
197
198   if (key) {
199
200 // creation of Vrml objects
201     Handle(VrmlConverter_LineAspect) LA = new VrmlConverter_LineAspect;
202     LA = aDrawer->LineAspect();
203
204 // Separator 1 {
205     Vrml_Separator SE1;
206     SE1.Print(anOStream);
207 // Material
208     if (LA->HasMaterial()){
209
210       Handle(Vrml_Material) M;
211       M = LA->Material();
212     
213       M->Print(anOStream);
214     }
215 // Coordinate3
216     Handle(Vrml_Coordinate3)  C3 = new Vrml_Coordinate3(HAV1);
217     C3->Print(anOStream);
218 // IndexedLineSet
219     Vrml_IndexedLineSet  ILS;
220     ILS.SetCoordIndex(HAI1);
221     ILS.Print(anOStream);
222 // Separator 1 }
223     SE1.Print(anOStream);
224   }
225 }
226 //==================================================================
227 // function: GetDeflection
228 // purpose:
229 //==================================================================
230 static Standard_Real GetDeflection(const Adaptor3d_Curve&        aCurve,
231                                    const Standard_Real         U1, 
232                                    const Standard_Real         U2, 
233                                    const Handle(VrmlConverter_Drawer)& aDrawer) {
234
235   Standard_Real theRequestedDeflection;
236   if(aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE)   // TOD_RELATIVE, TOD_ABSOLUTE
237     {
238       Bnd_Box box;
239       BndLib_Add3dCurve::Add(aCurve, U1, U2, Precision::Confusion(), box);
240
241       Standard_Real  Xmin, Xmax, Ymin, Ymax, Zmin, Zmax, diagonal;
242       box.Get( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax );
243       if (!(box.IsOpenXmin() || box.IsOpenXmax() ||
244             box.IsOpenYmin() || box.IsOpenYmax() ||
245             box.IsOpenZmin() || box.IsOpenZmax()))
246         {
247           diagonal = Sqrt ((Xmax - Xmin)*( Xmax - Xmin) + ( Ymax - Ymin)*( Ymax - Ymin) + ( Zmax - Zmin)*( Zmax - Zmin));
248           diagonal = Max(diagonal, Precision::Confusion());
249           theRequestedDeflection = aDrawer->DeviationCoefficient() * diagonal;      
250         }  
251       else
252         {
253           diagonal =1000000.;
254           theRequestedDeflection = aDrawer->DeviationCoefficient() * diagonal;  
255         }
256 //      cout << "diagonal = " << diagonal << endl;
257 //      cout << "theRequestedDeflection = " << theRequestedDeflection << endl;
258     }
259   else 
260     {
261       theRequestedDeflection = aDrawer->MaximalChordialDeviation(); 
262     }
263   return theRequestedDeflection;
264 }
265 //==================================================================
266 // function: Add
267 // purpose: 1
268 //==================================================================
269 void VrmlConverter_DeflectionCurve::Add(Standard_OStream&                   anOStream, 
270                                          Adaptor3d_Curve&                aCurve, 
271                                         const Handle(VrmlConverter_Drawer)& aDrawer)
272 {
273
274   Standard_Real V1, V2;
275   Standard_Real aLimit = aDrawer->MaximalParameterValue();
276   FindLimits(aCurve, aLimit, V1, V2);
277  
278   Standard_Real theRequestedDeflection = GetDeflection(aCurve, V1, V2, aDrawer);
279
280   DrawCurve(aCurve,
281             theRequestedDeflection,
282             V1 , V2, aDrawer, anOStream);
283 }
284
285 //==================================================================
286 // function: Add 
287 // purpose: 2
288 //==================================================================
289 void VrmlConverter_DeflectionCurve::Add(Standard_OStream&                   anOStream,
290                                         Adaptor3d_Curve&                aCurve, 
291                                         const Standard_Real                 U1, 
292                                         const Standard_Real                 U2, 
293                                         const Handle(VrmlConverter_Drawer)& aDrawer)
294 {
295   Standard_Real V1 = U1;
296   Standard_Real V2 = U2;  
297
298   if (Precision::IsNegativeInfinite(V1)) V1 = -aDrawer->MaximalParameterValue();
299   if (Precision::IsPositiveInfinite(V2)) V2 = aDrawer->MaximalParameterValue();
300
301   Standard_Real theRequestedDeflection = GetDeflection(aCurve, V1, V2, aDrawer);
302   DrawCurve(aCurve,
303             theRequestedDeflection,
304             V1 , V2, aDrawer, anOStream);
305
306 }
307 //==================================================================
308 // function: Add
309 // purpose: 3
310 //==================================================================
311
312 void VrmlConverter_DeflectionCurve::Add(Standard_OStream&    anOStream, 
313                                         Adaptor3d_Curve& aCurve, 
314                                         const Standard_Real  aDeflection, 
315                                         const Standard_Real  aLimit)
316 {
317   Standard_Real V1, V2;
318   FindLimits(aCurve, aLimit, V1, V2);
319
320   Handle(VrmlConverter_Drawer) aDrawer = new VrmlConverter_Drawer;
321   Handle(VrmlConverter_LineAspect) la = new  VrmlConverter_LineAspect;
322   aDrawer->SetLineAspect(la);
323
324   DrawCurve(aCurve,
325             aDeflection,
326             V1 , V2, aDrawer, anOStream);
327 }
328 //==================================================================
329 // function: Add
330 // purpose: 4
331 //==================================================================
332
333 void VrmlConverter_DeflectionCurve::Add(Standard_OStream&                   anOStream, 
334                                         Adaptor3d_Curve&                aCurve, 
335                                         const Standard_Real                 aDeflection, 
336                                         const Handle(VrmlConverter_Drawer)& aDrawer)
337 {
338   Standard_Real aLimit = aDrawer->MaximalParameterValue();
339   Standard_Real V1, V2;
340   FindLimits(aCurve, aLimit, V1, V2);
341
342   DrawCurve(aCurve,
343             aDeflection,
344             V1 , V2, aDrawer, anOStream);
345 }
346 //==================================================================
347 // function: Add
348 // purpose: 5
349 //==================================================================
350
351 void VrmlConverter_DeflectionCurve::Add(Standard_OStream&    anOStream, 
352                                         Adaptor3d_Curve& aCurve, 
353                                         const Standard_Real  U1, 
354                                         const Standard_Real  U2, 
355                                         const Standard_Real  aDeflection)
356 {
357   Handle(VrmlConverter_Drawer) aDrawer = new VrmlConverter_Drawer;
358   Handle(VrmlConverter_LineAspect) la = new VrmlConverter_LineAspect;
359   aDrawer->SetLineAspect(la);
360
361   DrawCurve(aCurve,
362             aDeflection,
363             U1 , U2, aDrawer, anOStream);
364 }
365