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