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