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