1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-31 11:15:31 +03:00
occt/src/VrmlData/VrmlData_Group.cxx
abv ed4415982c 0024624: Lost word in license statement in source files
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast
Wrong license statements corrected in several files.
Copyright and license statements added in XSD and GLSL files.
Copyright year updated in some files.
Obsolete documentation files removed from DrawResources.
2014-03-25 16:38:55 +04:00

539 lines
19 KiB
C++

// 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 <VrmlData_Group.hxx>
#include <VrmlData_Geometry.hxx>
#include <VrmlData_Scene.hxx>
#include <VrmlData_WorldInfo.hxx>
#include <VrmlData_InBuffer.hxx>
#include <VrmlData_ListOfNode.hxx>
#include <VrmlData_UnknownNode.hxx>
#include <Precision.hxx>
#include <gp_Ax1.hxx>
#ifdef WNT
#define _CRT_SECURE_NO_DEPRECATE
#pragma warning (disable:4996)
#endif
IMPLEMENT_STANDARD_HANDLE (VrmlData_Group, VrmlData_Node)
IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Group, VrmlData_Node)
//=======================================================================
//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, "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, "scale")) {
if (myIsTransform)
aStatus = Scene().ReadXYZ (theBuffer, aScale,
Standard_False, Standard_True);
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, "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<TCollection_AsciiString> lstURL;
if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) {
NCollection_List<TCollection_AsciiString>::Iterator anIter (lstURL);
for (; anIter.More(); anIter.Next()) {
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 <VrmlData_Scene&> (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<char *> (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)
{
ifstream& aStream = static_cast<ifstream&> (theStream);
VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
NCollection_List<TCollection_ExtendedString>::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(), ios::in);
if (aStream.fail())
aStream.clear();
else {
aStatus = VrmlData_StatusOK;
break;
}
}
if (aStatus == VrmlData_EmptyData) {
aStream.open (theFilename.ToCString(), 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;
}