0025740: VrmlData_Scene::WriteArrIndex() writes extra point indices.
[occt.git] / src / VrmlData / VrmlData_Scene.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 69914bb..ff57177
@@ -1,7 +1,17 @@
-// File:      VrmlData_Scene.cxx
-// Created:   25.05.06 16:33:25
-// Author:    Alexander GRIGORIEV
-// Copyright: Open Cascade 2006
+// Created on: 2006-05-25
+// Created by: Alexander GRIGORIEV
+// Copyright (c) 2006-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <VrmlData_Scene.hxx>
 #include <VrmlData_InBuffer.hxx>
@@ -32,6 +42,7 @@
 #include <TopExp_Explorer.hxx>
 #include <BRep_Builder.hxx>
 #include <Precision.hxx>
+#include <Standard_Version.hxx>
 
 #ifdef WNT
 #define _CRT_SECURE_NO_DEPRECATE
@@ -65,7 +76,8 @@ VrmlData_Scene::VrmlData_Scene
     myAutoNameCounter (0)
 {
   myWorldInfo = new VrmlData_WorldInfo (* this);
-  myWorldInfo->AddInfo ("Created by OPEN CASCADE (tm) VrmlData API");
+  Standard_CString anInfo = "Generated by Open CASCADE Technology " OCC_VERSION_STRING;
+  myWorldInfo->AddInfo (anInfo);
   myLstNodes.Append (myWorldInfo);
   myAllNodes.Append (myWorldInfo);
 }
@@ -175,7 +187,7 @@ void VrmlData_Scene::SetVrmlDir (const TCollection_ExtendedString& theDir)
 //purpose  : 
 //=======================================================================
 
-const Handle_VrmlData_WorldInfo& VrmlData_Scene::WorldInfo() const
+const Handle(VrmlData_WorldInfo)& VrmlData_Scene::WorldInfo() const
 {
   return myWorldInfo;
 }
@@ -194,13 +206,17 @@ VrmlData_ErrorStatus VrmlData_Scene::readLine (VrmlData_InBuffer& theBuffer)
     theBuffer.Input.getline (theBuffer.Line, sizeof(theBuffer.Line));
     theBuffer.LineCount++;
     const int stat = theBuffer.Input.rdstate();
-    if (stat & ios::badbit)
+    if (stat & ios::badbit) {
       aStatus = VrmlData_UnrecoverableError;
-    else if (stat & ios::failbit)
-      if (stat & ios::eofbit)
+    }
+    else if (stat & ios::failbit) {
+      if (stat & ios::eofbit) {
         aStatus = VrmlData_EndOfFile;
-      else
+      }
+      else {
         aStatus = VrmlData_GeneralError;
+      }
+    }
     theBuffer.LinePtr = &theBuffer.Line[0];
     theBuffer.IsProcessed = Standard_False;
   }
@@ -291,7 +307,7 @@ VrmlData_Scene& VrmlData_Scene::operator << (Standard_IStream& theInput)
 //   if (myStatus == StatusOK)
 //     myStatus = ReadLine (aBuffer);
   // Read VRML data by nodes
-  while (~0) {
+  for(;;) {
     if (!VrmlData_Node::OK(myStatus, ReadLine(aBuffer))) {
       if (myStatus == VrmlData_EndOfFile)
         myStatus = VrmlData_StatusOK;
@@ -332,7 +348,7 @@ VrmlData_Scene& VrmlData_Scene::operator << (Standard_IStream& theInput)
 
 Handle(VrmlData_Node) VrmlData_Scene::FindNode
                                 (const char                   * theName,
-                                 const Handle(Standard_Type)& theType) const
+                                 const Handle(Standard_Type)& /*theType*/) const
 {
   Handle(VrmlData_Node) aResult;
 #ifdef USE_LIST_API
@@ -433,10 +449,9 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
   VrmlData_ErrorStatus    aStatus;
   Handle(VrmlData_Node)   aNode;
   TCollection_AsciiString aName;
-  Standard_Boolean        isReused (Standard_False);
 
   // Read the DEF token to assign the node name
-  if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
+  if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer))) {
     if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "DEF")) {
       if (VrmlData_Node::OK(aStatus, ReadWord (theBuffer, aName)))
         aStatus = ReadLine(theBuffer);
@@ -444,6 +459,7 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
       theNode.Nullify();
       return aStatus;
     }
