0024157: Parallelization of assembly part of BO
[occt.git] / src / VrmlData / VrmlData_Geometry.cxx
1 // Created on: 2006-05-25
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2006-2012 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
22 #include <VrmlData_Scene.hxx>
23 #include <VrmlData_Coordinate.hxx>
24 #include <VrmlData_Color.hxx>
25 #include <VrmlData_Normal.hxx>
26 #include <VrmlData_TextureCoordinate.hxx>
27 #include <VrmlData_InBuffer.hxx>
28 #include <VrmlData_Box.hxx>
29 #include <VrmlData_Cone.hxx>
30 #include <VrmlData_Cylinder.hxx>
31 #include <VrmlData_Sphere.hxx>
32 #include <VrmlData_UnknownNode.hxx>
33 #include <BRepPrimAPI_MakeBox.hxx>
34 #include <BRepPrim_Cone.hxx>
35 #include <BRepPrim_Cylinder.hxx>
36 #include <BRepPrim_Sphere.hxx>
37 #include <BRepPrim_Builder.hxx>
38 #include <NCollection_Vector.hxx>
39 #include <Standard_ErrorHandler.hxx>
40
41 #ifdef WNT
42 #define _CRT_SECURE_NO_DEPRECATE
43 #pragma warning (disable:4996)
44 #endif
45
46 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Geometry, VrmlData_Node)
47 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Geometry, VrmlData_Node)
48 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Box, VrmlData_Geometry)
49 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Box, VrmlData_Geometry)
50 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Cone, VrmlData_Geometry)
51 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Cone, VrmlData_Geometry)
52 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Cylinder, VrmlData_Geometry)
53 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Cylinder, VrmlData_Geometry)
54 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Sphere, VrmlData_Geometry)
55 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Sphere, VrmlData_Geometry)
56 IMPLEMENT_STANDARD_HANDLE  (VrmlData_ArrayVec3d, VrmlData_Node)
57 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_ArrayVec3d, VrmlData_Node)
58 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Color, VrmlData_ArrayVec3d)
59 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Color, VrmlData_ArrayVec3d)
60 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Coordinate, VrmlData_ArrayVec3d)
61 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Coordinate, VrmlData_ArrayVec3d)
62 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Normal, VrmlData_ArrayVec3d)
63 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Normal, VrmlData_ArrayVec3d)
64 IMPLEMENT_STANDARD_HANDLE  (VrmlData_TextureCoordinate, VrmlData_Node)
65 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_TextureCoordinate, VrmlData_Node)
66
67 //=======================================================================
68 //function : Value
69 //purpose  : 
70 //=======================================================================
71
72 const gp_XYZ& VrmlData_ArrayVec3d::Value (const Standard_Size i) const
73 {
74   static gp_XYZ anOrigin (0., 0., 0.);
75   return i < myLength ? myArray[i] : anOrigin;
76 }
77
78 //=======================================================================
79 //function : AllocateValues
80 //purpose  : 
81 //=======================================================================
82
83 Standard_Boolean VrmlData_ArrayVec3d::AllocateValues
84                                 (const Standard_Size theLength)
85 {
86   myArray = reinterpret_cast <const gp_XYZ *>
87     (Scene().Allocator()->Allocate (theLength*sizeof(gp_XYZ)));
88   myLength = theLength;
89   return (myArray != 0L);
90 }
91
92 //=======================================================================
93 //function : VrmlData_Box::TShape
94 //purpose  : 
95 //=======================================================================
96
97 const Handle(TopoDS_TShape)& VrmlData_Box::TShape ()
98 {
99   if (myIsModified) {
100     try {
101       const TopoDS_Shell aShell =
102         BRepPrimAPI_MakeBox (gp_Pnt (-0.5 * mySize),
103                              mySize.X(), mySize.Y(), mySize.Z());
104       SetTShape (aShell.TShape());
105       myIsModified = Standard_False;
106     } catch (Standard_Failure) {
107       myTShape.Nullify();
108     }
109   }
110   return myTShape;
111 }
112
113 //=======================================================================
114 //function : VrmlData_Box::Clone
115 //purpose  : 
116 //=======================================================================
117
118 Handle(VrmlData_Node) VrmlData_Box::Clone
119                                 (const Handle(VrmlData_Node)& theOther) const
120 {
121   Handle(VrmlData_Box) aResult =
122     Handle(VrmlData_Box)::DownCast (VrmlData_Node::Clone(theOther));
123   if (aResult.IsNull())
124     aResult = new VrmlData_Box (theOther.IsNull() ? Scene() : theOther->Scene(),
125                                 Name());
126   aResult->SetSize(mySize);
127   return aResult;
128 }
129
130 //=======================================================================
131 //function : VrmlData_Box::Read
132 //purpose  : 
133 //=======================================================================
134
135 VrmlData_ErrorStatus VrmlData_Box::Read (VrmlData_InBuffer& theBuffer)
136 {
137   VrmlData_ErrorStatus aStatus;
138   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
139     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "size"))
140       aStatus = Scene().ReadXYZ (theBuffer, mySize,
141                                  Standard_True, Standard_True);
142     if (OK(aStatus))
143       aStatus = readBrace (theBuffer);
144   }
145   return aStatus;
146 }
147
148 //=======================================================================
149 //function : VrmlData_Box::Write
150 //purpose  : 
151 //=======================================================================
152
153 VrmlData_ErrorStatus VrmlData_Box::Write (const char * thePrefix) const
154 {
155   static char header[] = "Box {";
156   VrmlData_ErrorStatus aStatus;
157   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
158   {
159     char buf[128];
160     Sprintf (buf, "size %.12g %.12g %.12g", mySize.X(), mySize.Y(), mySize.Z());
161     Scene().WriteLine (buf);
162     aStatus = WriteClosing();
163   }
164   return aStatus;
165 }
166
167 //=======================================================================
168 //function : VrmlData_Cone::TShape
169 //purpose  : 
170 //=======================================================================
171
172 const Handle(TopoDS_TShape)& VrmlData_Cone::TShape ()
173 {
174   if (myIsModified && (myHasBottom || myHasSide)) {
175     try {
176       gp_Ax2 aLocalAxis (gp_Pnt (0., -0.5 * myHeight, 0.),
177                          gp_Dir (0., 1., 0.));
178       BRepPrim_Cone aBuilder (aLocalAxis, myBottomRadius, 0., myHeight);
179       if (!myHasBottom)
180         myTShape = aBuilder.LateralFace().TShape();
181       else if (!myHasSide) 
182         myTShape = aBuilder.BottomFace().TShape();
183       else
184         myTShape = aBuilder.Shell().TShape();
185       myIsModified = Standard_False;
186     } catch (Standard_Failure) {
187       myTShape.Nullify();
188     }
189   }
190   return myTShape;
191 }
192
193 //=======================================================================
194 //function : VrmlData_Cone::Clone
195 //purpose  : 
196 //=======================================================================
197
198 Handle(VrmlData_Node) VrmlData_Cone::Clone
199                                 (const Handle(VrmlData_Node)& theOther) const
200 {
201   Handle(VrmlData_Cone) aResult =
202     Handle(VrmlData_Cone)::DownCast (VrmlData_Node::Clone(theOther));
203   if (aResult.IsNull())
204     aResult = new VrmlData_Cone (theOther.IsNull() ? Scene(): theOther->Scene(),
205                                 Name());
206
207   aResult->SetBottomRadius (myBottomRadius);
208   aResult->SetHeight (myHeight);
209   aResult->SetFaces (myHasBottom, myHasSide);
210   return aResult;
211 }
212
213 //=======================================================================
214 //function : VrmlData_Cone::Read
215 //purpose  : 
216 //=======================================================================
217
218 VrmlData_ErrorStatus VrmlData_Cone::Read (VrmlData_InBuffer& theBuffer)
219 {
220   VrmlData_ErrorStatus aStatus;
221   Standard_Boolean hasSide(Standard_True), hasBottom(Standard_True);
222
223   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
224   {
225     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bottomRadius"))
226       aStatus = Scene().ReadReal (theBuffer, myBottomRadius,
227                                   Standard_True, Standard_True);
228     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "height"))
229       aStatus = Scene().ReadReal (theBuffer, myHeight,
230                                   Standard_True, Standard_True);
231     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "side")) {
232       if (OK(aStatus, ReadBoolean (theBuffer, hasSide)))
233         myHasSide = hasSide;
234     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bottom")) {
235       if (OK(aStatus, ReadBoolean (theBuffer, hasBottom)))
236         myHasBottom = hasBottom;
237     } else
238       break;
239
240     if (!OK(aStatus))
241       break;
242   }
243   // Read the terminating (closing) brace
244   if (OK(aStatus))
245     aStatus = readBrace (theBuffer);
246   return aStatus;
247 }
248
249 //=======================================================================
250 //function : VrmlData_Cone::Write
251 //purpose  : 
252 //=======================================================================
253
254 VrmlData_ErrorStatus VrmlData_Cone::Write (const char * thePrefix) const
255 {
256   static char header[] = "Cone {";
257   VrmlData_ErrorStatus aStatus;
258   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
259   {
260     char buf[128];
261     if ((myBottomRadius - 1.)*(myBottomRadius - 1.) > Precision::Confusion()) {
262       Sprintf (buf, "bottomRadius %.12g", myBottomRadius);
263       aStatus = Scene().WriteLine (buf);
264     }
265     if (OK(aStatus) &&
266         (myHeight - 2.)*(myHeight - 2.) > Precision::Confusion()) {
267       Sprintf (buf, "height       %.12g", myHeight);
268       aStatus = Scene().WriteLine (buf);
269     }
270     if (OK(aStatus) && myHasBottom == Standard_False)
271       aStatus = Scene().WriteLine ("bottom   FALSE");
272     if (OK(aStatus) && myHasSide == Standard_False)
273       aStatus = Scene().WriteLine ("side     FALSE");
274
275     aStatus = WriteClosing();
276   }
277   return aStatus;
278 }
279
280 //=======================================================================
281 //function : VrmlData_Cone::IsDefault
282 //purpose  : 
283 //=======================================================================
284
285 // Standard_Boolean VrmlData_Cone::IsDefault () const
286 // {
287 //   return
288 //     (myHasBottom && myHasSide &&
289 //      ((myBottomRadius - 1.)*(myBottomRadius-1.) < Precision::Confusion()) &&
290 //      ((myHeight - 2.)*(myHeight - 2.) < Precision::Confusion()));
291 // }
292
293 //=======================================================================
294 //function : VrmlData_Cylinder::TShape
295 //purpose  : 
296 //=======================================================================
297
298 const Handle(TopoDS_TShape)& VrmlData_Cylinder::TShape ()
299 {
300   if (myIsModified && (myHasBottom || myHasSide || myHasTop)) {
301     try {
302       gp_Ax2 aLocalAxis (gp_Pnt (0., -0.5 * myHeight, 0.),
303                          gp_Dir (0., 1., 0.));
304       BRepPrim_Cylinder aBuilder (aLocalAxis, myRadius, myHeight);
305       BRepPrim_Builder aShapeBuilder;
306       TopoDS_Shell aShell;
307       aShapeBuilder.MakeShell(aShell);
308       if (myHasSide)
309         aShapeBuilder.AddShellFace (aShell, aBuilder.LateralFace());
310       if (myHasTop)
311         aShapeBuilder.AddShellFace (aShell, aBuilder.TopFace());
312       if (myHasBottom)
313         aShapeBuilder.AddShellFace (aShell, aBuilder.BottomFace());
314       myTShape = aShell.TShape();
315       myIsModified = Standard_False;
316     } catch (Standard_Failure) {
317       myTShape.Nullify();
318     }
319   }
320   return myTShape;
321 }
322
323 //=======================================================================
324 //function : VrmlData_Cylinder::Clone
325 //purpose  : 
326 //=======================================================================
327
328 Handle(VrmlData_Node) VrmlData_Cylinder::Clone
329                                 (const Handle(VrmlData_Node)& theOther) const
330 {
331   Handle(VrmlData_Cylinder) aResult =
332     Handle(VrmlData_Cylinder)::DownCast (VrmlData_Node::Clone(theOther));
333   if (aResult.IsNull())
334     aResult = new VrmlData_Cylinder(theOther.IsNull()?Scene():theOther->Scene(),
335                                     Name());
336   aResult->SetRadius (myRadius);
337   aResult->SetHeight (myHeight);
338   aResult->SetFaces  (myHasBottom, myHasSide, myHasTop);
339   return aResult;
340 }
341
342 //=======================================================================
343 //function : VrmlData_Cylinder::Read
344 //purpose  : 
345 //=======================================================================
346
347 VrmlData_ErrorStatus VrmlData_Cylinder::Read (VrmlData_InBuffer& theBuffer)
348 {
349   VrmlData_ErrorStatus aStatus;
350   Standard_Boolean hasSide(Standard_True), hasBottom(Standard_True);
351   Standard_Boolean hasTop (Standard_True);
352
353   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
354   {
355     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "radius"))
356       aStatus = Scene().ReadReal (theBuffer, myRadius,
357                                   Standard_True, Standard_True);
358     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "height"))
359       aStatus = Scene().ReadReal (theBuffer, myHeight,
360                                   Standard_True, Standard_True);
361     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "top")) {
362       if (OK(aStatus, ReadBoolean (theBuffer, hasTop)))
363         myHasTop = hasTop;
364     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "side")) {
365       if (OK(aStatus, ReadBoolean (theBuffer, hasSide)))
366         myHasSide = hasSide;
367     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bottom")) {
368       if (OK(aStatus, ReadBoolean (theBuffer, hasBottom)))
369         myHasBottom = hasBottom;
370     } else
371       break;
372
373     if (!OK(aStatus))
374       break;
375   }
376
377   // Read the terminating (closing) brace
378   if (OK(aStatus))
379     aStatus = readBrace (theBuffer);
380   return aStatus;
381 }
382
383 //=======================================================================
384 //function : VrmlData_Cylinder::Write
385 //purpose  : 
386 //=======================================================================
387
388 VrmlData_ErrorStatus VrmlData_Cylinder::Write (const char * thePrefix) const
389 {
390   static char header[] = "Cylinder {";
391   VrmlData_ErrorStatus aStatus;
392   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
393   {
394     char buf[128];
395     if ((myRadius - 1.)*(myRadius - 1.) > Precision::Confusion()) {
396       Sprintf (buf, "radius   %.12g", myRadius);
397       aStatus = Scene().WriteLine (buf);
398     }
399     if (OK(aStatus) &&
400         (myHeight - 2.)*(myHeight - 2.) > Precision::Confusion()) {
401       Sprintf (buf, "height   %.12g", myHeight);
402       aStatus = Scene().WriteLine (buf);
403     }
404     if (OK(aStatus) && myHasBottom == Standard_False)
405       aStatus = Scene().WriteLine ("bottom   FALSE");
406     if (OK(aStatus) && myHasSide == Standard_False)
407       aStatus = Scene().WriteLine ("side     FALSE");
408     if (OK(aStatus) && myHasTop == Standard_False)
409       aStatus = Scene().WriteLine ("top      FALSE");
410
411     aStatus = WriteClosing();
412   }
413   return aStatus;
414 }
415
416 //=======================================================================
417 //function : VrmlData_Cylinder::IsDefault
418 //purpose  : 
419 //=======================================================================
420
421 // Standard_Boolean VrmlData_Cylinder::IsDefault () const
422 // {
423 //   return
424 //     (myHasBottom && myHasSide && myHasTop &&
425 //      ((myRadius - 1.)*(myRadius - 1.) < Precision::Confusion()) &&
426 //      ((myHeight - 2.)*(myHeight - 2.) < Precision::Confusion()));
427 // }
428
429 //=======================================================================
430 //function : VrmlData_Sphere::TShape
431 //purpose  : 
432 //=======================================================================
433
434 const Handle(TopoDS_TShape)& VrmlData_Sphere::TShape ()
435 {
436   if (myIsModified) {
437     try {
438       myTShape = BRepPrim_Sphere(myRadius).Shell().TShape();
439       myIsModified = Standard_False;
440     } catch (Standard_Failure) {
441       myTShape.Nullify();
442     }
443   }
444   return myTShape;
445 }
446
447 //=======================================================================
448 //function : VrmlData_Sphere::Clone
449 //purpose  : 
450 //=======================================================================
451
452 Handle(VrmlData_Node) VrmlData_Sphere::Clone
453                                 (const Handle(VrmlData_Node)& theOther) const
454 {
455   Handle(VrmlData_Sphere) aResult =
456     Handle(VrmlData_Sphere)::DownCast (VrmlData_Node::Clone(theOther));
457   if (aResult.IsNull())
458     aResult = new VrmlData_Sphere(theOther.IsNull()? Scene() :theOther->Scene(),
459                                   Name());
460   aResult->SetRadius (myRadius);
461   return aResult;
462 }
463
464 //=======================================================================
465 //function : VrmlData_Sphere::Read
466 //purpose  : 
467 //=======================================================================
468
469 VrmlData_ErrorStatus VrmlData_Sphere::Read (VrmlData_InBuffer& theBuffer)
470 {
471   VrmlData_ErrorStatus aStatus;
472   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
473     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "radius"))
474       aStatus = Scene().ReadReal (theBuffer, myRadius,
475                                   Standard_True, Standard_True);
476     else
477       break;
478
479   // Read the terminating (closing) brace
480   if (OK(aStatus))
481     aStatus = readBrace (theBuffer);
482   return aStatus;
483 }
484
485 //=======================================================================
486 //function : VrmlData_Sphere::Write
487 //purpose  : 
488 //=======================================================================
489
490 VrmlData_ErrorStatus VrmlData_Sphere::Write (const char * thePrefix) const
491 {
492   static char header[] = "Sphere {";
493   VrmlData_ErrorStatus aStatus;
494   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
495   {
496     char buf[128];
497     Sprintf (buf, "radius   %.12g", myRadius);
498     Scene().WriteLine (buf);
499     aStatus = WriteClosing();
500   }
501   return aStatus;
502 }
503
504 //=======================================================================
505 //function : VrmlData_Sphere::IsDefault
506 //purpose  : 
507 //=======================================================================
508
509 // Standard_Boolean VrmlData_Sphere::IsDefault () const
510 // {
511 //   return ((myRadius - 1.)*(myRadius - 1.) < Precision::Confusion())
512 // }
513
514 //=======================================================================
515 //function : VrmlData_TextureCoordinate::AllocateValues
516 //purpose  : 
517 //=======================================================================
518
519 Standard_Boolean VrmlData_TextureCoordinate::AllocateValues
520                                 (const Standard_Size theLength)
521 {
522   myPoints = reinterpret_cast <const gp_XY *>
523     (Scene().Allocator()->Allocate (theLength*sizeof(gp_XY)));
524   myLength = theLength;
525   return (myPoints != 0L);
526 }
527
528 //=======================================================================
529 //function : VrmlData_TextureCoordinate::Clone
530 //purpose  : 
531 //=======================================================================
532
533 Handle(VrmlData_Node) VrmlData_TextureCoordinate::Clone
534                                 (const Handle(VrmlData_Node)& theOther) const
535 {
536   Handle(VrmlData_TextureCoordinate) aResult =
537     Handle(VrmlData_TextureCoordinate)::DownCast
538     (VrmlData_Node::Clone(theOther));
539   if (aResult.IsNull())
540     aResult = new VrmlData_TextureCoordinate
541       (theOther.IsNull() ? Scene() : theOther->Scene(), Name());
542   if (&aResult->Scene() == &Scene())
543     aResult->SetPoints (myLength, myPoints);
544   else {
545     aResult->AllocateValues (myLength);
546     for (Standard_Size i = 0; i < myLength; i++)
547       const_cast <gp_XY&> (aResult->myPoints[i]) = myPoints[i];
548   }
549   return aResult;
550 }
551
552 //=======================================================================
553 //function : VrmlData_TextureCoordinate::Read
554 //purpose  : 
555 //=======================================================================
556
557 VrmlData_ErrorStatus VrmlData_TextureCoordinate::Read
558                                         (VrmlData_InBuffer& theBuffer)
559 {
560   VrmlData_ErrorStatus aStatus;
561   NCollection_Vector<gp_XY> vecValues;
562   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
563     // Match the name with the current word in the stream
564     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "point"))
565       // Read the body of the data node (comma-separated list of duplets)
566       if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
567         if (theBuffer.LinePtr[0] != '[')  // opening bracket
568           aStatus = VrmlData_VrmlFormatError;
569         else {
570           theBuffer.LinePtr++;
571           for(;;) {
572             gp_XY anXY;
573             if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
574               break;
575             // closing bracket, in case that it follows a comma
576             if (theBuffer.LinePtr[0] == ']') {
577               theBuffer.LinePtr++;
578               break;
579             }
580             if (!OK(aStatus, Scene().ReadXY(theBuffer, anXY,
581                                             Standard_False, Standard_False)))
582               break;
583             vecValues.Append(anXY);
584             if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
585               break;
586             if (theBuffer.LinePtr[0] == ',') {
587               theBuffer.LinePtr++;
588             } else if (theBuffer.LinePtr[0] == ']') { // closing bracket
589               theBuffer.LinePtr++;
590               break;
591             }
592           }
593         }
594       }
595     if (OK(aStatus) && OK(aStatus, readBrace (theBuffer))) {
596       myLength = vecValues.Length();
597       if (myLength > 0) {
598         gp_XY * aPoints = reinterpret_cast <gp_XY *>
599           (Scene().Allocator()->Allocate (myLength * sizeof(gp_XY)));
600         myPoints = aPoints;
601         for (Standard_Integer i = 0; i < Standard_Integer(myLength); i++)
602           aPoints[i] = vecValues(i);
603       }
604     }
605   }
606   return aStatus;
607 }
608
609 //=======================================================================
610 //function : VrmlData_ArrayVec3d::Clone
611 //purpose  : 
612 //=======================================================================
613
614 // Handle(VrmlData_Node) VrmlData_ArrayVec3d::Clone
615 //                                 (const Handle(VrmlData_Node)& theOther) const
616 // {
617 //   VrmlData_Node::Clone (theOther);
618 //   const Handle(VrmlData_ArrayVec3d) anArrayNode =
619 //     Handle(VrmlData_ArrayVec3d)::DownCast (theOther);
620 //   if (anArrayNode.IsNull() == Standard_False)
621 //     anArrayNode->SetValues (myLength, myArray);
622 //   return theOther;
623 // }
624
625 //=======================================================================
626 //function : VrmlData_ArrayVec3d::ReadArray
627 //purpose  : 
628 //=======================================================================
629
630 VrmlData_ErrorStatus VrmlData_ArrayVec3d::ReadArray
631                                         (VrmlData_InBuffer&     theBuffer,
632                                          const char *           theName,
633                                          const Standard_Boolean isScale)
634 {
635   VrmlData_ErrorStatus aStatus;
636   NCollection_Vector<gp_XYZ> vecValues;
637   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
638     // Match the name with the current word in the stream
639     if (theName) {
640       const Standard_Size aNameLen = strlen(theName);
641       if (strncmp (theBuffer.LinePtr, theName, aNameLen))
642         aStatus = VrmlData_VrmlFormatError;
643       else
644         theBuffer.LinePtr += aNameLen;
645     } else {
646       // Skip the word in the input
647       while (theBuffer.LinePtr[0] != ' ' &&
648              theBuffer.LinePtr[0] != ',' &&
649              theBuffer.LinePtr[0] != '\t' &&
650              theBuffer.LinePtr[0] != '\n' &&
651              theBuffer.LinePtr[0] != '\r' &&
652              theBuffer.LinePtr[0] != '\0')
653         theBuffer.LinePtr++;
654     }
655     // Read the body of the data node (list of triplets)
656     if (OK(aStatus) && OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
657       if (theBuffer.LinePtr[0] != '[')  // opening bracket
658         aStatus = VrmlData_VrmlFormatError;
659       else {
660         theBuffer.LinePtr++;
661         for(;;) {
662           gp_XYZ anXYZ;
663           if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
664             break;
665           // closing bracket, in case that it follows a comma
666           if (theBuffer.LinePtr[0] == ']') {
667             theBuffer.LinePtr++;
668             break;
669           }
670           // Read three numbers (XYZ value)
671           if (!OK(aStatus, Scene().ReadXYZ(theBuffer, anXYZ,
672                                            isScale, Standard_False)))
673             break;
674           vecValues.Append(anXYZ);
675           if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
676             break;
677           if (theBuffer.LinePtr[0] == ']') {// closing bracket
678             theBuffer.LinePtr++;
679             break;
680           }
681         }
682       }
683     }
684     if (OK(aStatus) && OK(aStatus, readBrace (theBuffer))) {
685       myLength = vecValues.Length();
686       if (myLength > 0) {
687         gp_XYZ * anArray = reinterpret_cast <gp_XYZ *>
688           (Scene().Allocator()->Allocate (myLength * sizeof(gp_XYZ)));
689         myArray = anArray;
690         for (Standard_Integer i = 0; i < Standard_Integer(myLength); i++)
691           anArray[i] = vecValues(i);
692       }
693     }
694   }
695   return aStatus;
696 }
697
698 //=======================================================================
699 //function : VrmlData_ArrayVec3d::WriteArray
700 //purpose  : 
701 //=======================================================================
702
703 VrmlData_ErrorStatus VrmlData_ArrayVec3d::WriteArray
704                                         (const char *           theName,
705                                          const Standard_Boolean isScale) const
706 {
707   VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
708   if (myLength > 0) {
709     aStatus = Scene().WriteLine (theName, "[", 2*GlobalIndent());
710     if (OK(aStatus)) {
711       for (Standard_Size i = 0; i < myLength-1; i++)
712         if (!OK (aStatus, Scene().WriteXYZ (myArray[i], isScale, ",")))
713           break;
714       if (OK(aStatus))
715         aStatus = Scene().WriteXYZ (myArray[myLength-1], isScale);
716     }
717     if (aStatus == VrmlData_StatusOK)
718       aStatus = Scene().WriteLine ("]", 0L, -2*GlobalIndent());
719   }
720   return aStatus;
721 }
722
723 //=======================================================================
724 //function : VrmlData_ArrayVec3d::IsDefault
725 //purpose  : 
726 //=======================================================================
727
728 Standard_Boolean VrmlData_ArrayVec3d::IsDefault () const
729 {
730   return myLength == 0;
731 }
732
733 //=======================================================================
734 //function : VrmlData_Coodinate::Clone
735 //purpose  : 
736 //=======================================================================
737
738 Handle(VrmlData_Node) VrmlData_Coordinate::Clone
739                                 (const Handle(VrmlData_Node)& theOther) const
740 {
741   Handle(VrmlData_Coordinate) aResult =
742     Handle(VrmlData_Coordinate)::DownCast (VrmlData_Node::Clone(theOther));
743   if (aResult.IsNull())
744     aResult = new VrmlData_Coordinate
745       (theOther.IsNull() ? Scene() : theOther->Scene(), Name());
746   if (&aResult->Scene() == &Scene())
747     aResult->SetValues (Length(), Values());
748   else {
749     aResult->AllocateValues (Length());
750     for (Standard_Size i = 0; i < Length(); i++)
751       const_cast <gp_XYZ&> (aResult->Values()[i]) = Values()[i];
752   }
753   return aResult;
754 }
755
756 //=======================================================================
757 //function : VrmlData_Coordinate::Read
758 //purpose  : 
759 //=======================================================================
760
761 VrmlData_ErrorStatus VrmlData_Coordinate::Read (VrmlData_InBuffer& theBuffer)
762 {
763   return VrmlData_ArrayVec3d::ReadArray (theBuffer, "point", Standard_True);
764 }
765
766 //=======================================================================
767 //function : VrmlData_Coordinate::Write
768 //purpose  : 
769 //=======================================================================
770
771 VrmlData_ErrorStatus VrmlData_Coordinate::Write (const char * thePrefix) const
772 {
773   static char header[] = "Coordinate {";
774   VrmlData_ErrorStatus aStatus;
775   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
776   {
777     WriteArray ("point", Standard_True);
778     aStatus = WriteClosing();
779   }
780   return aStatus;
781 }
782
783 //=======================================================================
784 //function : VrmlData_Color::Clone
785 //purpose  : 
786 //=======================================================================
787
788 Handle(VrmlData_Node) VrmlData_Color::Clone
789                                 (const Handle(VrmlData_Node)& theOther) const
790 {
791   Handle(VrmlData_Color) aResult =
792     Handle(VrmlData_Color)::DownCast (VrmlData_Node::Clone(theOther));
793   if (aResult.IsNull())
794     aResult = new VrmlData_Color(theOther.IsNull()? Scene() : theOther->Scene(),
795                                  Name());
796   if (&aResult->Scene() == &Scene())
797     aResult->SetValues (Length(), Values());
798   else {
799     aResult->AllocateValues (Length());
800     for (Standard_Size i = 0; i < Length(); i++)
801       const_cast <gp_XYZ&> (aResult->Values()[i]) = Values()[i];
802   }
803   return aResult;
804 }
805
806 //=======================================================================
807 //function : VrmlData_Color::Read
808 //purpose  : 
809 //=======================================================================
810
811 VrmlData_ErrorStatus VrmlData_Color::Read (VrmlData_InBuffer& theBuffer)
812 {
813   return ReadArray (theBuffer, "color", Standard_False);
814 }
815
816 //=======================================================================
817 //function : VrmlData_Color::Write
818 //purpose  : 
819 //=======================================================================
820
821 VrmlData_ErrorStatus VrmlData_Color::Write (const char * thePrefix) const
822 {
823   static char header[] = "Color {";
824   VrmlData_ErrorStatus aStatus;
825   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
826   {
827     WriteArray ("color", Standard_False);
828     aStatus = WriteClosing();
829   }
830   return aStatus;
831 }
832
833 //=======================================================================
834 //function : VrmlData_Normal::Clone
835 //purpose  : 
836 //=======================================================================
837
838 Handle(VrmlData_Node) VrmlData_Normal::Clone
839                                 (const Handle(VrmlData_Node)& theOther) const
840 {
841   Handle(VrmlData_Normal) aResult =
842     Handle(VrmlData_Normal)::DownCast (VrmlData_Node::Clone(theOther));
843   if (aResult.IsNull())
844     aResult= new VrmlData_Normal(theOther.IsNull()? Scene() : theOther->Scene(),
845                                  Name());
846   if (&aResult->Scene() == &Scene())
847     aResult->SetValues (Length(), Values());
848   else {
849     aResult->AllocateValues (Length());
850     for (Standard_Size i = 0; i < Length(); i++)
851       const_cast <gp_XYZ&> (aResult->Values()[i]) = Values()[i];
852   }
853   return aResult;
854 }
855
856 //=======================================================================
857 //function : VrmlData_Normal::Read
858 //purpose  : 
859 //=======================================================================
860
861 VrmlData_ErrorStatus VrmlData_Normal::Read (VrmlData_InBuffer& theBuffer)
862 {
863   return VrmlData_ArrayVec3d::ReadArray (theBuffer, "vector", Standard_False);
864 }
865
866 //=======================================================================
867 //function : VrmlData_Normal::Write
868 //purpose  : 
869 //=======================================================================
870
871 VrmlData_ErrorStatus VrmlData_Normal::Write (const char * thePrefix) const
872 {
873   static char header[] = "Normal {";
874   VrmlData_ErrorStatus aStatus;
875   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
876   {
877     WriteArray ("vector", Standard_False);
878     aStatus = WriteClosing();
879   }
880   return aStatus;
881 }