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