+  }
 
   const char * strName = aName.ToCString();
   if (aStatus == VrmlData_StatusOK) {
@@ -458,8 +474,13 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
       aNode = new VrmlData_Color          (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cone"))
       aNode = new VrmlData_Cone           (* this, strName);
-    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Coordinate"))
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Coordinate")) {
       aNode = new VrmlData_Coordinate     (* this, strName);
+      
+      // Check for "Coordinate3"
+      if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "3"))
+        theBuffer.LinePtr++;
+    }
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Cylinder"))
       aNode = new VrmlData_Cylinder       (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Group"))
@@ -471,6 +492,12 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Inline"))
       aNode = new VrmlData_Group          (* this, strName,
                                            Standard_False);
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
+      aNode = new VrmlData_Group          (* this, strName,
+                                           Standard_False);
+    else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Switch"))
+      aNode = new VrmlData_Group          (* this, strName,
+                                           Standard_False);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ImageTexture"))
       aNode = new VrmlData_ImageTexture   (* this, strName);
     else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "IndexedFaceSet"))
@@ -493,7 +520,7 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
       aStatus = ReadWord (theBuffer, aTitle);
       if (isProto) {
         aStatus = ReadLine(theBuffer);
-        if (aStatus == VrmlData_StatusOK)
+        if (aStatus == VrmlData_StatusOK) {
           if (theBuffer.LinePtr[0] != '[')
             aStatus = VrmlData_VrmlFormatError;
           else {
@@ -517,6 +544,7 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
               }
             }
           }
+        }
       }
       if (aStatus == VrmlData_StatusOK)
         aNode = new VrmlData_UnknownNode(* this,
@@ -526,22 +554,21 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
   }
   aStatus = ReadLine(theBuffer);
   if (aNode.IsNull() == Standard_False) {
-    if (aNode->Name()[0] != '\0')
+    if (aNode->Name()[0] != '\0') 
       myNamedNodes.Add (aNode);
     if (theType.IsNull() == Standard_False)
       if (aNode->IsKind(theType) == Standard_False)
         aStatus = VrmlData_VrmlFormatError;
-#ifdef _DEBUG
-    aNode->myLineCount = theBuffer.LineCount;
-#endif
   }
-  if (aStatus == VrmlData_StatusOK)
+  if (aStatus == VrmlData_StatusOK) {
     if (theBuffer.LinePtr[0] == '{') {
       theBuffer.LinePtr++;
       theNode = aNode;
       myAllNodes.Append(aNode);
-    } else
+    } else {
       aStatus = VrmlData_VrmlFormatError;
+    }
+  }
   return aStatus;
 }
 
@@ -599,23 +626,24 @@ void VrmlData_Scene::createShape
           isSingleShape = Standard_False;
         const Handle(TopoDS_TShape) aTShape = aNodeGeom->TShape();
         aSingleShape.TShape(aTShape);
