// Created on: 2006-11-06 // 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 #include #include #include #include #include #include #include #include IMPLEMENT_STANDARD_RTTIEXT(VrmlData_Group,VrmlData_Node) #ifdef _MSC_VER #define _CRT_SECURE_NO_DEPRECATE #pragma warning (disable:4996) #endif //======================================================================= //function : VrmlData_Group //purpose : Constructor //======================================================================= VrmlData_Group::VrmlData_Group (const VrmlData_Scene& theScene, const char * theName, const Standard_Boolean isTransform) : VrmlData_Node (theScene, theName), myIsTransform (isTransform), myNodes (theScene.Allocator()) {} //======================================================================= //function : RemoveNode //purpose : //======================================================================= Standard_Boolean VrmlData_Group::RemoveNode (const Handle(VrmlData_Node)& theNode) { Standard_Boolean aResult (Standard_False); for (Iterator anIter = NodeIterator(); anIter.More(); anIter.Next()) if (anIter.Value() == theNode) { aResult = Standard_True; myNodes.Remove (anIter); break; } return aResult; } //======================================================================= //function : SetTransform //purpose : //======================================================================= Standard_Boolean VrmlData_Group::SetTransform (const gp_Trsf& theTrsf) { Standard_Boolean aResult (Standard_False); if (myIsTransform) { myTrsf = theTrsf; aResult = Standard_True; } return aResult; } //======================================================================= //function : VrmlData_Group::Clone //purpose : //======================================================================= Handle(VrmlData_Node) VrmlData_Group::Clone (const Handle(VrmlData_Node)& theOther) const { Handle(VrmlData_Group) aResult = Handle(VrmlData_Group)::DownCast (VrmlData_Node::Clone(theOther)); if (aResult.IsNull()) aResult = new VrmlData_Group (theOther.IsNull() ? Scene() : theOther->Scene(), Name(), myIsTransform); aResult->myIsTransform = myIsTransform; if (&aResult->Scene() == &Scene()) aResult->myNodes = myNodes; else { // Create a dummy node to pass the different Scene instance to methods Clone const Handle(VrmlData_UnknownNode) aDummyNode = new VrmlData_UnknownNode (aResult->Scene()); Iterator anIter (myNodes); for (; anIter.More(); anIter.Next()) { const Handle(VrmlData_Node)& aNode = anIter.Value(); if (aNode.IsNull() == Standard_False) aResult->myNodes.Append(aNode->Clone (aDummyNode)); } } if (myIsTransform) aResult->SetTransform (myTrsf); aResult->SetBox (myBox); return aResult; } //======================================================================= //function : FindNode //purpose : //======================================================================= Handle(VrmlData_Node) VrmlData_Group::FindNode (const char * theName, gp_Trsf& theLocation) const { Handle(VrmlData_Node) aResult; Iterator anIter (myNodes); for (; anIter.More(); anIter.Next()) { const Handle(VrmlData_Node)& aNode = anIter.Value(); if (aNode.IsNull() == Standard_False) { if (strcmp(aNode->Name(), theName) == 0) { aResult = aNode; theLocation = myTrsf; break; } // Try a Group type of node if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group))) { const Handle(VrmlData_Group) aGroup = Handle(VrmlData_Group)::DownCast (aNode); if (aGroup.IsNull() == Standard_False) { aResult = aGroup->FindNode(theName, theLocation); if (aResult.IsNull() == Standard_False) { //theLocation *= myTrsf; theLocation.PreMultiply(myTrsf); break; } } } } } return aResult; } //======================================================================= //function : VrmlData_Group::Read //purpose : //======================================================================= VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer) { VrmlData_ErrorStatus aStatus; gp_XYZ aBoxCenter(0., 0., 0.), aBoxSize(-1., -1., -1.); gp_XYZ aCenter (0., 0., 0.), aScale (1., 1., 1.), aTrans (0., 0., 0.); gp_XYZ aRotAxis (0., 0., 1.), aScaleAxis (0., 0., 1.); Standard_Real aRotAngle (0.), aScaleAngle(0.); while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) { if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxCenter")) aStatus = Scene().ReadXYZ (theBuffer, aBoxCenter, Standard_True, Standard_False); else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxSize")) aStatus = Scene().ReadXYZ (theBuffer, aBoxSize, Standard_True, Standard_False); else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "children")) { Standard_Boolean isBracketed (Standard_False); // Read the opening bracket for the list of children if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) break; if (theBuffer.LinePtr[0] == '[') { theBuffer.LinePtr++; if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) break; isBracketed = Standard_True; } // Read the child nodes Handle(VrmlData_Node) aChildNode; while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) { // read the end-of-list bracket if (isBracketed && theBuffer.LinePtr[0] == ']') { theBuffer.LinePtr++; break; } // otherwise read a node if (!OK(aStatus, ReadNode (theBuffer, aChildNode))) break; AddNode (aChildNode); if (isBracketed == Standard_False) break; } } else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "collide")) { TCollection_AsciiString aDummy; aStatus = Scene().ReadWord (theBuffer, aDummy); } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") || VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) { Standard_Boolean isBracketed (Standard_False); // Read the opening bracket for the list of children if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) break; if (theBuffer.LinePtr[0] == '{') { theBuffer.LinePtr++; if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) break; isBracketed = Standard_True; } // Read the child nodes Handle(VrmlData_Node) aChildNode; while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) { // read the end-of-list bracket if (isBracketed && theBuffer.LinePtr[0] == '}') { theBuffer.LinePtr++; break; } // otherwise read a node if (!OK(aStatus, ReadNode (theBuffer, aChildNode))) break; AddNode (aChildNode); if (isBracketed == Standard_False) break; } } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) { // Skip this tag if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) break; if (theBuffer.LinePtr[0] == '{') { theBuffer.LinePtr++; if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) break; while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) { // read the end-of-list bracket if (theBuffer.LinePtr[0] == '}') { theBuffer.LinePtr++; break; } theBuffer.LinePtr++; } } } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center")) if (myIsTransform) aStatus = Scene().ReadXYZ (theBuffer, aCenter, Standard_True, Standard_False); else { aStatus = VrmlData_VrmlFormatError; break; } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "rotation")) if (myIsTransform) { if (OK(aStatus, Scene().ReadXYZ (theBuffer, aRotAxis, Standard_False, Standard_False))) { if (aRotAxis.SquareModulus() < Precision::Confusion()) aRotAxis.SetZ (1.0); aStatus = Scene().ReadReal (theBuffer, aRotAngle, Standard_False, Standard_False); } } else { aStatus = VrmlData_VrmlFormatError; break; } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scaleOrientation")) if (myIsTransform) { if (OK(aStatus, Scene().ReadXYZ (theBuffer, aScaleAxis, Standard_False, Standard_False))) aStatus = Scene().ReadReal (theBuffer, aScaleAngle, Standard_False, Standard_False); } else { aStatus = VrmlData_VrmlFormatError; break; } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scale")) if (myIsTransform) aStatus = Scene().ReadXYZ (theBuffer, aScale, Standard_False, Standard_True); else { aStatus = VrmlData_VrmlFormatError; break; } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "translation")) if (myIsTransform) aStatus = Scene().ReadXYZ (theBuffer, aTrans, Standard_True, Standard_False); else { aStatus = VrmlData_VrmlFormatError; break; } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) { NCollection_List lstURL; if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) { NCollection_List::Iterator anIter (lstURL); for (; anIter.More(); anIter.Next()) { std::ifstream aStream; const TCollection_AsciiString& aFileName = anIter.Value(); if (!OK(aStatus, openFile (aStream, aFileName))) break; VrmlData_Scene aScene (Scene().Allocator()); aScene.myLinearScale = Scene().myLinearScale; aScene.myVrmlDir = Scene().myVrmlDir; aScene << aStream; if (!OK(aStatus, aScene.Status())) break; VrmlData_Scene::Iterator anIterN = aScene.GetIterator(); for (; anIterN.More(); anIterN.Next()) if (!anIterN.Value()->IsKind(STANDARD_TYPE(VrmlData_WorldInfo))) AddNode (anIterN.Value()); VrmlData_Scene::Iterator anAllIter(aScene.myAllNodes); for (; anAllIter.More(); anAllIter.Next()) { const Handle(VrmlData_Node)& aNode = anAllIter.Value(); if (aNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo))) continue; const_cast (Scene()).myAllNodes.Append (aNode); aNode->myScene = &Scene(); // The name of the imported node should be prefixed by the URL // because each name must remain unique in the global scene. if (aNode->Name()) if (* aNode->Name() != '\0') { TCollection_AsciiString buf; buf += aFileName; Standard_Integer aCharLocation = buf.Location (1, '.', 1, buf.Length()); if (aCharLocation != 0) { buf.Remove (aCharLocation, buf.Length() - aCharLocation + 1); } buf += '_'; buf += aNode->Name(); const size_t len = buf.Length(); char * aNewName = static_cast (Scene().Allocator()->Allocate (len)); if (aNewName) { aNode->myName = aNewName; memcpy (aNewName, buf.ToCString(), len); } } } } } } else break; if (!OK(aStatus)) break; } // Read the terminating (closing) brace if (OK(aStatus)) aStatus = readBrace (theBuffer); if (OK(aStatus)) { // Check if the Bounding Box has been imported if (aBoxSize.X() > -Precision::Confusion() && aBoxSize.Y() > -Precision::Confusion() && aBoxSize.Z() > -Precision::Confusion()) { myBox.SetCenter (aBoxCenter); myBox.SetHSize (aBoxSize*0.5); } if (myIsTransform) { // Create the corresponding transformation. gp_Trsf tRot, tCentInv; myTrsf.SetTranslation(aTrans+aCenter); gp_Ax1 aRotation (gp::Origin(), aRotAxis); tRot.SetRotation(gp_Ax1 (gp::Origin(), aRotAxis), aRotAngle); myTrsf.Multiply (tRot); // Check that the scale is uniform (the same value in all 3 directions. // Only in this case the scaling is applied. const Standard_Real aScaleDiff[2] = { aScale.X()-aScale.Y(), aScale.X()-aScale.Z() }; if (aScaleDiff[0]*aScaleDiff[0] + aScaleDiff[1]*aScaleDiff[1] < Precision::Confusion()) { gp_Trsf tScale; tScale.SetScale (gp::Origin(), (aScale.X()+aScale.Y()+aScale.Z())/3.); myTrsf.Multiply (tScale); } tCentInv.SetTranslation (aCenter.Reversed()); myTrsf.Multiply (tCentInv); } } return aStatus; } //======================================================================= //function : Shape //purpose : //======================================================================= void VrmlData_Group::Shape (TopoDS_Shape& theShape, VrmlData_DataMapOfShapeAppearance * pMapApp) { VrmlData_Scene::createShape (theShape, myNodes, pMapApp); theShape.Location(myTrsf); } //======================================================================= //function : openFile //purpose : //======================================================================= VrmlData_ErrorStatus VrmlData_Group::openFile (Standard_IStream& theStream, const TCollection_AsciiString& theFilename) { std::ifstream& aStream = static_cast (theStream); VrmlData_ErrorStatus aStatus (VrmlData_EmptyData); NCollection_List::Iterator aDirIter = Scene().VrmlDirIterator(); for (; aDirIter.More(); aDirIter.Next()) { if (!aDirIter.Value().IsAscii()) continue; const TCollection_AsciiString aFullName = TCollection_AsciiString (aDirIter.Value()) + theFilename; aStream.open (aFullName.ToCString(), std::ios::in); if (aStream.fail()) aStream.clear(); else { aStatus = VrmlData_StatusOK; break; } } if (aStatus == VrmlData_EmptyData) { aStream.open (theFilename.ToCString(), std::ios::in); if (!aStream.fail()) aStatus = VrmlData_StatusOK; } if (aStatus == VrmlData_EmptyData) aStatus = VrmlData_CannotOpenFile; return aStatus; } //======================================================================= //function : Write //purpose : //======================================================================= VrmlData_ErrorStatus VrmlData_Group::Write (const char * thePrefix) const { VrmlData_ErrorStatus aStatus (VrmlData_StatusOK); if (myNodes.IsEmpty() == Standard_False) { const VrmlData_Scene& aScene = Scene(); Standard_Boolean isTransform = myIsTransform; if (isTransform && myTrsf.Form() == gp_Identity) isTransform = Standard_False; static const char * header[2] = { "Group {" , "Transform {" }; if (OK (aStatus, aScene.WriteLine (thePrefix, header[isTransform ? 1 : 0], GlobalIndent()))) { char buf[240]; if (OK(aStatus) && aScene.IsDummyWrite() == Standard_False) { const gp_XYZ aBoxCorner[2] = { myBox.CornerMin(), myBox.CornerMax() }; // Check that the box is not void if (aBoxCorner[0].X() < aBoxCorner[1].X() + Precision::Confusion()) { Sprintf (buf, "bboxCenter %.9g %.9g %.9g", 0.5 * (aBoxCorner[0].X() + aBoxCorner[1].X()), 0.5 * (aBoxCorner[0].Y() + aBoxCorner[1].Y()), 0.5 * (aBoxCorner[0].Z() + aBoxCorner[1].Z())); aStatus = aScene.WriteLine (buf); if (OK(aStatus)) { Sprintf (buf, "bboxSize %.9g %.9g %.9g", aBoxCorner[1].X() - aBoxCorner[0].X(), aBoxCorner[1].Y() - aBoxCorner[0].Y(), aBoxCorner[1].Z() - aBoxCorner[0].Z()); aStatus = aScene.WriteLine (buf); } } } if (OK(aStatus) && isTransform && aScene.IsDummyWrite() == Standard_False) { // Output the Scale const Standard_Real aScaleFactor = myTrsf.ScaleFactor(); if ((aScaleFactor - 1.)*(aScaleFactor - 1.) > 0.0001*Precision::Confusion()) { Sprintf (buf, "scale %.12g %.12g %.12g", aScaleFactor, aScaleFactor, aScaleFactor); aStatus = aScene.WriteLine (buf); } // Output the Translation const gp_XYZ& aTrans = myTrsf.TranslationPart(); if (aTrans.SquareModulus() > 0.0001*Precision::Confusion()) { Sprintf (buf, "translation %.12g %.12g %.12g", aTrans.X(), aTrans.Y(), aTrans.Z()); aStatus = aScene.WriteLine (buf); } // Output the Rotation gp_XYZ anAxis; Standard_Real anAngle; if (myTrsf.GetRotation (anAxis, anAngle)) { // output the Rotation Sprintf (buf, "rotation %.12g %.12g %.12g %.9g", anAxis.X(), anAxis.Y(), anAxis.Z(), anAngle); aStatus = aScene.WriteLine (buf); } } if (OK(aStatus)) { aStatus = aScene.WriteLine ("children [", 0L, GlobalIndent()); VrmlData_ListOfNode::Iterator anIterChild (myNodes); for (; anIterChild.More() && OK(aStatus); anIterChild.Next()) { const Handle(VrmlData_Node)& aNode = anIterChild.Value(); aScene.WriteNode (0L, aNode); } if (OK(aStatus)) { aStatus = aScene.WriteLine ("]", 0L, -GlobalIndent()); } } aStatus = WriteClosing(); } } return aStatus; }