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