ca634a52ed8fafa6ba745b0a52d7604d3ee27067
[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           while (~0) {
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     if (OK(aStatus) && OK(aStatus, readBrace (theBuffer))) {
595       myLength = vecValues.Length();
596       if (myLength > 0) {
597         gp_XY * aPoints = reinterpret_cast <gp_XY *>
598           (Scene().Allocator()->Allocate (myLength * sizeof(gp_XY)));
599         myPoints = aPoints;
600         for (Standard_Integer i = 0; i < Standard_Integer(myLength); i++)
601           aPoints[i] = vecValues(i);
602       }
603     }
604   }
605   return aStatus;
606 }
607
608 //=======================================================================
609 //function : VrmlData_ArrayVec3d::Clone
610 //purpose  : 
611 //=======================================================================
612
613 // Handle(VrmlData_Node) VrmlData_ArrayVec3d::Clone
614 //                                 (const Handle(VrmlData_Node)& theOther) const
615 // {
616 //   VrmlData_Node::Clone (theOther);
617 //   const Handle(VrmlData_ArrayVec3d) anArrayNode =
618 //     Handle(VrmlData_ArrayVec3d)::DownCast (theOther);
619 //   if (anArrayNode.IsNull() == Standard_False)
620 //     anArrayNode->SetValues (myLength, myArray);
621 //   return theOther;
622 // }
623
624 //=======================================================================
625 //function : VrmlData_ArrayVec3d::ReadArray
626 //purpose  : 
627 //=======================================================================
628
629 VrmlData_ErrorStatus VrmlData_ArrayVec3d::ReadArray
630                                         (VrmlData_InBuffer&     theBuffer,
631                                          const char *           theName,
632                                          const Standard_Boolean isScale)
633 {
634   VrmlData_ErrorStatus aStatus;
635   NCollection_Vector<gp_XYZ> vecValues;
636   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
637     // Match the name with the current word in the stream
638     if (theName) {
639       const Standard_Size aNameLen = strlen(theName);
640       if (strncmp (theBuffer.LinePtr, theName, aNameLen))
641         aStatus = VrmlData_VrmlFormatError;
642       else
643         theBuffer.LinePtr += aNameLen;
644     } else {
645       // Skip the word in the input
646       while (theBuffer.LinePtr[0] != ' ' &&
647              theBuffer.LinePtr[0] != ',' &&
648              theBuffer.LinePtr[0] != '\t' &&
649              theBuffer.LinePtr[0] != '\n' &&
650              theBuffer.LinePtr[0] != '\r' &&
651              theBuffer.LinePtr[0] != '\0')
652         theBuffer.LinePtr++;
653     }
654     // Read the body of the data node (list of triplets)
655     if (OK(aStatus) && OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
656       if (theBuffer.LinePtr[0] != '[')  // opening bracket
657         aStatus = VrmlData_VrmlFormatError;
658       else {
659         theBuffer.LinePtr++;
660         while (~0) {
661           gp_XYZ anXYZ;
662           if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
663             break;
664           // closing bracket, in case that it follows a comma
665           if (theBuffer.LinePtr[0] == ']') {
666             theBuffer.LinePtr++;
667             break;
668           }
669           // Read three numbers (XYZ value)
670           if (!OK(aStatus, Scene().ReadXYZ(theBuffer, anXYZ,
671                                            isScale, Standard_False)))
672             break;
673           vecValues.Append(anXYZ);
674           if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
675             break;
676           if (theBuffer.LinePtr[0] == ']') {// closing bracket
677             theBuffer.LinePtr++;
678             break;
679           }
680         }
681       }
682     if (OK(aStatus) && OK(aStatus, readBrace (theBuffer))) {
683       myLength = vecValues.Length();
684       if (myLength > 0) {
685         gp_XYZ * anArray = reinterpret_cast <gp_XYZ *>
686           (Scene().Allocator()->Allocate (myLength * sizeof(gp_XYZ)));
687         myArray = anArray;
688         for (Standard_Integer i = 0; i < Standard_Integer(myLength); i++)
689           anArray[i] = vecValues(i);
690       }
691     }
692   }
693   return aStatus;
694 }
695
696 //=======================================================================
697 //function : VrmlData_ArrayVec3d::WriteArray
698 //purpose  : 
699 //=======================================================================
700
701 VrmlData_ErrorStatus VrmlData_ArrayVec3d::WriteArray
702                                         (const char *           theName,
703                                          const Standard_Boolean isScale) const
704 {
705   VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
706   if (myLength > 0) {
707     aStatus = Scene().WriteLine (theName, "[", 2*GlobalIndent());
708     if (OK(aStatus)) {
709       for (Standard_Size i = 0; i < myLength-1; i++)
710         if (!OK (aStatus, Scene().WriteXYZ (myArray[i], isScale, ",")))
711           break;
712       if (OK(aStatus))
713         aStatus = Scene().WriteXYZ (myArray[myLength-1], isScale);
714     }
715     if (aStatus == VrmlData_StatusOK)
716       aStatus = Scene().WriteLine ("]", 0L, -2*GlobalIndent());
717   }
718   return aStatus;
719 }
720
721 //=======================================================================
722 //function : VrmlData_ArrayVec3d::IsDefault
723 //purpose  : 
724 //=======================================================================
725
726 Standard_Boolean VrmlData_ArrayVec3d::IsDefault () const
727 {
728   return myLength == 0;
729 }
730
731 //=======================================================================
732 //function : VrmlData_Coodinate::Clone
733 //purpose  : 
734 //=======================================================================
735
736 Handle(VrmlData_Node) VrmlData_Coordinate::Clone
737                                 (const Handle(VrmlData_Node)& theOther) const
738 {
739   Handle(VrmlData_Coordinate) aResult =
740     Handle(VrmlData_Coordinate)::DownCast (VrmlData_Node::Clone(theOther));
741   if (aResult.IsNull())
742     aResult = new VrmlData_Coordinate
743       (theOther.IsNull() ? Scene() : theOther->Scene(), Name());
744   if (&aResult->Scene() == &Scene())
745     aResult->SetValues (Length(), Values());
746   else {
747     aResult->AllocateValues (Length());
748     for (Standard_Size i = 0; i < Length(); i++)
749       const_cast <gp_XYZ&> (aResult->Values()[i]) = Values()[i];
750   }
751   return aResult;
752 }
753
754 //=======================================================================
755 //function : VrmlData_Coordinate::Read
756 //purpose  : 
757 //=======================================================================
758
759 VrmlData_ErrorStatus VrmlData_Coordinate::Read (VrmlData_InBuffer& theBuffer)
760 {
761   return VrmlData_ArrayVec3d::ReadArray (theBuffer, "point", Standard_True);
762 }
763
764 //=======================================================================
765 //function : VrmlData_Coordinate::Write
766 //purpose  : 
767 //=======================================================================
768
769 VrmlData_ErrorStatus VrmlData_Coordinate::Write (const char * thePrefix) const
770 {
771   static char header[] = "Coordinate {";
772   VrmlData_ErrorStatus aStatus;
773   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
774   {
775     WriteArray ("point", Standard_True);
776     aStatus = WriteClosing();
777   }
778   return aStatus;
779 }
780
781 //=======================================================================
782 //function : VrmlData_Color::Clone
783 //purpose  : 
784 //=======================================================================
785
786 Handle(VrmlData_Node) VrmlData_Color::Clone
787                                 (const Handle(VrmlData_Node)& theOther) const
788 {
789   Handle(VrmlData_Color) aResult =
790     Handle(VrmlData_Color)::DownCast (VrmlData_Node::Clone(theOther));
791   if (aResult.IsNull())
792     aResult = new VrmlData_Color(theOther.IsNull()? Scene() : theOther->Scene(),
793                                  Name());
794   if (&aResult->Scene() == &Scene())
795     aResult->SetValues (Length(), Values());
796   else {
797     aResult->AllocateValues (Length());
798     for (Standard_Size i = 0; i < Length(); i++)
799       const_cast <gp_XYZ&> (aResult->Values()[i]) = Values()[i];
800   }
801   return aResult;
802 }
803
804 //=======================================================================
805 //function : VrmlData_Color::Read
806 //purpose  : 
807 //=======================================================================
808
809 VrmlData_ErrorStatus VrmlData_Color::Read (VrmlData_InBuffer& theBuffer)
810 {
811   return ReadArray (theBuffer, "color", Standard_False);
812 }
813
814 //=======================================================================
815 //function : VrmlData_Color::Write
816 //purpose  : 
817 //=======================================================================
818
819 VrmlData_ErrorStatus VrmlData_Color::Write (const char * thePrefix) const
820 {
821   static char header[] = "Color {";
822   VrmlData_ErrorStatus aStatus;
823   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
824   {
825     WriteArray ("color", Standard_False);
826     aStatus = WriteClosing();
827   }
828   return aStatus;
829 }
830
831 //=======================================================================
832 //function : VrmlData_Normal::Clone
833 //purpose  : 
834 //=======================================================================
835
836 Handle(VrmlData_Node) VrmlData_Normal::Clone
837                                 (const Handle(VrmlData_Node)& theOther) const
838 {
839   Handle(VrmlData_Normal) aResult =
840     Handle(VrmlData_Normal)::DownCast (VrmlData_Node::Clone(theOther));
841   if (aResult.IsNull())
842     aResult= new VrmlData_Normal(theOther.IsNull()? Scene() : theOther->Scene(),
843                                  Name());
844   if (&aResult->Scene() == &Scene())
845     aResult->SetValues (Length(), Values());
846   else {
847     aResult->AllocateValues (Length());
848     for (Standard_Size i = 0; i < Length(); i++)
849       const_cast <gp_XYZ&> (aResult->Values()[i]) = Values()[i];
850   }
851   return aResult;
852 }
853
854 //=======================================================================
855 //function : VrmlData_Normal::Read
856 //purpose  : 
857 //=======================================================================
858
859 VrmlData_ErrorStatus VrmlData_Normal::Read (VrmlData_InBuffer& theBuffer)
860 {
861   return VrmlData_ArrayVec3d::ReadArray (theBuffer, "vector", Standard_False);
862 }
863
864 //=======================================================================
865 //function : VrmlData_Normal::Write
866 //purpose  : 
867 //=======================================================================
868
869 VrmlData_ErrorStatus VrmlData_Normal::Write (const char * thePrefix) const
870 {
871   static char header[] = "Normal {";
872   VrmlData_ErrorStatus aStatus;
873   if (OK (aStatus, Scene().WriteLine (thePrefix, header, GlobalIndent())))
874   {
875     WriteArray ("vector", Standard_False);
876     aStatus = WriteClosing();
877   }
878   return aStatus;
879 }