-        if (aSingleShape.IsNull() == Standard_False)
+        if (aSingleShape.IsNull() == Standard_False) {
           aBuilder.Add (outShape, aSingleShape);
-        if (pMapShapeApp != 0L) {
-          const Handle(VrmlData_Appearance)& anAppearance =
-            aNodeShape->Appearance();
-          if (anAppearance.IsNull() == Standard_False) {
-            // Check if the current topology is a single face
-            if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
-              pMapShapeApp->Bind(aTShape, anAppearance);
-            else {
-              // This is not a face, explode it in faces and bind each face
-              TopoDS_Shape aCurShape;
-              aCurShape.TShape(aTShape);
-              TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
-              for (; anExp.More(); anExp.Next()) {
-                const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
-                pMapShapeApp->Bind(aFace.TShape(), anAppearance);
+          if (pMapShapeApp != 0L) {
+            const Handle(VrmlData_Appearance)& anAppearance =
+              aNodeShape->Appearance();
+            if (anAppearance.IsNull() == Standard_False) {
+              // Check if the current topology is a single face
+              if (aTShape->IsKind(STANDARD_TYPE(TopoDS_TFace)))
+                pMapShapeApp->Bind(aTShape, anAppearance);
+              else {
+                // This is not a face, explode it in faces and bind each face
+                TopoDS_Shape aCurShape;
+                aCurShape.TShape(aTShape);
+                TopExp_Explorer anExp(aCurShape, TopAbs_FACE);
+                for (; anExp.More(); anExp.Next()) {
+                  const TopoDS_Face& aFace = TopoDS::Face(anExp.Current());
+                  pMapShapeApp->Bind(aFace.TShape(), anAppearance);
+                }
               }
             }
           }
@@ -654,7 +682,7 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadReal
   VrmlData_ErrorStatus aStatus;
   if (VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
     char * endptr;
-    aResult = strtod (theBuffer.LinePtr, &endptr);
+    aResult = Strtod (theBuffer.LinePtr, &endptr);
     if (endptr == theBuffer.LinePtr)
       aStatus = VrmlData_NumericInputError;
     else if (isOnlyPositive && aResult < 0.001*Precision::Confusion())
@@ -679,12 +707,12 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadXYZ
                                  Standard_Boolean       isOnlyPos) const
 {
   Standard_Real aVal[3] = {0., 0., 0.};
-  VrmlData_ErrorStatus aStatus;
+  VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
   for (Standard_Integer i = 0; i < 3; i++) {
     if (!VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
       break;
     char * endptr;
-    aVal[i] = strtod (theBuffer.LinePtr, &endptr);
+    aVal[i] = Strtod (theBuffer.LinePtr, &endptr);
     if (endptr == theBuffer.LinePtr) {
       aStatus = VrmlData_NumericInputError;
       break;
@@ -696,13 +724,16 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadXYZ
       theBuffer.LinePtr = endptr;
     }
   }
-  if (aStatus == VrmlData_StatusOK)
-    if (isScale)
+  if (aStatus == VrmlData_StatusOK) {
+    if (isScale) {
       theXYZ.SetCoord (aVal[0] * myLinearScale,
                        aVal[1] * myLinearScale,
                        aVal[2] * myLinearScale);
-    else
+    }
+    else {
       theXYZ.SetCoord (aVal[0], aVal[1], aVal[2]);
+    }
+  }
   return aStatus;
 }
 
@@ -718,12 +749,12 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadXY
                                  Standard_Boolean       isOnlyPos) const
 {
   Standard_Real aVal[2] = {0., 0.};
-  VrmlData_ErrorStatus aStatus;
+  VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
   for (Standard_Integer i = 0; i < 2; i++) {
     if (!VrmlData_Node::OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
       break;
     char * endptr;
-    aVal[i] = strtod (theBuffer.LinePtr, &endptr);
+    aVal[i] = Strtod (theBuffer.LinePtr, &endptr);
     if (endptr == theBuffer.LinePtr) {
       aStatus = VrmlData_NumericInputError;
       break;
@@ -735,11 +766,12 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadXY
       theBuffer.LinePtr = endptr;
     }
   }
-  if (aStatus == VrmlData_StatusOK)
+  if (aStatus == VrmlData_StatusOK) {
     if (isScale)
       theXY.SetCoord (aVal[0] * myLinearScale, aVal[1] * myLinearScale);
     else
       theXY.SetCoord (aVal[0], aVal[1]);
+  }
   return aStatus;
 }
 
@@ -756,7 +788,7 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadArrIndex
 {
   VrmlData_ErrorStatus aStatus;
   theNBlocks = 0;
-  if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer)))
+  if (VrmlData_Node::OK(aStatus, ReadLine(theBuffer))) {
     if (theBuffer.LinePtr[0] != '[')  // opening bracket
       aStatus = VrmlData_VrmlFormatError;
     else {
@@ -816,13 +848,14 @@ VrmlData_ErrorStatus VrmlData_Scene::ReadArrIndex
             aStatus = VrmlData_UnrecoverableError;
           else {
             for (size_t i = 0; i < aNbBlocks; i++)
-              anArray[i] = vecIndice(i);
+              anArray[i] = vecIndice((Standard_Integer)i);
             theNBlocks = aNbBlocks;
             theArray = anArray;
           } 
         }
       }
     }
+  }
   return aStatus;
 }
 
@@ -848,23 +881,25 @@ VrmlData_ErrorStatus VrmlData_Scene::WriteArrIndex
         const Standard_Integer * arrVal = theArrIndex[iBlock]+1;
         switch (nVal) {
         case 1:
-          sprintf (buf, "%d,", arrVal[0]);
+          Sprintf (buf, "%d,", arrVal[0]);
           break;
         case 2:
-          sprintf (buf, "%d,%d,", arrVal[0], arrVal[1]);
+          Sprintf (buf, "%d,%d,", arrVal[0], arrVal[1]);
           break;
         case 3:
-          sprintf (buf, "%d,%d,%d,", arrVal[0], arrVal[1], arrVal[2]);
+          Sprintf (buf, "%d,%d,%d,", arrVal[0], arrVal[1], arrVal[2]);
           break;
         case 4:
-          sprintf (buf, "%d,%d,%d,%d,",
+          Sprintf (buf, "%d,%d,%d,%d,",
                    arrVal[0], arrVal[1], arrVal[2], arrVal[3]);
           break;
         default:
           if (nVal > 0) {
             char * ptr = &buf[0];
             for (Standard_Integer i = 0; i < nVal; i++) {
-              sprintf (ptr, "%d,", arrVal[i]);
+              Sprintf (ptr, "%d,", arrVal[i]);
+              if (i == nVal - 1)
+                break;
               ptr = strchr (ptr, ',') + 1;
               if ((ptr - &buf[0]) > (ptrdiff_t)aLineLimit) {
                 WriteLine(buf);
@@ -893,14 +928,15 @@ VrmlData_ErrorStatus VrmlData_Scene::WriteXYZ
                                  const char             * thePostfix) const
 {
   char buf[240];
-  if (IsDummyWrite() == Standard_False)
+  if (IsDummyWrite() == Standard_False) {
     if (isApplyScale && myLinearScale > Precision::Confusion())
-      sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X() / myLinearScale,
+      Sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X() / myLinearScale,
                theXYZ.Y() / myLinearScale, theXYZ.Z() / myLinearScale,
                thePostfix ? thePostfix : "");
     else
-      sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X(), theXYZ.Y(), theXYZ.Z(),
+      Sprintf (buf, "%.12g %.12g %.12g%s", theXYZ.X(), theXYZ.Y(), theXYZ.Z(),
                thePostfix ? thePostfix : "");
+  }
   return WriteLine (buf);
 }
 
@@ -982,7 +1018,7 @@ VrmlData_ErrorStatus VrmlData_Scene::WriteNode
           Handle(VrmlData_UnknownNode) bidNode = new VrmlData_UnknownNode;
           char buf[32];
           do {
-            sprintf (buf, "_%d",
+            Sprintf (buf, "_%d",
                      ++const_cast<Standard_Integer&>(myAutoNameCounter));
             bidNode->myName = &buf[0];
           } while (myNamedNodes.Contains (bidNode));
@@ -1004,21 +1040,23 @@ VrmlData_ErrorStatus VrmlData_Scene::WriteNode
           aStatus = theNode->Write (thePrefix);
         else {
           // Name is written under DEF clause
-          char buf[1024], * ptr;
-          if (myNamedNodesOut.Contains (theNode)) {
-            memcpy (buf, "USE ", 4);
-            strncpy (&buf[4], theNode->Name(), sizeof(buf)-5);
-            aStatus = WriteLine (thePrefix, buf);
-          } else {
-            if (thePrefix) {
-              strncpy (buf, thePrefix, sizeof(buf));
-              ptr = strchr (buf, '\0');
-              * ptr++ = ' ';
-            } else
-              ptr = &buf[0];
-            strcpy (ptr, "DEF ");
-            strncpy (ptr+4, theNode->Name(), &buf[sizeof(buf)] - (ptr+5));
-            aStatus = theNode->Write (buf);
+          TCollection_AsciiString buf;
+          if (myNamedNodesOut.Contains (theNode))
+          {
+            buf += "USE ";
+            buf += theNode->Name();
+            aStatus = WriteLine (thePrefix, buf.ToCString());
+          } 
+          else 
+          {
+            if (thePrefix)
+            {
+              buf += thePrefix;
+              buf += ' ';
+            }
+            buf += "DEF ";
+            buf += theNode->Name();
+            aStatus = theNode->Write (buf.ToCString());
             const_cast<VrmlData_MapOfNode&>(myNamedNodesOut).Add (theNode);
           }
         }
@@ -1091,7 +1129,7 @@ void dumpNode (Standard_OStream&                theStream,
     const Handle(VrmlData_Group) aGroup = 
       Handle(VrmlData_Group)::DownCast (theNode);
     char buf[64];
-    sprintf (buf, "Group (%s)",
+    Sprintf (buf, "Group (%s)",
              aGroup->IsTransform() ? "Transform" : "Group");
     dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
     if (theIndent.IsEmpty() == Standard_False) {
@@ -1107,8 +1145,10 @@ void dumpNode (Standard_OStream&                theStream,
     const Standard_Integer ** ppDummy; 
     const Standard_Size nCoord = aNode->Coordinates()->Length();
     const Standard_Size nPoly  = aNode->Polygons (ppDummy);
-    char buf[64];
-    sprintf (buf, "IndexedFaceSet (%d vertices, %d polygons)", nCoord, nPoly);
+    char buf[80];
+    Sprintf (buf, "IndexedFaceSet (%" PRIuPTR " vertices, %" PRIuPTR " polygons)",
+             nCoord, nPoly);
+
     dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
   } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_IndexedLineSet))) {
     const Handle(VrmlData_IndexedLineSet) aNode =
@@ -1116,8 +1156,11 @@ void dumpNode (Standard_OStream&                theStream,
     const Standard_Integer ** ppDummy; 
     const Standard_Size nCoord = aNode->Coordinates()->Length();
     const Standard_Size nPoly  = aNode->Polygons (ppDummy);
-    char buf[64];
-    sprintf (buf, "IndexedLineSet (%d vertices, %d polygons)", nCoord, nPoly);
+
+    char buf[80];
+    Sprintf(buf, "IndexedLineSet (%" PRIuPTR " vertices, %" PRIuPTR " polygons)",
+            nCoord, nPoly);
+
     dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
   } else if (theNode->IsKind(STANDARD_TYPE(VrmlData_Material))) {
 //     const Handle(VrmlData_Material) aMaterial = 
@@ -1134,7 +1177,7 @@ void dumpNode (Standard_OStream&                theStream,
     const Handle(VrmlData_UnknownNode) anUnknown = 
       Handle(VrmlData_UnknownNode)::DownCast (theNode);
     char buf[64];
-    sprintf (buf, "Unknown (%s)", anUnknown->GetTitle().ToCString());
+    Sprintf (buf, "Unknown (%s)", anUnknown->GetTitle().ToCString());
     dumpNodeHeader (theStream, theIndent, buf, theNode->Name());
   }
 }