1 // File: VrmlData_Scene.cxx
2 // Created: 25.05.06 16:33:25
3 // Author: Alexander GRIGORIEV
4 // Copyright: Open Cascade 2006
6 #include <VrmlData_Scene.hxx>
7 #include <VrmlData_InBuffer.hxx>
8 #include <VrmlData_Appearance.hxx>
9 #include <VrmlData_Box.hxx>
10 #include <VrmlData_Color.hxx>
11 #include <VrmlData_Cone.hxx>
12 #include <VrmlData_Coordinate.hxx>
13 #include <VrmlData_Cylinder.hxx>
14 #include <VrmlData_DataMapOfShapeAppearance.hxx>
15 #include <VrmlData_Group.hxx>
16 #include <VrmlData_ImageTexture.hxx>
17 #include <VrmlData_InBuffer.hxx>
18 #include <VrmlData_IndexedFaceSet.hxx>
19 #include <VrmlData_IndexedLineSet.hxx>
20 #include <VrmlData_Material.hxx>
21 #include <VrmlData_Normal.hxx>
22 #include <VrmlData_Scene.hxx>
23 #include <VrmlData_ShapeNode.hxx>
24 #include <VrmlData_Sphere.hxx>
25 #include <VrmlData_TextureCoordinate.hxx>
26 #include <VrmlData_UnknownNode.hxx>
27 //#include <VrmlData_WorldInfo.hxx>
28 #include <NCollection_Vector.hxx>
29 #include <TopoDS_TFace.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <BRep_Builder.hxx>
34 #include <Precision.hxx>
37 #define _CRT_SECURE_NO_DEPRECATE
38 #pragma warning (disable:4996)
41 static void dumpNode (Standard_OStream& theStream,
42 const Handle(VrmlData_Node)& theNode,
43 const TCollection_AsciiString& theIndent);
45 static void dumpNodeHeader (Standard_OStream& theStream,
46 const TCollection_AsciiString& theIndent,
48 const char * theName);
50 //=======================================================================
51 //function : VrmlData_Scene
52 //purpose : Constructor
53 //=======================================================================
55 VrmlData_Scene::VrmlData_Scene
56 (const Handle(NCollection_IncAllocator)& theAlloc)
58 myStatus (VrmlData_StatusOK),
59 myAllocator (theAlloc.IsNull() ?
60 new NCollection_IncAllocator : theAlloc.operator->()),
67 myWorldInfo = new VrmlData_WorldInfo (* this);
68 myWorldInfo->AddInfo ("Created by OPEN CASCADE (tm) VrmlData API");
69 myLstNodes.Append (myWorldInfo);
70 myAllNodes.Append (myWorldInfo);
73 //=======================================================================
76 //=======================================================================
78 const Handle(VrmlData_Node)& VrmlData_Scene::AddNode
79 (const Handle(VrmlData_Node)& theN,
80 const Standard_Boolean isTopLevel)
82 if (theN.IsNull() == Standard_False)
83 if (theN->IsKind (STANDARD_TYPE(VrmlData_WorldInfo)) == Standard_False) {
85 const Handle(VrmlData_Node)& aNode =
86 myAllNodes.Append ((&theN->Scene()== this) ? theN : theN->Clone (NULL));
87 // Name is checked for uniqueness. If not, letter 'D' is appended until
88 // the name proves to be unique.
89 if (aNode->Name()[0] != '\0')
90 while (myNamedNodes.Add (aNode) == Standard_False)
91 aNode->setName (aNode->Name(), "D");
93 myLstNodes.Append (aNode);
97 static Handle(VrmlData_Node) aNullNode;
102 //=======================================================================
103 //function : operator <<
104 //purpose : Export to text stream (file or else)
105 //=======================================================================
107 Standard_OStream& operator << (Standard_OStream& theOutput,
108 const VrmlData_Scene& theScene)
110 VrmlData_Scene& aScene = const_cast <VrmlData_Scene&> (theScene);
111 aScene.myMutex.Lock();
112 aScene.myCurrentIndent = 0;
113 aScene.myLineError = 0;
114 aScene.myOutput = 0L;
115 aScene.myNamedNodesOut.Clear();
116 aScene.myUnnamedNodesOut.Clear();
117 aScene.myAutoNameCounter = 0;
121 VrmlData_Scene::Iterator anIterD(aScene.myLstNodes);
122 for (; anIterD.More(); anIterD.Next()) {
123 const Handle(VrmlData_Node)& aNode = anIterD.Value();
124 if (aNode.IsNull() == Standard_False) {
125 const VrmlData_ErrorStatus aStatus = aScene.WriteNode (0L, aNode);
126 if (aStatus != VrmlData_StatusOK &&
127 aStatus != VrmlData_NotImplemented)
132 aScene.myOutput = &theOutput;
133 aScene.myNamedNodesOut.Clear();
134 theOutput << "#VRML V2.0 utf8" << endl << endl;
138 VrmlData_Scene::Iterator anIter(aScene.myLstNodes);
139 for (; anIter.More(); anIter.Next()) {
140 const Handle(VrmlData_Node)& aNode = anIter.Value();
141 if (aNode.IsNull() == Standard_False) {
142 const VrmlData_ErrorStatus aStatus = aScene.WriteNode (0L, aNode);
143 if (aStatus != VrmlData_StatusOK &&
144 aStatus != VrmlData_NotImplemented)
148 aScene.myOutput = 0L;
149 aScene.myNamedNodesOut.Clear();
150 aScene.myUnnamedNodesOut.Clear();
151 aScene.myMutex.Unlock();
155 //=======================================================================
156 //function : SetVrmlDir
158 //=======================================================================
160 void VrmlData_Scene::SetVrmlDir (const TCollection_ExtendedString& theDir)
162 TCollection_ExtendedString& aDir = myVrmlDir.Append (theDir);
163 const Standard_ExtCharacter aTerminator = aDir.Value(aDir.Length());
164 if (aTerminator != Standard_ExtCharacter('\\') &&
165 aTerminator != Standard_ExtCharacter('/'))
167 aDir += TCollection_ExtendedString ("\\");
169 aDir += TCollection_ExtendedString ("/");
173 //=======================================================================
174 //function : WorldInfo
176 //=======================================================================
178 const Handle_VrmlData_WorldInfo& VrmlData_Scene::WorldInfo() const
183 //=======================================================================
184 //function : readLine
186 //=======================================================================
188 VrmlData_ErrorStatus VrmlData_Scene::readLine (VrmlData_InBuffer& theBuffer)
190 VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
191 if (theBuffer.Input.eof())
192 aStatus = VrmlData_EndOfFile;
194 theBuffer.Input.getline (theBuffer.Line, sizeof(theBuffer.Line));
195 theBuffer.LineCount++;
196 const int stat = theBuffer.Input.rdstate();
197 if (stat & ios::badbit)
198 aStatus = VrmlData_UnrecoverableError;
199 else if (stat & ios::failbit)
200 if (stat & ios::eofbit)
201 aStatus = VrmlData_EndOfFile;
203 aStatus = VrmlData_GeneralError;
204 theBuffer.LinePtr = &theBuffer.Line[0];
205 theBuffer.IsProcessed = Standard_False;
210 //=======================================================================
211 //function : ReadLine
213 //=======================================================================
215 VrmlData_ErrorStatus VrmlData_Scene::ReadLine (VrmlData_InBuffer& theBuffer)
217 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
219 while (aStatus == VrmlData_StatusOK) {
220 // Find the first significant character of the line
221 for (; * theBuffer.LinePtr != '\0'; theBuffer.LinePtr++) {
222 if (* theBuffer.LinePtr != ' ' && * theBuffer.LinePtr != '\t'
223 && * theBuffer.LinePtr != ',')
225 if (* theBuffer.LinePtr == '\n' || * theBuffer.LinePtr == '\r' ||
226 * theBuffer.LinePtr == '#')
227 // go requesting the next line
232 // the line is empty here (no significant characters). Read the next one.
233 aStatus = readLine (theBuffer);
236 // error or EOF detected
240 // Try to detect comment
241 if (theBuffer.IsProcessed == Standard_False) {
242 Standard_Boolean isQuoted (Standard_False);
243 Standard_Integer anOffset (0);
244 char * ptr = theBuffer.LinePtr;
245 for (; * ptr != '\0'; ptr++) {
247 * ptr = ptr[anOffset];
248 if (* ptr == '\n' || * ptr == '\r' || * ptr == '#') {
249 if (isQuoted == Standard_False) {
253 } else if (* ptr == '\\' && isQuoted)
254 ptr[0] = ptr[++anOffset];
255 else if (* ptr == '\"')
256 isQuoted = !isQuoted;
258 theBuffer.IsProcessed = Standard_True;
263 //=======================================================================
264 //function : readHeader
266 //=======================================================================
268 VrmlData_ErrorStatus VrmlData_Scene::readHeader (VrmlData_InBuffer& theBuffer)
270 VrmlData_ErrorStatus aStat = readLine (theBuffer);
271 if (aStat == VrmlData_StatusOK &&
272 !VRMLDATA_LCOMPARE(theBuffer.LinePtr, "#VRML V2.0"))
273 aStat = VrmlData_NotVrmlFile;
275 aStat = readLine(theBuffer);
279 //=======================================================================
280 //function : operator <<
281 //purpose : Import from text stream (file or else)
282 //=======================================================================
284 VrmlData_Scene& VrmlData_Scene::operator << (Standard_IStream& theInput)
286 VrmlData_InBuffer aBuffer (theInput);
288 // Read the VRML header
289 myStatus = readHeader (aBuffer);
290 const Handle(VrmlData_UnknownNode) aNullNode= new VrmlData_UnknownNode(*this);
291 // if (myStatus == StatusOK)
292 // myStatus = ReadLine (aBuffer);
293 // Read VRML data by nodes
295 if (!VrmlData_Node::OK(myStatus, ReadLine(aBuffer))) {
296 if (myStatus == VrmlData_EndOfFile)
297 myStatus = VrmlData_StatusOK;
300 // this line provides the method ReadNode in the present context
301 Handle(VrmlData_Node) aNode;
302 myStatus = aNullNode->ReadNode (aBuffer, aNode);
303 // Unknown nodes are not stored however they do not generate error
304 if (myStatus != VrmlData_StatusOK)
306 if (aNode.IsNull() == Standard_False /*&&
307 !aNode->IsKind (STANDARD_TYPE(VrmlData_UnknownNode))*/)
309 if (aNode->IsKind (STANDARD_TYPE(VrmlData_WorldInfo)) == Standard_False)
310 myLstNodes.Append (aNode);
311 else if (aNode->IsDefault() == Standard_False) {
312 const Handle(VrmlData_WorldInfo) aInfo =
313 Handle(VrmlData_WorldInfo)::DownCast (aNode);
314 myWorldInfo->SetTitle (aInfo->Title());
315 NCollection_List <const char *>::Iterator anIterInfo =
316 aInfo->InfoIterator();
317 for (; anIterInfo.More(); anIterInfo.Next())
318 myWorldInfo->AddInfo (anIterInfo.Value());
322 if (myStatus != VrmlData_StatusOK)
323 myLineError = aBuffer.LineCount;
328 //=======================================================================
329 //function : FindNode
331 //=======================================================================
333 Handle(VrmlData_Node) VrmlData_Scene::FindNode
334 (const char * theName,
335 const Handle(Standard_Type)& theType) const
337 Handle(VrmlData_Node) aResult;
339 Iterator anIter (myAllNodes);
340 for (; anIter.More(); anIter.Next())
341 if (!strcmp (anIter.Value()->Name(), theName)) {
342 aResult = anIter.Value();
343 if (theType.IsNull())
345 if (aResult->IsKind(theType))
350 const Handle(VrmlData_UnknownNode) aDummyNode = new VrmlData_UnknownNode;
351 aDummyNode->myName = theName;
352 if (myNamedNodes.Contains (aDummyNode))
353 aResult = const_cast<VrmlData_MapOfNode&>(myNamedNodes).Added(aDummyNode);
358 //=======================================================================
359 //function : FindNode
361 //=======================================================================
363 Handle(VrmlData_Node) VrmlData_Scene::FindNode
364 (const char * theName,
365 gp_Trsf& theLocation) const
368 Handle(VrmlData_Node) aResult;
369 Iterator anIter (myLstNodes);
370 for (; anIter.More(); anIter.Next()) {
371 const Handle(VrmlData_Node)& aNode = anIter.Value();
374 // Match a top-level node name
375 if (strcmp(aNode->Name(), theName) == 0) {
380 // Try a Group type of node
381 if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group)))
383 const Handle(VrmlData_Group) aGroup =
384 Handle(VrmlData_Group)::DownCast (aNode);
385 if (aGroup.IsNull() == Standard_False) {
386 aResult = aGroup->FindNode(theName, theLocation);
387 if (aResult.IsNull() == Standard_False)
395 //=======================================================================
396 //function : ReadWord
398 //=======================================================================
400 VrmlData_ErrorStatus VrmlData_Scene::ReadWord
401 (VrmlData_InBuffer& theBuffer,
402 TCollection_AsciiString& theWord)
404 VrmlData_ErrorStatus aStatus = ReadLine(theBuffer);
405 if (aStatus == VrmlData_StatusOK) {
406 char * ptr = theBuffer.LinePtr;
407 while (* ptr != '\0' && * ptr != '\n' && * ptr != '\r' &&
408 * ptr != ' ' && * ptr != '\t' && * ptr != '{' && * ptr != '}' &&
409 * ptr != ',' && * ptr != '[' && * ptr != ']')
411 const Standard_Integer aLen = Standard_Integer(ptr - theBuffer.LinePtr);
413 aStatus = VrmlData_StringInputError;
415 theWord = TCollection_AsciiString ((Standard_CString)theBuffer.LinePtr,
417 theBuffer.LinePtr = ptr;
423 //=======================================================================
424 //function : createNode
426 //=======================================================================
428 VrmlData_ErrorStatus VrmlData_Scene::createNode
429 (VrmlData_InBuffer& theBuffer,
430 Handle(VrmlData_Node)& theNode,
431 const Handle(Standard_Type)& theType)
433 VrmlData_ErrorStatus aStatus;
434 Handle(VrmlData_Node) aNode;
435 TCollection_AsciiString aName;
437 // Read the DEF token to assign the node name
438 if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
439 if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "DEF")) {
440 if (VrmlData_Node::OK(aStatus, ReadWord (theBuffer, aName)))
441 aStatus = ReadLine(theBuffer);
442 } else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "NULL")) {
447 const char * strName = aName.ToCString();
448 if (aStatus == VrmlData_StatusOK) {
449 // create the new node
450 if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Appearance"))
451 aNode = new VrmlData_Appearance (* this, strName);
452 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Shape"))
453 aNode = new VrmlData_ShapeNode (* this, strName);
454 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Box"))
455 aNode = new VrmlData_Box (* this, strName);
456 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Color"))
457 aNode = new VrmlData_Color (* this, strName);
458 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cone"))
459 aNode = new VrmlData_Cone (* this, strName);
460 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Coordinate")) {
461 aNode = new VrmlData_Coordinate (* this, strName);
463 // Check for "Coordinate3"
464 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "3"))
467 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cylinder"))
468 aNode = new VrmlData_Cylinder (* this, strName);
469 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Group"))
470 aNode = new VrmlData_Group (* this, strName,
472 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Transform"))
473 aNode = new VrmlData_Group (* this, strName,
475 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Inline"))
476 aNode = new VrmlData_Group (* this, strName,
478 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
479 aNode = new VrmlData_Group (* this, strName,
481 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Switch"))
482 aNode = new VrmlData_Group (* this, strName,
484 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ImageTexture"))
485 aNode = new VrmlData_ImageTexture (* this, strName);
486 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedFaceSet"))
487 aNode = new VrmlData_IndexedFaceSet (* this, strName);
488 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedLineSet"))
489 aNode = new VrmlData_IndexedLineSet (* this, strName);
490 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Material"))
491 aNode = new VrmlData_Material (* this, strName);
492 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Normal"))
493 aNode = new VrmlData_Normal (* this, strName);
494 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Sphere"))
495 aNode = new VrmlData_Sphere (* this, strName);
496 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "TextureCoordinate"))
497 aNode = new VrmlData_TextureCoordinate(* this, strName);
498 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "WorldInfo"))
499 aNode = new VrmlData_WorldInfo (* this, strName);
501 void * isProto = VRMLDATA_LCOMPARE(theBuffer.LinePtr, "PROTO");
502 TCollection_AsciiString aTitle;
503 aStatus = ReadWord (theBuffer, aTitle);
505 aStatus = ReadLine(theBuffer);
506 if (aStatus == VrmlData_StatusOK)
507 if (theBuffer.LinePtr[0] != '[')
508 aStatus = VrmlData_VrmlFormatError;
511 Standard_Integer aLevelCounter(0);
512 // This loop searches for any opening bracket '['.
513 // Such bracket increments the level counter. A closing bracket decrements
514 // the counter. The loop terminates when the counter becomes negative.
515 while (aLevelCounter >= 0 &&
516 (aStatus = ReadLine(theBuffer)) == VrmlData_StatusOK) {
518 while ((aChar = theBuffer.LinePtr[0]) != '\0') {
523 } else if (aChar == ']') {
531 if (aStatus == VrmlData_StatusOK)
532 aNode = new VrmlData_UnknownNode(* this,
537 aStatus = ReadLine(theBuffer);
538 if (aNode.IsNull() == Standard_False) {
539 if (aNode->Name()[0] != '\0')
540 myNamedNodes.Add (aNode);
541 if (theType.IsNull() == Standard_False)
542 if (aNode->IsKind(theType) == Standard_False)
543 aStatus = VrmlData_VrmlFormatError;
545 if (aStatus == VrmlData_StatusOK)
546 if (theBuffer.LinePtr[0] == '{') {
549 myAllNodes.Append(aNode);
551 aStatus = VrmlData_VrmlFormatError;
555 //=======================================================================
556 //function : operator TopoDS_Shape
558 //=======================================================================
560 VrmlData_Scene::operator TopoDS_Shape () const
563 VrmlData_Scene::createShape (aShape, myLstNodes, 0L);
567 //=======================================================================
568 //function : GetShape
570 //=======================================================================
572 TopoDS_Shape VrmlData_Scene::GetShape (VrmlData_DataMapOfShapeAppearance& aMap)
575 VrmlData_Scene::createShape (aShape, myLstNodes, &aMap);
579 //=======================================================================
580 //function : createShape
582 //=======================================================================
584 void VrmlData_Scene::createShape
585 (TopoDS_Shape& outShape,
586 const VrmlData_ListOfNode& lstNodes,
587 VrmlData_DataMapOfShapeAppearance* pMapShapeApp)
589 TopoDS_Shape aSingleShape; // used when there is a single ShapeNode
590 Standard_Boolean isSingleShape (Standard_True);
591 BRep_Builder aBuilder;
593 aBuilder.MakeCompound(TopoDS::Compound(outShape));
594 aSingleShape.Orientation(TopAbs_FORWARD);
596 Iterator anIter (lstNodes);
597 for (; anIter.More(); anIter.Next()) {
598 // Try a Shape type of node
599 const Handle(VrmlData_ShapeNode) aNodeShape =
600 Handle(VrmlData_ShapeNode)::DownCast (anIter.Value());
601 if (aNodeShape.IsNull() == Standard_False) {
602 const Handle(VrmlData_Geometry) aNodeGeom =
603 Handle(VrmlData_Geometry)::DownCast(aNodeShape->Geometry());
604 if (aNodeGeom.IsNull() == Standard_False) {
605 if (aSingleShape.IsNull() == Standard_False)
606 isSingleShape = Standard_False;
607 const Handle(TopoDS_TShape) aTShape = aNodeGeom->TShape();
608 aSingleShape.TShape(aTShape);
609 if (aSingleShape.IsNull() == Standard_False) {
610 aBuilder.Add (outShape, aSingleShape);
611 if (pMapShapeApp != 0L) {
612 const Handle(VrmlData_Appearance)& anAppearance =
613 aNodeShape->Appearance();
614 if (anAppearance.IsNull() == Standard_False) {
615 // Check if the current topology is a single face
616 if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
617 pMapShapeApp->Bind(aTShape, anAppearance);
619 // This is not a face, explode it in faces and bind each face
620 TopoDS_Shape aCurShape;
621 aCurShape.TShape(aTShape);
622 TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
623 for (; anExp.More(); anExp.Next()) {
624 const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
625 pMapShapeApp->Bind(aFace.TShape(), anAppearance);
634 // Try a Group type of node
635 const Handle(VrmlData_Group) aNodeGroup =
636 Handle(VrmlData_Group)::DownCast (anIter.Value());
637 if (aNodeGroup.IsNull() == Standard_False) {
639 aNodeGroup->Shape(aShape, pMapShapeApp);
640 if (aShape.IsNull() == Standard_False) {
641 aBuilder.Add (outShape, aShape);
642 isSingleShape = Standard_False;
647 outShape = aSingleShape;
650 //=======================================================================
651 //function : ReadReal
653 //=======================================================================
655 VrmlData_ErrorStatus VrmlData_Scene::ReadReal
656 (VrmlData_InBuffer& theBuffer,
657 Standard_Real& theResult,
658 Standard_Boolean isScale,
659 Standard_Boolean isOnlyPositive) const
661 Standard_Real aResult(0.);
662 VrmlData_ErrorStatus aStatus;
663 if (VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
665 aResult = strtod (theBuffer.LinePtr, &endptr);
666 if (endptr == theBuffer.LinePtr)
667 aStatus = VrmlData_NumericInputError;
668 else if (isOnlyPositive && aResult < 0.001*Precision::Confusion())
669 aStatus = VrmlData_IrrelevantNumber;
671 theResult = isScale ? (aResult * myLinearScale) : aResult;
672 theBuffer.LinePtr = endptr;
678 //=======================================================================
681 //=======================================================================
683 VrmlData_ErrorStatus VrmlData_Scene::ReadXYZ
684 (VrmlData_InBuffer& theBuffer,
686 Standard_Boolean isScale,
687 Standard_Boolean isOnlyPos) const
689 Standard_Real aVal[3] = {0., 0., 0.};
690 VrmlData_ErrorStatus aStatus;
691 for (Standard_Integer i = 0; i < 3; i++) {
692 if (!VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
695 aVal[i] = strtod (theBuffer.LinePtr, &endptr);
696 if (endptr == theBuffer.LinePtr) {
697 aStatus = VrmlData_NumericInputError;
700 if (isOnlyPos && aVal[i] < 0.001*Precision::Confusion()) {
701 aStatus = VrmlData_IrrelevantNumber;
704 theBuffer.LinePtr = endptr;
707 if (aStatus == VrmlData_StatusOK)
709 theXYZ.SetCoord (aVal[0] * myLinearScale,
710 aVal[1] * myLinearScale,
711 aVal[2] * myLinearScale);
713 theXYZ.SetCoord (aVal[0], aVal[1], aVal[2]);
717 //=======================================================================
720 //=======================================================================
722 VrmlData_ErrorStatus VrmlData_Scene::ReadXY
723 (VrmlData_InBuffer& theBuffer,
725 Standard_Boolean isScale,
726 Standard_Boolean isOnlyPos) const
728 Standard_Real aVal[2] = {0., 0.};
729 VrmlData_ErrorStatus aStatus;
730 for (Standard_Integer i = 0; i < 2; i++) {
731 if (!VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
734 aVal[i] = strtod (theBuffer.LinePtr, &endptr);
735 if (endptr == theBuffer.LinePtr) {
736 aStatus = VrmlData_NumericInputError;
739 if (isOnlyPos && aVal[i] < 0.001*Precision::Confusion()) {
740 aStatus = VrmlData_IrrelevantNumber;
743 theBuffer.LinePtr = endptr;
746 if (aStatus == VrmlData_StatusOK)
748 theXY.SetCoord (aVal[0] * myLinearScale, aVal[1] * myLinearScale);
750 theXY.SetCoord (aVal[0], aVal[1]);
754 //=======================================================================
755 //function : ReadArrIndex
756 //purpose : Read the body of the data node (comma-separated list of int
758 //=======================================================================
760 VrmlData_ErrorStatus VrmlData_Scene::ReadArrIndex
761 (VrmlData_InBuffer& theBuffer,
762 const Standard_Integer **& theArray,
763 Standard_Size& theNBlocks) const
765 VrmlData_ErrorStatus aStatus;
767 if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
768 if (theBuffer.LinePtr[0] != '[') // opening bracket
769 aStatus = VrmlData_VrmlFormatError;
772 NCollection_Vector<const Standard_Integer *> vecIndice;
773 NCollection_Vector<Standard_Integer> vecInt;
774 Standard_Boolean isMore (Standard_True);
777 // Loop reading integers from the stream
778 while (isMore && VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
780 // closing bracket, in case that it follows a comma
781 if (theBuffer.LinePtr[0] == ']') {
785 if (!VrmlData_Node::OK(aStatus, VrmlData_Node::ReadInteger(theBuffer,
788 // Check for valid delimiter (']' or ',')
789 if (!VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
791 if (theBuffer.LinePtr[0] == ']') {
793 isMore = Standard_False;
796 // The input value is a node index, store it in the buffer vector
797 vecInt.Append (static_cast<Standard_Integer> (anIntValue));
798 if ((anIntValue < 0 || isMore == Standard_False)
799 && vecInt.Length() > 0)
801 const Standard_Integer aLen = vecInt.Length();
802 // The input is the end-of-face, store and close this face
803 Standard_Integer * bufFace = static_cast <Standard_Integer *>
804 (myAllocator->Allocate((aLen+1) * sizeof(Standard_Integer)));
806 aStatus = VrmlData_UnrecoverableError;
810 for (Standard_Integer i = 0; i < aLen; i++)
811 bufFace[i+1] = vecInt(i);
813 vecIndice.Append(bufFace);
816 if (aStatus == VrmlData_StatusOK) {
817 const Standard_Size aNbBlocks =
818 static_cast <Standard_Size> (vecIndice.Length());
820 const Standard_Integer ** anArray =
821 static_cast <const Standard_Integer **>
822 (myAllocator->Allocate (aNbBlocks * sizeof(Standard_Integer *)));
824 aStatus = VrmlData_UnrecoverableError;
826 for (size_t i = 0; i < aNbBlocks; i++)
827 anArray[i] = vecIndice(i);
828 theNBlocks = aNbBlocks;
837 //=======================================================================
838 //function : writeArrIndex
840 //=======================================================================
842 VrmlData_ErrorStatus VrmlData_Scene::WriteArrIndex
843 (const char * thePrefix,
844 const Standard_Integer ** theArrIndex,
845 const Standard_Size theNbBlocks) const
847 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
848 if (theNbBlocks && (IsDummyWrite() == Standard_False)) {
849 if (VrmlData_Node::OK (aStatus,
850 WriteLine (thePrefix, "[", 1)))
852 const size_t aLineLimit = (myCurrentIndent < 41) ? 36 : 100;
854 for (Standard_Size iBlock = 0; iBlock < theNbBlocks; iBlock++) {
855 const Standard_Integer nVal (* theArrIndex[iBlock]);
856 const Standard_Integer * arrVal = theArrIndex[iBlock]+1;
859 sprintf (buf, "%d,", arrVal[0]);
862 sprintf (buf, "%d,%d,", arrVal[0], arrVal[1]);
865 sprintf (buf, "%d,%d,%d,", arrVal[0], arrVal[1], arrVal[2]);
868 sprintf (buf, "%d,%d,%d,%d,",
869 arrVal[0], arrVal[1], arrVal[2], arrVal[3]);
873 char * ptr = &buf[0];
874 for (Standard_Integer i = 0; i < nVal; i++) {
875 sprintf (ptr, "%d,", arrVal[i]);
876 ptr = strchr (ptr, ',') + 1;
877 if ((ptr - &buf[0]) > (ptrdiff_t)aLineLimit) {
884 WriteLine (buf, iBlock < theNbBlocks-1 ? "-1," : "-1");
886 if (aStatus == VrmlData_StatusOK)
887 aStatus = WriteLine ("]", 0L, -1);
893 //=======================================================================
894 //function : WriteXYZ
896 //=======================================================================
898 VrmlData_ErrorStatus VrmlData_Scene::WriteXYZ
899 (const gp_XYZ& theXYZ,
900 const Standard_Boolean isApplyScale,
901 const char * thePostfix) const
904 if (IsDummyWrite() == Standard_False)
905 if (isApplyScale && myLinearScale > Precision::Confusion())
906 sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X() / myLinearScale,
907 theXYZ.Y() / myLinearScale, theXYZ.Z() / myLinearScale,
908 thePostfix ? thePostfix : "");
910 sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X(), theXYZ.Y(), theXYZ.Z(),
911 thePostfix ? thePostfix : "");
912 return WriteLine (buf);
915 //=======================================================================
916 //function : WriteLine
917 //purpose : write the given string prepending the current indentation
918 //=======================================================================
920 VrmlData_ErrorStatus VrmlData_Scene::WriteLine
921 (const char * theLin0,
922 const char * theLin1,
923 const Standard_Integer theIndent) const
925 static const char spaces[] = " "
927 VrmlData_ErrorStatus& aStatus =
928 const_cast <VrmlData_ErrorStatus&> (myStatus);
930 aStatus = VrmlData_StatusOK;
932 Standard_Integer& aCurrentIndent =
933 const_cast <Standard_Integer&> (myCurrentIndent);
935 aCurrentIndent -= myIndent;
936 if (aCurrentIndent < 0)
938 if (theLin0 == 0L && theLin1 == 0L)
939 (* myOutput) << endl;
941 const Standard_Integer nSpaces = Min (aCurrentIndent, sizeof(spaces)-1);
942 (* myOutput) << &spaces[sizeof(spaces)-1 - nSpaces];
944 (* myOutput) << theLin0;
946 (* myOutput) << ' ' << theLin1;
948 (* myOutput) << theLin1;
949 (* myOutput) << endl;
951 const int stat = myOutput->rdstate();
952 if (stat & ios::badbit)
953 aStatus = VrmlData_UnrecoverableError;
954 else if (stat & ios::failbit)
955 // if (stat & ios::eofbit)
956 // aStatus = VrmlData_EndOfFile;
958 aStatus = VrmlData_GeneralError;
960 aCurrentIndent += myIndent;
965 //=======================================================================
966 //function : WriteNode
968 //=======================================================================
970 VrmlData_ErrorStatus VrmlData_Scene::WriteNode
971 (const char * thePrefix,
972 const Handle(VrmlData_Node)& theNode) const
974 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
975 Standard_Boolean isNoName (Standard_False);
976 if (theNode->Name() == 0L)
977 isNoName = Standard_True;
978 else if (theNode->Name()[0] == '\0')
979 isNoName = Standard_True;
981 if (theNode.IsNull() == Standard_False)
982 if (theNode->IsDefault() == Standard_False) {
983 if (isNoName && IsDummyWrite()) {
984 // We are in a tentative 'write' session (nothing is written).
985 // The goal is to identify multiply referred nodes.
986 Standard_Address addrNode = theNode.operator->();
987 if (!const_cast<NCollection_Map<Standard_Address>&>(myUnnamedNodesOut)
990 Handle(VrmlData_UnknownNode) bidNode = new VrmlData_UnknownNode;
994 ++const_cast<Standard_Integer&>(myAutoNameCounter));
995 bidNode->myName = &buf[0];
996 } while (myNamedNodes.Contains (bidNode));
997 // We found the vacant automatic name, let us assign to it.
998 theNode->setName (&buf[0]);
999 const_cast<VrmlData_MapOfNode&>(myNamedNodes).Add (theNode);
1000 return aStatus; // do not search under already duplicated node
1004 aStatus = theNode->Write (thePrefix);
1006 // If the node name consists of blank characters, we do not write it
1007 const char * nptr = theNode->Name();
1008 for (; * nptr != '\0'; nptr++)
1009 if (* nptr != ' ' && * nptr != '\t')
1012 aStatus = theNode->Write (thePrefix);
1014 // Name is written under DEF clause
1015 char buf[1024], * ptr;
1016 if (myNamedNodesOut.Contains (theNode)) {
1017 memcpy (buf, "USE ", 4);
1018 strncpy (&buf[4], theNode->Name(), sizeof(buf)-5);
1019 aStatus = WriteLine (thePrefix, buf);
1022 strncpy (buf, thePrefix, sizeof(buf));
1023 ptr = strchr (buf, '\0');
1027 strcpy (ptr, "DEF ");
1028 strncpy (ptr+4, theNode->Name(), &buf[sizeof(buf)] - (ptr+5));
1029 aStatus = theNode->Write (buf);
1030 const_cast<VrmlData_MapOfNode&>(myNamedNodesOut).Add (theNode);
1038 //=======================================================================
1041 //=======================================================================
1043 void VrmlData_Scene::Dump (Standard_OStream& theStream) const
1045 theStream << " ===== Diagnostic Dump of a Scene (" << myAllNodes.Extent()
1046 << " nodes)" << endl;
1049 Iterator anIterA(myAllNodes);
1050 for (; anIterA.More(); anIterA.Next())
1051 dumpNode(theStream, anIterA.Value(), "");
1053 Iterator anIter(myLstNodes);
1054 for (; anIter.More(); anIter.Next())
1055 dumpNode(theStream, anIter.Value(), " ");
1058 //=======================================================================
1059 //function : dumpNode
1060 //purpose : static (local) function
1061 //=======================================================================
1063 void dumpNode (Standard_OStream& theStream,
1064 const Handle(VrmlData_Node)& theNode,
1065 const TCollection_AsciiString& theIndent)
1067 if (theNode.IsNull())
1069 TCollection_AsciiString aNewIndent =
1070 theIndent.IsEmpty() ? theIndent : theIndent + " ";
1071 if (theNode->IsKind(STANDARD_TYPE(VrmlData_Appearance))) {
1072 const Handle(VrmlData_Appearance) anAppearance =
1073 Handle(VrmlData_Appearance)::DownCast (theNode);
1074 dumpNodeHeader (theStream, theIndent, "Appearance", theNode->Name());
1075 if (theIndent.IsEmpty() == Standard_False) {
1076 dumpNode (theStream, anAppearance->Material(), aNewIndent);
1077 dumpNode (theStream, anAppearance->Texture(), aNewIndent);
1078 dumpNode (theStream, anAppearance->TextureTransform(), aNewIndent);
1080 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_ShapeNode))) {
1081 const Handle(VrmlData_ShapeNode) aShape =
1082 Handle(VrmlData_ShapeNode)::DownCast (theNode);
1083 dumpNodeHeader (theStream, theIndent, "Shape", theNode->Name());
1084 if (theIndent.IsEmpty() == Standard_False) {
1085 dumpNode (theStream, aShape->Appearance(), aNewIndent);
1086 dumpNode (theStream, aShape->Geometry(), aNewIndent);
1088 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Box)))
1089 dumpNodeHeader (theStream, theIndent, "Box", theNode->Name());
1090 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Cylinder)))
1091 dumpNodeHeader (theStream, theIndent, "Cylinder", theNode->Name());
1092 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Sphere)))
1093 dumpNodeHeader (theStream, theIndent, "Sphere", theNode->Name());
1094 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Cone)))
1095 dumpNodeHeader (theStream, theIndent, "Cone", theNode->Name());
1096 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Coordinate)))
1097 dumpNodeHeader (theStream, theIndent, "Coordinate", theNode->Name());
1098 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Group))) {
1099 const Handle(VrmlData_Group) aGroup =
1100 Handle(VrmlData_Group)::DownCast (theNode);
1102 sprintf (buf, "Group (%s)",
1103 aGroup->IsTransform() ? "Transform" : "Group");
1104 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1105 if (theIndent.IsEmpty() == Standard_False) {
1106 VrmlData_ListOfNode::Iterator anIter = aGroup->NodeIterator();
1107 for (; anIter.More(); anIter.Next())
1108 dumpNode (theStream, anIter.Value(), aNewIndent);
1110 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_ImageTexture)))
1111 dumpNodeHeader (theStream, theIndent, "ImageTexture", theNode->Name());
1112 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_IndexedFaceSet))) {
1113 const Handle(VrmlData_IndexedFaceSet) aNode =
1114 Handle(VrmlData_IndexedFaceSet)::DownCast(theNode);
1115 const Standard_Integer ** ppDummy;
1116 const Standard_Size nCoord = aNode->Coordinates()->Length();
1117 const Standard_Size nPoly = aNode->Polygons (ppDummy);
1119 sprintf (buf, "IndexedFaceSet (%d vertices, %d polygons)", nCoord, nPoly);
1120 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1121 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_IndexedLineSet))) {
1122 const Handle(VrmlData_IndexedLineSet) aNode =
1123 Handle(VrmlData_IndexedLineSet)::DownCast(theNode);
1124 const Standard_Integer ** ppDummy;
1125 const Standard_Size nCoord = aNode->Coordinates()->Length();
1126 const Standard_Size nPoly = aNode->Polygons (ppDummy);
1128 sprintf (buf, "IndexedLineSet (%d vertices, %d polygons)", nCoord, nPoly);
1129 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1130 } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Material))) {
1131 // const Handle(VrmlData_Material) aMaterial =
1132 // Handle(VrmlData_Material)::DownCast (theNode);
1133 dumpNodeHeader (theStream, theIndent, "Material", theNode->Name());
1135 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Normal)))
1136 dumpNodeHeader (theStream, theIndent, "Normal", theNode->Name());
1137 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_TextureCoordinate)))
1138 dumpNodeHeader (theStream, theIndent, "TextureCoordinate", theNode->Name());
1139 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
1140 dumpNodeHeader (theStream, theIndent, "WorldInfo", theNode->Name());
1141 else if (theNode->IsKind(STANDARD_TYPE(VrmlData_UnknownNode))) {
1142 const Handle(VrmlData_UnknownNode) anUnknown =
1143 Handle(VrmlData_UnknownNode)::DownCast (theNode);
1145 sprintf (buf, "Unknown (%s)", anUnknown->GetTitle().ToCString());
1146 dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
1150 //=======================================================================
1151 //function : dumpNodeHeader
1153 //=======================================================================
1155 void dumpNodeHeader (Standard_OStream& theStream,
1156 const TCollection_AsciiString& theIndent,
1157 const char * theType,
1158 const char * theName)
1160 theStream << theIndent << theType <<" node";
1161 if (theName[0] == '\0')
1164 theStream << ": \"" << theName << '\"' << endl;