0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / VrmlData / VrmlData_Scene.cxx
CommitLineData
b311480e 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
7fd59977 20#include <VrmlData_Scene.hxx>
21#include <VrmlData_InBuffer.hxx>
22#include <VrmlData_Appearance.hxx>
23#include <VrmlData_Box.hxx>
24#include <VrmlData_Color.hxx>
25#include <VrmlData_Cone.hxx>
26#include <VrmlData_Coordinate.hxx>
27#include <VrmlData_Cylinder.hxx>
28#include <VrmlData_DataMapOfShapeAppearance.hxx>
29#include <VrmlData_Group.hxx>
30#include <VrmlData_ImageTexture.hxx>
31#include <VrmlData_InBuffer.hxx>
32#include <VrmlData_IndexedFaceSet.hxx>
33#include <VrmlData_IndexedLineSet.hxx>
34#include <VrmlData_Material.hxx>
35#include <VrmlData_Normal.hxx>
36#include <VrmlData_Scene.hxx>
37#include <VrmlData_ShapeNode.hxx>
38#include <VrmlData_Sphere.hxx>
39#include <VrmlData_TextureCoordinate.hxx>
40#include <VrmlData_UnknownNode.hxx>
41//#include <VrmlData_WorldInfo.hxx>
42#include <NCollection_Vector.hxx>
43#include <TopoDS_TFace.hxx>
44#include <TopoDS.hxx>
45#include <TopoDS_Face.hxx>
46#include <TopExp_Explorer.hxx>
47#include <BRep_Builder.hxx>
48#include <Precision.hxx>
49
50#ifdef WNT
51#define _CRT_SECURE_NO_DEPRECATE
52#pragma warning (disable:4996)
53#endif
54
55static void dumpNode (Standard_OStream& theStream,
56 const Handle(VrmlData_Node)& theNode,
57 const TCollection_AsciiString& theIndent);
58
59static void dumpNodeHeader (Standard_OStream& theStream,
60 const TCollection_AsciiString& theIndent,
61 const char * theType,
62 const char * theName);
63
64//=======================================================================
65//function : VrmlData_Scene
66//purpose : Constructor
67//=======================================================================
68
69VrmlData_Scene::VrmlData_Scene
70 (const Handle(NCollection_IncAllocator)& theAlloc)
71 : myLinearScale (1.),
72 myStatus (VrmlData_StatusOK),
73 myAllocator (theAlloc.IsNull() ?
74 new NCollection_IncAllocator : theAlloc.operator->()),
75 myLineError (0),
76 myOutput (0L),
77 myIndent (2),
78 myCurrentIndent (0),
79 myAutoNameCounter (0)
80{
81 myWorldInfo = new VrmlData_WorldInfo (* this);
82 myWorldInfo->AddInfo ("Created by OPEN CASCADE (tm) VrmlData API");
83 myLstNodes.Append (myWorldInfo);
84 myAllNodes.Append (myWorldInfo);
85}
86
87//=======================================================================
88//function : AddNode
89//purpose :
90//=======================================================================
91
92const Handle(VrmlData_Node)& VrmlData_Scene::AddNode
93 (const Handle(VrmlData_Node)& theN,
94 const Standard_Boolean isTopLevel)
95{
96 if (theN.IsNull() == Standard_False)
97 if (theN->IsKind (STANDARD_TYPE(VrmlData_WorldInfo)) == Standard_False) {
98 myMutex.Lock();
99 const Handle(VrmlData_Node)& aNode =
100 myAllNodes.Append ((&theN->Scene()== this) ? theN : theN->Clone (NULL));
101 // Name is checked for uniqueness. If not, letter 'D' is appended until
102 // the name proves to be unique.
103 if (aNode->Name()[0] != '\0')
104 while (myNamedNodes.Add (aNode) == Standard_False)
105 aNode->setName (aNode->Name(), "D");
106 if (isTopLevel)
107 myLstNodes.Append (aNode);
108 myMutex.Unlock();
109 return aNode;
110 }
111 static Handle(VrmlData_Node) aNullNode;
112 aNullNode.Nullify();
113 return aNullNode;
114}
115
116//=======================================================================
117//function : operator <<
118//purpose : Export to text stream (file or else)
119//=======================================================================
120
121Standard_OStream& operator << (Standard_OStream& theOutput,
122 const VrmlData_Scene& theScene)
123{
124 VrmlData_Scene& aScene = const_cast <VrmlData_Scene&> (theScene);
125 aScene.myMutex.Lock();
126 aScene.myCurrentIndent = 0;
127 aScene.myLineError = 0;
128 aScene.myOutput = 0L;
129 aScene.myNamedNodesOut.Clear();
130 aScene.myUnnamedNodesOut.Clear();
131 aScene.myAutoNameCounter = 0;
132
133 // Dummy write
134
135 VrmlData_Scene::Iterator anIterD(aScene.myLstNodes);
136 for (; anIterD.More(); anIterD.Next()) {
137 const Handle(VrmlData_Node)& aNode = anIterD.Value();
138 if (aNode.IsNull() == Standard_False) {
139 const VrmlData_ErrorStatus aStatus = aScene.WriteNode (0L, aNode);
140 if (aStatus != VrmlData_StatusOK &&
141 aStatus != VrmlData_NotImplemented)
142 break;
143 }
144 }
145
146 aScene.myOutput = &theOutput;
147 aScene.myNamedNodesOut.Clear();
148 theOutput << "#VRML V2.0 utf8" << endl << endl;
149
150 // Real write
151
152 VrmlData_Scene::Iterator anIter(aScene.myLstNodes);
153 for (; anIter.More(); anIter.Next()) {
154 const Handle(VrmlData_Node)& aNode = anIter.Value();
155 if (aNode.IsNull() == Standard_False) {
156 const VrmlData_ErrorStatus aStatus = aScene.WriteNode (0L, aNode);
157 if (aStatus != VrmlData_StatusOK &&
158 aStatus != VrmlData_NotImplemented)
159 break;
160 }
161 }
162 aScene.myOutput = 0L;
163 aScene.myNamedNodesOut.Clear();
164 aScene.myUnnamedNodesOut.Clear();
165 aScene.myMutex.Unlock();
166 return theOutput;
167}
168
169//=======================================================================
170//function : SetVrmlDir
171//purpose :
172//=======================================================================
173
174void VrmlData_Scene::SetVrmlDir (const TCollection_ExtendedString& theDir)
175{
176 TCollection_ExtendedString& aDir = myVrmlDir.Append (theDir);
177 const Standard_ExtCharacter aTerminator = aDir.Value(aDir.Length());
178 if (aTerminator != Standard_ExtCharacter('\\') &&
179 aTerminator != Standard_ExtCharacter('/'))
180#ifdef WNT
181 aDir += TCollection_ExtendedString ("\\");
182#else
183 aDir += TCollection_ExtendedString ("/");
184#endif
185}
186
187//=======================================================================
188//function : WorldInfo
189//purpose :
190//=======================================================================
191
192const Handle_VrmlData_WorldInfo& VrmlData_Scene::WorldInfo() const
193{
194 return myWorldInfo;
195}
196
197//=======================================================================
198//function : readLine
199//purpose :
200//=======================================================================
201
202VrmlData_ErrorStatus VrmlData_Scene::readLine (VrmlData_InBuffer& theBuffer)
203{
204 VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
205 if (theBuffer.Input.eof())
206 aStatus = VrmlData_EndOfFile;
207 else {
208 theBuffer.Input.getline (theBuffer.Line, sizeof(theBuffer.Line));
209 theBuffer.LineCount++;
210 const int stat = theBuffer.Input.rdstate();
eafb234b 211 if (stat & ios::badbit) {
7fd59977 212 aStatus = VrmlData_UnrecoverableError;
eafb234b 213 }
214 else if (stat & ios::failbit) {
215 if (stat & ios::eofbit) {
7fd59977 216 aStatus = VrmlData_EndOfFile;
eafb234b 217 }
218 else {
7fd59977 219 aStatus = VrmlData_GeneralError;
eafb234b 220 }
221 }
7fd59977 222 theBuffer.LinePtr = &theBuffer.Line[0];
223 theBuffer.IsProcessed = Standard_False;
224 }
225 return aStatus;
226}
227
228//=======================================================================
229//function : ReadLine
230//purpose :
231//=======================================================================
232
233VrmlData_ErrorStatus VrmlData_Scene::ReadLine (VrmlData_InBuffer& theBuffer)
234{
235 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
236
237 while (aStatus == VrmlData_StatusOK) {
238 // Find the first significant character of the line
239 for (; * theBuffer.LinePtr != '\0'; theBuffer.LinePtr++) {
240 if (* theBuffer.LinePtr != ' ' && * theBuffer.LinePtr != '\t'
241 && * theBuffer.LinePtr != ',')
242 {
243 if (* theBuffer.LinePtr == '\n' || * theBuffer.LinePtr == '\r' ||
244 * theBuffer.LinePtr == '#')
245 // go requesting the next line
246 break;
247 goto nonempty_line;
248 }
249 }
250 // the line is empty here (no significant characters). Read the next one.
251 aStatus = readLine (theBuffer);
252 }
253
254 // error or EOF detected
255 return aStatus;
256
257 nonempty_line:
258 // Try to detect comment
259 if (theBuffer.IsProcessed == Standard_False) {
260 Standard_Boolean isQuoted (Standard_False);
261 Standard_Integer anOffset (0);
262 char * ptr = theBuffer.LinePtr;
263 for (; * ptr != '\0'; ptr++) {
264 if (anOffset)
265 * ptr = ptr[anOffset];
266 if (* ptr == '\n' || * ptr == '\r' || * ptr == '#') {
267 if (isQuoted == Standard_False) {
268 * ptr = '\0';
269 break;
270 }
271 } else if (* ptr == '\\' && isQuoted)
272 ptr[0] = ptr[++anOffset];
273 else if (* ptr == '\"')
274 isQuoted = !isQuoted;
275 }
276 theBuffer.IsProcessed = Standard_True;
277 }
278 return aStatus;
279}
280
281//=======================================================================
282//function : readHeader
283//purpose :
284//=======================================================================
285
286VrmlData_ErrorStatus VrmlData_Scene::readHeader (VrmlData_InBuffer& theBuffer)
287{
288 VrmlData_ErrorStatus aStat = readLine (theBuffer);
289 if (aStat == VrmlData_StatusOK &&
290 !VRMLDATA_LCOMPARE(theBuffer.LinePtr, "#VRML V2.0"))
291 aStat = VrmlData_NotVrmlFile;
292 else
293 aStat = readLine(theBuffer);
294 return aStat;
295}
296
297//=======================================================================
298//function : operator <<
299//purpose : Import from text stream (file or else)
300//=======================================================================
301
302VrmlData_Scene& VrmlData_Scene::operator << (Standard_IStream& theInput)
303{
304 VrmlData_InBuffer aBuffer (theInput);
305 myMutex.Lock();
306 // Read the VRML header
307 myStatus = readHeader (aBuffer);
308 const Handle(VrmlData_UnknownNode) aNullNode= new VrmlData_UnknownNode(*this);
309// if (myStatus == StatusOK)
310// myStatus = ReadLine (aBuffer);
311 // Read VRML data by nodes
302f96fb 312 for(;;) {
7fd59977 313 if (!VrmlData_Node::OK(myStatus, ReadLine(aBuffer))) {
314 if (myStatus == VrmlData_EndOfFile)
315 myStatus = VrmlData_StatusOK;
316 break;
317 }
318 // this line provides the method ReadNode in the present context
319 Handle(VrmlData_Node) aNode;
320 myStatus = aNullNode->ReadNode (aBuffer, aNode);
321 // Unknown nodes are not stored however they do not generate error
322 if (myStatus != VrmlData_StatusOK)
323 break;
324 if (aNode.IsNull() == Standard_False /*&&
325 !aNode->IsKind (STANDARD_TYPE(VrmlData_UnknownNode))*/)
326 {
327 if (aNode->IsKind (STANDARD_TYPE(VrmlData_WorldInfo)) == Standard_False)
328 myLstNodes.Append (aNode);
329 else if (aNode->IsDefault() == Standard_False) {
330 const Handle(VrmlData_WorldInfo) aInfo =
331 Handle(VrmlData_WorldInfo)::DownCast (aNode);
332 myWorldInfo->SetTitle (aInfo->Title());
333 NCollection_List <const char *>::Iterator anIterInfo =
334 aInfo->InfoIterator();
335 for (; anIterInfo.More(); anIterInfo.Next())
336 myWorldInfo->AddInfo (anIterInfo.Value());
337 }
338 }
339 }
340 if (myStatus != VrmlData_StatusOK)
341 myLineError = aBuffer.LineCount;
342 myMutex.Unlock();
343 return * this;
344}
345
346//=======================================================================
347//function : FindNode
348//purpose :
349//=======================================================================
350
351Handle(VrmlData_Node) VrmlData_Scene::FindNode
352 (const char * theName,
35e08fe8 353 const Handle(Standard_Type)& /*theType*/) const
7fd59977 354{
355 Handle(VrmlData_Node) aResult;
356#ifdef USE_LIST_API
357 Iterator anIter (myAllNodes);
358 for (; anIter.More(); anIter.Next())
359 if (!strcmp (anIter.Value()->Name(), theName)) {
360 aResult = anIter.Value();
361 if (theType.IsNull())
362 break;
363 if (aResult->IsKind(theType))
364 break;
365 aResult.Nullify();
366 }
367#else
368 const Handle(VrmlData_UnknownNode) aDummyNode = new VrmlData_UnknownNode;
369 aDummyNode->myName = theName;
370 if (myNamedNodes.Contains (aDummyNode))
371 aResult = const_cast<VrmlData_MapOfNode&>(myNamedNodes).Added(aDummyNode);
372#endif
373 return aResult;
374}
375
376//=======================================================================
377//function : FindNode
378//purpose :
379//=======================================================================
380
381Handle(VrmlData_Node) VrmlData_Scene::FindNode
382 (const char * theName,
383 gp_Trsf& theLocation) const
384{
385 gp_Trsf aLoc;
386 Handle(VrmlData_Node) aResult;
387 Iterator anIter (myLstNodes);
388 for (; anIter.More(); anIter.Next()) {
389 const Handle(VrmlData_Node)& aNode = anIter.Value();
390 if (aNode.IsNull())
391 continue;
392 // Match a top-level node name
393 if (strcmp(aNode->Name(), theName) == 0) {
394 aResult = aNode;
395 theLocation = aLoc;
396 break;
397 }
398 // Try a Group type of node
399 if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group)))
400 {
401 const Handle(VrmlData_Group) aGroup =
402 Handle(VrmlData_Group)::DownCast (aNode);
403 if (aGroup.IsNull() == Standard_False) {
404 aResult = aGroup->FindNode(theName, theLocation);
405 if (aResult.IsNull() == Standard_False)
406 break;
407 }
408 }
409 }
410 return aResult;
411}
412
413//=======================================================================
414//function : ReadWord
415//purpose :
416//=======================================================================
417
418VrmlData_ErrorStatus VrmlData_Scene::ReadWord
419 (VrmlData_InBuffer& theBuffer,
420 TCollection_AsciiString& theWord)
421{
422 VrmlData_ErrorStatus aStatus = ReadLine(theBuffer);
423 if (aStatus == VrmlData_StatusOK) {
424 char * ptr = theBuffer.LinePtr;
425 while (* ptr != '\0' && * ptr != '\n' && * ptr != '\r' &&
426 * ptr != ' ' && * ptr != '\t' && * ptr != '{' && * ptr != '}' &&
427 * ptr != ',' && * ptr != '[' && * ptr != ']')
428 ptr++;
429 const Standard_Integer aLen = Standard_Integer(ptr - theBuffer.LinePtr);
430 if (aLen <= 0)
431 aStatus = VrmlData_StringInputError;
432 else {
433 theWord = TCollection_AsciiString ((Standard_CString)theBuffer.LinePtr,
434 aLen);
435 theBuffer.LinePtr = ptr;
436 }
437 }
438 return aStatus;
439}
440
441//=======================================================================
442//function : createNode
443//purpose :
444//=======================================================================
445
446VrmlData_ErrorStatus VrmlData_Scene::createNode
447 (VrmlData_InBuffer& theBuffer,
448 Handle(VrmlData_Node)& theNode,
449 const Handle(Standard_Type)& theType)
450{
451 VrmlData_ErrorStatus aStatus;
452 Handle(VrmlData_Node) aNode;
453 TCollection_AsciiString aName;
7fd59977 454
455 // Read the DEF token to assign the node name
eafb234b 456 if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer))) {
7fd59977 457 if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "DEF")) {
458 if (VrmlData_Node::OK(aStatus, ReadWord (theBuffer, aName)))
459 aStatus = ReadLine(theBuffer);
460 } else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "NULL")) {
461 theNode.Nullify();
462 return aStatus;
463 }
eafb234b 464 }
7fd59977 465
466 const char * strName = aName.ToCString();
467 if (aStatus == VrmlData_StatusOK) {
468 // create the new node
469 if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Appearance"))
470 aNode = new VrmlData_Appearance (* this, strName);
471 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Shape"))
472 aNode = new VrmlData_ShapeNode (* this, strName);
473 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Box"))
474 aNode = new VrmlData_Box (* this, strName);
475 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Color"))
476 aNode = new VrmlData_Color (* this, strName);
477 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cone"))
478 aNode = new VrmlData_Cone (* this, strName);
bd754989 479 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Coordinate")) {
7fd59977 480 aNode = new VrmlData_Coordinate (* this, strName);
bd754989
V
481
482 // Check for "Coordinate3"
483 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "3"))
484 theBuffer.LinePtr++;
485 }
7fd59977 486 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cylinder"))
487 aNode = new VrmlData_Cylinder (* this, strName);
488 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Group"))
489 aNode = new VrmlData_Group (* this, strName,
490 Standard_False);
491 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Transform"))
492 aNode = new VrmlData_Group (* this, strName,
493 Standard_True);
494 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Inline"))
495 aNode = new VrmlData_Group (* this, strName,
496 Standard_False);
bd754989
V
497 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
498 aNode = new VrmlData_Group (* this, strName,
499 Standard_False);
500 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Switch"))
501 aNode = new VrmlData_Group (* this, strName,
502 Standard_False);
7fd59977 503 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ImageTexture"))
504 aNode = new VrmlData_ImageTexture (* this, strName);
505 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedFaceSet"))
506 aNode = new VrmlData_IndexedFaceSet (* this, strName);
507 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedLineSet"))
508 aNode = new VrmlData_IndexedLineSet (* this, strName);
509 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Material"))
510 aNode = new VrmlData_Material (* this, strName);
511 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Normal"))
512 aNode = new VrmlData_Normal (* this, strName);
513 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Sphere"))
514 aNode = new VrmlData_Sphere (* this, strName);
515 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "TextureCoordinate"))
516 aNode = new VrmlData_TextureCoordinate(* this, strName);
517 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "WorldInfo"))
518 aNode = new VrmlData_WorldInfo (* this, strName);
519 else {
520 void * isProto = VRMLDATA_LCOMPARE(theBuffer.LinePtr, "PROTO");
521 TCollection_AsciiString aTitle;
522 aStatus = ReadWord (theBuffer, aTitle);
523 if (isProto) {
524 aStatus = ReadLine(theBuffer);
eafb234b 525 if (aStatus == VrmlData_StatusOK) {
7fd59977 526 if (theBuffer.LinePtr[0] != '[')
527 aStatus = VrmlData_VrmlFormatError;
528 else {
529 theBuffer.LinePtr++;
530 Standard_Integer aLevelCounter(0);
531 // This loop searches for any opening bracket '['.
532 // Such bracket increments the level counter. A closing bracket decrements
533 // the counter. The loop terminates when the counter becomes negative.
534 while (aLevelCounter >= 0 &&
535 (aStatus = ReadLine(theBuffer)) == VrmlData_StatusOK) {
536 int aChar;
537 while ((aChar = theBuffer.LinePtr[0]) != '\0') {
538 theBuffer.LinePtr++;
539 if (aChar == '[') {
540 aLevelCounter++;
541 break;
542 } else if (aChar == ']') {
543 aLevelCounter--;
544 break;
545 }
546 }
547 }
548 }
eafb234b 549 }
7fd59977 550 }
551 if (aStatus == VrmlData_StatusOK)
552 aNode = new VrmlData_UnknownNode(* this,
553 strName,
554 aTitle.ToCString());
555 }
556 }
557 aStatus = ReadLine(theBuffer);
558 if (aNode.IsNull() == Standard_False) {
eafb234b 559 if (aNode->Name()[0] != '\0')
7fd59977 560 myNamedNodes.Add (aNode);
561 if (theType.IsNull() == Standard_False)
562 if (aNode->IsKind(theType) == Standard_False)
563 aStatus = VrmlData_VrmlFormatError;
7fd59977 564 }
eafb234b 565 if (aStatus == VrmlData_StatusOK) {
7fd59977 566 if (theBuffer.LinePtr[0] == '{') {
567 theBuffer.LinePtr++;
568 theNode = aNode;
569 myAllNodes.Append(aNode);
eafb234b 570 } else {
7fd59977 571 aStatus = VrmlData_VrmlFormatError;
eafb234b 572 }
573 }
7fd59977 574 return aStatus;
575}
576
577//=======================================================================
578//function : operator TopoDS_Shape
579//purpose :
580//=======================================================================
581
582VrmlData_Scene::operator TopoDS_Shape () const
583{
584 TopoDS_Shape aShape;
585 VrmlData_Scene::createShape (aShape, myLstNodes, 0L);
586 return aShape;
587}
588
589//=======================================================================
590//function : GetShape
591//purpose :
592//=======================================================================
593
594TopoDS_Shape VrmlData_Scene::GetShape (VrmlData_DataMapOfShapeAppearance& aMap)
595{
596 TopoDS_Shape aShape;
597 VrmlData_Scene::createShape (aShape, myLstNodes, &aMap);
598 return aShape;
599}
600
601//=======================================================================
602//function : createShape
603//purpose :
604//=======================================================================
605
606void VrmlData_Scene::createShape
607 (TopoDS_Shape& outShape,
608 const VrmlData_ListOfNode& lstNodes,
609 VrmlData_DataMapOfShapeAppearance* pMapShapeApp)
610{
611 TopoDS_Shape aSingleShape; // used when there is a single ShapeNode
612 Standard_Boolean isSingleShape (Standard_True);
613 BRep_Builder aBuilder;
614 outShape.Nullify();
615 aBuilder.MakeCompound(TopoDS::Compound(outShape));
616 aSingleShape.Orientation(TopAbs_FORWARD);
617
618 Iterator anIter (lstNodes);
619 for (; anIter.More(); anIter.Next()) {
620 // Try a Shape type of node
621 const Handle(VrmlData_ShapeNode) aNodeShape =
622 Handle(VrmlData_ShapeNode)::DownCast (anIter.Value());
623 if (aNodeShape.IsNull() == Standard_False) {
624 const Handle(VrmlData_Geometry) aNodeGeom =
625 Handle(VrmlData_Geometry)::DownCast(aNodeShape->Geometry());
626 if (aNodeGeom.IsNull() == Standard_False) {
627 if (aSingleShape.IsNull() == Standard_False)
628 isSingleShape = Standard_False;
629 const Handle(TopoDS_TShape) aTShape = aNodeGeom->TShape();
630 aSingleShape.TShape(aTShape);
bd754989 631 if (aSingleShape.IsNull() == Standard_False) {
7fd59977 632 aBuilder.Add (outShape, aSingleShape);
bd754989
V
633 if (pMapShapeApp != 0L) {
634 const Handle(VrmlData_Appearance)& anAppearance =
635 aNodeShape->Appearance();
636 if (anAppearance.IsNull() == Standard_False) {
637 // Check if the current topology is a single face
638 if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
639 pMapShapeApp->Bind(aTShape, anAppearance);
640 else {
641 // This is not a face, explode it in faces and bind each face
642 TopoDS_Shape aCurShape;
643 aCurShape.TShape(aTShape);
644 TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
645 for (; anExp.More(); anExp.Next()) {
646 const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
647 pMapShapeApp->Bind(aFace.TShape(), anAppearance);
648 }
7fd59977 649 }
650 }
651 }
652 }
653 }
654 continue;
655 }
656 // Try a Group type of node
657 const Handle(VrmlData_Group) aNodeGroup =
658 Handle(VrmlData_Group)::DownCast (anIter.Value());
659 if (aNodeGroup.IsNull() == Standard_False) {
660 TopoDS_Shape aShape;
661 aNodeGroup->Shape(aShape, pMapShapeApp);
662 if (aShape.IsNull() == Standard_False) {
663 aBuilder.Add (outShape, aShape);
664 isSingleShape = Standard_False;
665 }
666 }
667 }
668 if (isSingleShape)
669 outShape = aSingleShape;
670}
671
672//=======================================================================
673//function : ReadReal
674//purpose :
675//=======================================================================
676
677VrmlData_ErrorStatus VrmlData_Scene::ReadReal
678 (VrmlData_InBuffer& theBuffer,
679 Standard_Real& theResult,
680 Standard_Boolean isScale,
681 Standard_Boolean isOnlyPositive) const
682{
683 Standard_Real aResult(0.);
684 VrmlData_ErrorStatus aStatus;
685 if (VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
686 char * endptr;
91322f44 687 aResult = Strtod (theBuffer.LinePtr, &endptr);
7fd59977 688 if (endptr == theBuffer.LinePtr)
689 aStatus = VrmlData_NumericInputError;
690 else if (isOnlyPositive && aResult < 0.001*Precision::Confusion())
691 aStatus = VrmlData_IrrelevantNumber;
692 else {
693 theResult = isScale ? (aResult * myLinearScale) : aResult;
694 theBuffer.LinePtr = endptr;
695 }
696 }
697 return aStatus;
698}
699
700//=======================================================================
701//function : ReadXYZ
702//purpose :
703//=======================================================================
704
705VrmlData_ErrorStatus VrmlData_Scene::ReadXYZ
706 (VrmlData_InBuffer& theBuffer,
707 gp_XYZ& theXYZ,
708 Standard_Boolean isScale,
709 Standard_Boolean isOnlyPos) const
710{
711 Standard_Real aVal[3] = {0., 0., 0.};
1d47d8d0 712 VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
7fd59977 713 for (Standard_Integer i = 0; i < 3; i++) {
714 if (!VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
715 break;
716 char * endptr;
91322f44 717 aVal[i] = Strtod (theBuffer.LinePtr, &endptr);
7fd59977 718 if (endptr == theBuffer.LinePtr) {
719 aStatus = VrmlData_NumericInputError;
720 break;
721 } else {
722 if (isOnlyPos && aVal[i] < 0.001*Precision::Confusion()) {
723 aStatus = VrmlData_IrrelevantNumber;
724 break;
725 }
726 theBuffer.LinePtr = endptr;
727 }
728 }
eafb234b 729 if (aStatus == VrmlData_StatusOK) {
730 if (isScale) {
7fd59977 731 theXYZ.SetCoord (aVal[0] * myLinearScale,
732 aVal[1] * myLinearScale,
733 aVal[2] * myLinearScale);
eafb234b 734 }
735 else {
7fd59977 736 theXYZ.SetCoord (aVal[0], aVal[1], aVal[2]);
eafb234b 737 }
738 }
7fd59977 739 return aStatus;
740}
741
742//=======================================================================
743//function : ReadXY
744//purpose :
745//=======================================================================
746
747VrmlData_ErrorStatus VrmlData_Scene::ReadXY
748 (VrmlData_InBuffer& theBuffer,
749 gp_XY& theXY,
750 Standard_Boolean isScale,
751 Standard_Boolean isOnlyPos) const
752{
753 Standard_Real aVal[2] = {0., 0.};
1d47d8d0 754 VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
7fd59977 755 for (Standard_Integer i = 0; i < 2; i++) {
756 if (!VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
757 break;
758 char * endptr;
91322f44 759 aVal[i] = Strtod (theBuffer.LinePtr, &endptr);
7fd59977 760 if (endptr == theBuffer.LinePtr) {
761 aStatus = VrmlData_NumericInputError;
762 break;
763 } else {
764 if (isOnlyPos && aVal[i] < 0.001*Precision::Confusion()) {
765 aStatus = VrmlData_IrrelevantNumber;
766 break;
767 }
768 theBuffer.LinePtr = endptr;
769 }
770 }
eafb234b 771 if (aStatus == VrmlData_StatusOK) {
7fd59977 772 if (isScale)
773 theXY.SetCoord (aVal[0] * myLinearScale, aVal[1] * myLinearScale);
774 else
775 theXY.SetCoord (aVal[0], aVal[1]);
eafb234b 776 }
7fd59977 777 return aStatus;
778}
779
780//=======================================================================
781//function : ReadArrIndex
782//purpose : Read the body of the data node (comma-separated list of int
783// multiplets)
784//=======================================================================
785
786VrmlData_ErrorStatus VrmlData_Scene::ReadArrIndex
787 (VrmlData_InBuffer& theBuffer,
788 const Standard_Integer **& theArray,
789 Standard_Size& theNBlocks) const
790{
791 VrmlData_ErrorStatus aStatus;
792 theNBlocks = 0;
eafb234b 793 if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer))) {
7fd59977 794 if (theBuffer.LinePtr[0] != '[') // opening bracket
795 aStatus = VrmlData_VrmlFormatError;
796 else {
797 theBuffer.LinePtr++;
798 NCollection_Vector<const Standard_Integer *> vecIndice;
799 NCollection_Vector<Standard_Integer> vecInt;
800 Standard_Boolean isMore (Standard_True);
801 long anIntValue;
802
803 // Loop reading integers from the stream
804 while (isMore && VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
805 {
806 // closing bracket, in case that it follows a comma
807 if (theBuffer.LinePtr[0] == ']') {
808 theBuffer.LinePtr++;
809 break;
810 }
811 if (!VrmlData_Node::OK(aStatus, VrmlData_Node::ReadInteger(theBuffer,
812 anIntValue)))
813 break;
814 // Check for valid delimiter (']' or ',')
815 if (!VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
816 break;
817 if (theBuffer.LinePtr[0] == ']') {
818 theBuffer.LinePtr++;
819 isMore = Standard_False;
820 }
821 if (anIntValue >= 0)
822 // The input value is a node index, store it in the buffer vector
823 vecInt.Append (static_cast<Standard_Integer> (anIntValue));
824 if ((anIntValue < 0 || isMore == Standard_False)
825 && vecInt.Length() > 0)
826 {
827 const Standard_Integer aLen = vecInt.Length();
828 // The input is the end-of-face, store and close this face
829 Standard_Integer * bufFace = static_cast <Standard_Integer *>
830 (myAllocator->Allocate((aLen+1) * sizeof(Standard_Integer)));
831 if (bufFace == 0L) {
832 aStatus = VrmlData_UnrecoverableError;
833 break;
834 }
835 bufFace[0] = aLen;
836 for (Standard_Integer i = 0; i < aLen; i++)
837 bufFace[i+1] = vecInt(i);
838 vecInt.Clear();
839 vecIndice.Append(bufFace);
840 }
841 }
842 if (aStatus == VrmlData_StatusOK) {
843 const Standard_Size aNbBlocks =
844 static_cast <Standard_Size> (vecIndice.Length());
845 if (aNbBlocks) {
846 const Standard_Integer ** anArray =
847 static_cast <const Standard_Integer **>
848 (myAllocator->Allocate (aNbBlocks * sizeof(Standard_Integer *)));
849 if (anArray == 0L)
850 aStatus = VrmlData_UnrecoverableError;
851 else {
852 for (size_t i = 0; i < aNbBlocks; i++)
60be1f9b 853 anArray[i] = vecIndice((Standard_Integer)i);
7fd59977 854 theNBlocks = aNbBlocks;
855 theArray = anArray;
856 }
857 }
858 }
859 }
eafb234b 860 }
7fd59977 861 return aStatus;
862}
863
864//=======================================================================
865//function : writeArrIndex
866//purpose :
867//=======================================================================
868
869VrmlData_ErrorStatus VrmlData_Scene::WriteArrIndex
870 (const char * thePrefix,
871 const Standard_Integer ** theArrIndex,
872 const Standard_Size theNbBlocks) const
873{
874 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
875 if (theNbBlocks && (IsDummyWrite() == Standard_False)) {
876 if (VrmlData_Node::OK (aStatus,
877 WriteLine (thePrefix, "[", 1)))
878 {
879 const size_t aLineLimit = (myCurrentIndent < 41) ? 36 : 100;
880 char buf[256];
881 for (Standard_Size iBlock = 0; iBlock < theNbBlocks; iBlock++) {
882 const Standard_Integer nVal (* theArrIndex[iBlock]);
883 const Standard_Integer * arrVal = theArrIndex[iBlock]+1;
884 switch (nVal) {
885 case 1:
91322f44 886 Sprintf (buf, "%d,", arrVal[0]);
7fd59977 887 break;
888 case 2:
91322f44 889 Sprintf (buf, "%d,%d,", arrVal[0], arrVal[1]);
7fd59977 890 break;
891 case 3:
91322f44 892 Sprintf (buf, "%d,%d,%d,", arrVal[0], arrVal[1], arrVal[2]);
7fd59977 893 break;
894 case 4:
91322f44 895 Sprintf (buf, "%d,%d,%d,%d,",
7fd59977 896 arrVal[0], arrVal[1], arrVal[2], arrVal[3]);
897 break;
898 default:
899 if (nVal > 0) {
900 char * ptr = &buf[0];
901 for (Standard_Integer i = 0; i < nVal; i++) {
91322f44 902 Sprintf (ptr, "%d,", arrVal[i]);
7fd59977 903 ptr = strchr (ptr, ',') + 1;
904 if ((ptr - &buf[0]) > (ptrdiff_t)aLineLimit) {
905 WriteLine(buf);
906 ptr = &buf[0];
907 }
908 }
909 }
910 }
911 WriteLine (buf, iBlock < theNbBlocks-1 ? "-1," : "-1");
912 }
913 if (aStatus == VrmlData_StatusOK)
914 aStatus = WriteLine ("]", 0L, -1);
915 }
916 }
917 return aStatus;
918}
919
920//=======================================================================
921//function : WriteXYZ
922//purpose :
923//=======================================================================
924
925VrmlData_ErrorStatus VrmlData_Scene::WriteXYZ
926 (const gp_XYZ& theXYZ,
927 const Standard_Boolean isApplyScale,
928 const char * thePostfix) const
929{
930 char buf[240];
eafb234b 931 if (IsDummyWrite() == Standard_False) {
7fd59977 932 if (isApplyScale && myLinearScale > Precision::Confusion())
91322f44 933 Sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X() / myLinearScale,
7fd59977 934 theXYZ.Y() / myLinearScale, theXYZ.Z() / myLinearScale,
935 thePostfix ? thePostfix : "");
936 else
91322f44 937 Sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X(), theXYZ.Y(), theXYZ.Z(),
7fd59977 938 thePostfix ? thePostfix : "");
eafb234b 939 }
7fd59977 940 return WriteLine (buf);
941}
942
943//=======================================================================
944//function : WriteLine
945//purpose : write the given string prepending the current indentation
946//=======================================================================
947
948VrmlData_ErrorStatus VrmlData_Scene::WriteLine
949 (const char * theLin0,
950 const char * theLin1,
951 const Standard_Integer theIndent) const
952{
953 static const char spaces[] = " "
954 " ";
955 VrmlData_ErrorStatus& aStatus =
956 const_cast <VrmlData_ErrorStatus&> (myStatus);
957 if (IsDummyWrite())
958 aStatus = VrmlData_StatusOK;
959 else {
960 Standard_Integer& aCurrentIndent =
961 const_cast <Standard_Integer&> (myCurrentIndent);
962 if (theIndent < 0)
963 aCurrentIndent -= myIndent;
964 if (aCurrentIndent < 0)
965 aCurrentIndent = 0;
966 if (theLin0 == 0L && theLin1 == 0L)
967 (* myOutput) << endl;
968 else {
969 const Standard_Integer nSpaces = Min (aCurrentIndent, sizeof(spaces)-1);
970 (* myOutput) << &spaces[sizeof(spaces)-1 - nSpaces];
971 if (theLin0) {
972 (* myOutput) << theLin0;
973 if (theLin1)
974 (* myOutput) << ' ' << theLin1;
975 } else
976 (* myOutput) << theLin1;
977 (* myOutput) << endl;
978 }
979 const int stat = myOutput->rdstate();
980 if (stat & ios::badbit)
981 aStatus = VrmlData_UnrecoverableError;
982 else if (stat & ios::failbit)
983// if (stat & ios::eofbit)
984// aStatus = VrmlData_EndOfFile;
985// else
986 aStatus = VrmlData_GeneralError;
987 if (theIndent > 0)
988 aCurrentIndent += myIndent;
989 }
990 return myStatus;
991}
992
993//=======================================================================
994//function : WriteNode
995//purpose :
996//=======================================================================
997
998VrmlData_ErrorStatus VrmlData_Scene::WriteNode
999 (const char * thePrefix,
1000 const Handle(VrmlData_Node)& theNode) const
1001{
1002 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
1003 Standard_Boolean isNoName (Standard_False);
1004 if (theNode->Name() == 0L)
1005 isNoName = Standard_True;
1006 else if (theNode->Name()[0] == '\0')
1007 isNoName = Standard_True;
1008
1009 if (theNode.IsNull() == Standard_False)
1010 if (theNode->IsDefault() == Standard_False) {
1011 if (isNoName && IsDummyWrite()) {
1012 // We are in a tentative 'write' session (nothing is written).
1013 // The goal is to identify multiply referred nodes.
1014 Standard_Address addrNode = theNode.operator->();
1015 if (!const_cast<NCollection_Map<Standard_Address>&>(myUnnamedNodesOut)
1016 .Add (addrNode))
1017 {
1018 Handle(VrmlData_UnknownNode) bidNode = new VrmlData_UnknownNode;
1019 char buf[32];
1020 do {
91322f44 1021 Sprintf (buf, "_%d",
7fd59977 1022 ++const_cast<Standard_Integer&>(myAutoNameCounter));
1023 bidNode->myName = &buf[0];
1024 } while (myNamedNodes.Contains (bidNode));
1025 // We found the vacant automatic name, let us assign to it.
1026 theNode->setName (&buf[0]);
1027 const_cast<VrmlData_MapOfNode&>(myNamedNodes).Add (theNode);
1028 return aStatus; // do not search under already duplicated node
1029 }
1030 }
1031 if (isNoName)
1032 aStatus = theNode->Write (thePrefix);
1033 else {
1034 // If the node name consists of blank characters, we do not write it
1035 const char * nptr = theNode->Name();
1036 for (; * nptr != '\0'; nptr++)
1037 if (* nptr != ' ' && * nptr != '\t')
1038 break;
1039 if (* nptr == '\0')
1040 aStatus = theNode->Write (thePrefix);
1041 else {
1042 // Name is written under DEF clause
b6710675 1043 TCollection_AsciiString buf;
1044 if (myNamedNodesOut.Contains (theNode))
1045 {
1046 buf += "USE ";
1047 buf += theNode->Name();
1048 aStatus = WriteLine (thePrefix, buf.ToCString());
1049 }
1050 else
1051 {
1052 if (thePrefix)
1053 {
1054 buf += thePrefix;
1055 buf += ' ';
1056 }
1057 buf += "DEF ";
1058 buf += theNode->Name();
1059 aStatus = theNode->Write (buf.ToCString());
7fd59977 1060 const_cast<VrmlData_MapOfNode&>(myNamedNodesOut).Add (theNode);
1061 }
1062 }
1063 }
1064 }
1065 return aStatus;
1066}
1067
1068//=======================================================================
1069//function : Dump
1070//purpose :
1071//=======================================================================
1072
1073void VrmlData_Scene::Dump (Standard_OStream& theStream) const
1074{
1075 theStream << " ===== Diagnostic Dump of a Scene (" << myAllNodes.Extent()
1076 << " nodes)" << endl;
1077
1078 /*
1079 Iterator anIterA(myAllNodes);
1080 for (; anIterA.More(); anIterA.Next())
1081 dumpNode(theStream, anIterA.Value(), "");
1082 */
1083 Iterator anIter(myLstNodes);
1084 for (; anIter.More(); anIter.Next())
1085 dumpNode(theStream, anIter.Value(), " ");
1086}
1087
1088//=======================================================================
1089//function : dumpNode
1090//purpose : static (local) function
1091//=======================================================================
1092
1093void dumpNode (Standard_OStream& theStream,
1094 const Handle(VrmlData_Node)& theNode,
1095 const TCollection_AsciiString& theIndent)
1096{
1097 if (theNode.IsNull())
1098 return;
1099 TCollection_AsciiString aNewIndent =
1100 theIndent.IsEmpty() ? theIndent : theIndent + " ";
1101 if (theNode->IsKind(STANDARD_TYPE(VrmlData_Appearance))) {
1102 const Handle(VrmlData_Appearance) anAppearance =
1103 Handle(VrmlData_Appearance)::DownCast (theNode);
1104 dumpNodeHeader (theStream, theIndent, "Appearance", theNode->Name());
1105 if (theIndent.IsEmpty() == Standard_False) {
1106 dumpNode (theStream, anAppearance->Material(), aNewIndent);
1107 dumpNode (theStream, anAppearance->Texture(), aNewIndent);
1108 dumpNode (theStream, anAppearance->TextureTransform(), aNewIndent);
1109 }
1110 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_ShapeNode))) {
1111 const Handle(VrmlData_ShapeNode) aShape =
1112 Handle(VrmlData_ShapeNode)::DownCast (theNode);
1113 dumpNodeHeader (theStream, theIndent, "Shape", theNode->Name());
1114 if (theIndent.IsEmpty() == Standard_False) {
1115 dumpNode (theStream, aShape->Appearance(), aNewIndent);
1116 dumpNode (theStream, aShape->Geometry(), aNewIndent);
1117 }
1118 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Box)))
1119 dumpNodeHeader (theStream, theIndent, "Box", theNode->Name());
1120 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Cylinder)))
1121 dumpNodeHeader (theStream, theIndent, "Cylinder", theNode->Name());
1122 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Sphere)))
1123 dumpNodeHeader (theStream, theIndent, "Sphere", theNode->Name());
1124 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Cone)))
1125 dumpNodeHeader (theStream, theIndent, "Cone", theNode->Name());
1126 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Coordinate)))
1127 dumpNodeHeader (theStream, theIndent, "Coordinate", theNode->Name());
1128 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Group))) {
1129 const Handle(VrmlData_Group) aGroup =
1130 Handle(VrmlData_Group)::DownCast (theNode);
1131 char buf[64];
91322f44 1132 Sprintf (buf, "Group (%s)",
7fd59977 1133 aGroup->IsTransform() ? "Transform" : "Group");
1134 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1135 if (theIndent.IsEmpty() == Standard_False) {
1136 VrmlData_ListOfNode::Iterator anIter = aGroup->NodeIterator();
1137 for (; anIter.More(); anIter.Next())
1138 dumpNode (theStream, anIter.Value(), aNewIndent);
1139 }
1140 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_ImageTexture)))
1141 dumpNodeHeader (theStream, theIndent, "ImageTexture", theNode->Name());
1142 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_IndexedFaceSet))) {
1143 const Handle(VrmlData_IndexedFaceSet) aNode =
1144 Handle(VrmlData_IndexedFaceSet)::DownCast(theNode);
1145 const Standard_Integer ** ppDummy;
1146 const Standard_Size nCoord = aNode->Coordinates()->Length();
1147 const Standard_Size nPoly = aNode->Polygons (ppDummy);
64531d9c 1148 char buf[80];
1149 Sprintf (buf, "IndexedFaceSet (%" PRIuPTR " vertices, %" PRIuPTR " polygons)",
1150 nCoord, nPoly);
1151
7fd59977 1152 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1153 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_IndexedLineSet))) {
1154 const Handle(VrmlData_IndexedLineSet) aNode =
1155 Handle(VrmlData_IndexedLineSet)::DownCast(theNode);
1156 const Standard_Integer ** ppDummy;
1157 const Standard_Size nCoord = aNode->Coordinates()->Length();
1158 const Standard_Size nPoly = aNode->Polygons (ppDummy);
64531d9c 1159
1160 char buf[80];
1161 Sprintf(buf, "IndexedLineSet (%" PRIuPTR " vertices, %" PRIuPTR " polygons)",
1162 nCoord, nPoly);
1163
7fd59977 1164 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1165 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Material))) {
1166// const Handle(VrmlData_Material) aMaterial =
1167// Handle(VrmlData_Material)::DownCast (theNode);
1168 dumpNodeHeader (theStream, theIndent, "Material", theNode->Name());
1169 }
1170 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Normal)))
1171 dumpNodeHeader (theStream, theIndent, "Normal", theNode->Name());
1172 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_TextureCoordinate)))
1173 dumpNodeHeader (theStream, theIndent, "TextureCoordinate", theNode->Name());
1174 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
1175 dumpNodeHeader (theStream, theIndent, "WorldInfo", theNode->Name());
1176 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_UnknownNode))) {
1177 const Handle(VrmlData_UnknownNode) anUnknown =
1178 Handle(VrmlData_UnknownNode)::DownCast (theNode);
1179 char buf[64];
91322f44 1180 Sprintf (buf, "Unknown (%s)", anUnknown->GetTitle().ToCString());
7fd59977 1181 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1182 }
1183}
1184
1185//=======================================================================
1186//function : dumpNodeHeader
1187//purpose :
1188//=======================================================================
1189
1190void dumpNodeHeader (Standard_OStream& theStream,
1191 const TCollection_AsciiString& theIndent,
1192 const char * theType,
1193 const char * theName)
1194{
1195 theStream << theIndent << theType <<" node";
1196 if (theName[0] == '\0')
1197 theStream << endl;
1198 else
1199 theStream << ": \"" << theName << '\"' << endl;
1200}