1 // Created on: 2006-11-06
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2006-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <VrmlData_Group.hxx>
17 #include <VrmlData_Geometry.hxx>
18 #include <VrmlData_Scene.hxx>
19 #include <VrmlData_WorldInfo.hxx>
20 #include <VrmlData_InBuffer.hxx>
21 #include <VrmlData_ListOfNode.hxx>
22 #include <VrmlData_UnknownNode.hxx>
23 #include <Precision.hxx>
27 #define _CRT_SECURE_NO_DEPRECATE
28 #pragma warning (disable:4996)
32 //=======================================================================
33 //function : VrmlData_Group
34 //purpose : Constructor
35 //=======================================================================
37 VrmlData_Group::VrmlData_Group (const VrmlData_Scene& theScene,
39 const Standard_Boolean isTransform)
40 : VrmlData_Node (theScene, theName),
41 myIsTransform (isTransform),
42 myNodes (theScene.Allocator())
45 //=======================================================================
46 //function : RemoveNode
48 //=======================================================================
50 Standard_Boolean VrmlData_Group::RemoveNode
51 (const Handle(VrmlData_Node)& theNode)
53 Standard_Boolean aResult (Standard_False);
54 for (Iterator anIter = NodeIterator(); anIter.More(); anIter.Next())
55 if (anIter.Value() == theNode) {
56 aResult = Standard_True;
57 myNodes.Remove (anIter);
63 //=======================================================================
64 //function : SetTransform
66 //=======================================================================
68 Standard_Boolean VrmlData_Group::SetTransform (const gp_Trsf& theTrsf)
70 Standard_Boolean aResult (Standard_False);
73 aResult = Standard_True;
78 //=======================================================================
79 //function : VrmlData_Group::Clone
81 //=======================================================================
83 Handle(VrmlData_Node) VrmlData_Group::Clone
84 (const Handle(VrmlData_Node)& theOther) const
86 Handle(VrmlData_Group) aResult =
87 Handle(VrmlData_Group)::DownCast (VrmlData_Node::Clone(theOther));
90 new VrmlData_Group (theOther.IsNull() ? Scene() : theOther->Scene(),
91 Name(), myIsTransform);
93 aResult->myIsTransform = myIsTransform;
94 if (&aResult->Scene() == &Scene())
95 aResult->myNodes = myNodes;
97 // Create a dummy node to pass the different Scene instance to methods Clone
98 const Handle(VrmlData_UnknownNode) aDummyNode =
99 new VrmlData_UnknownNode (aResult->Scene());
100 Iterator anIter (myNodes);
101 for (; anIter.More(); anIter.Next()) {
102 const Handle(VrmlData_Node)& aNode = anIter.Value();
103 if (aNode.IsNull() == Standard_False)
104 aResult->myNodes.Append(aNode->Clone (aDummyNode));
108 aResult->SetTransform (myTrsf);
109 aResult->SetBox (myBox);
114 //=======================================================================
115 //function : FindNode
117 //=======================================================================
119 Handle(VrmlData_Node) VrmlData_Group::FindNode
120 (const char * theName,
121 gp_Trsf& theLocation) const
123 Handle(VrmlData_Node) aResult;
124 Iterator anIter (myNodes);
125 for (; anIter.More(); anIter.Next()) {
126 const Handle(VrmlData_Node)& aNode = anIter.Value();
127 if (aNode.IsNull() == Standard_False) {
128 if (strcmp(aNode->Name(), theName) == 0)
131 theLocation = myTrsf;
134 // Try a Group type of node
135 if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group)))
137 const Handle(VrmlData_Group) aGroup =
138 Handle(VrmlData_Group)::DownCast (aNode);
139 if (aGroup.IsNull() == Standard_False) {
140 aResult = aGroup->FindNode(theName, theLocation);
141 if (aResult.IsNull() == Standard_False) {
142 //theLocation *= myTrsf;
143 theLocation.PreMultiply(myTrsf);
153 //=======================================================================
154 //function : VrmlData_Group::Read
156 //=======================================================================
158 VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
160 VrmlData_ErrorStatus aStatus;
161 gp_XYZ aBoxCenter(0., 0., 0.), aBoxSize(-1., -1., -1.);
162 gp_XYZ aCenter (0., 0., 0.), aScale (1., 1., 1.), aTrans (0., 0., 0.);
163 gp_XYZ aRotAxis (0., 0., 1.), aScaleAxis (0., 0., 1.);
164 Standard_Real aRotAngle (0.), aScaleAngle(0.);
166 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
168 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxCenter"))
169 aStatus = Scene().ReadXYZ (theBuffer, aBoxCenter,
170 Standard_True, Standard_False);
172 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxSize"))
173 aStatus = Scene().ReadXYZ (theBuffer, aBoxSize,
174 Standard_True, Standard_False);
176 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "children")) {
177 Standard_Boolean isBracketed (Standard_False);
178 // Read the opening bracket for the list of children
179 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
181 if (theBuffer.LinePtr[0] == '[') {
183 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
185 isBracketed = Standard_True;
188 // Read the child nodes
189 Handle(VrmlData_Node) aChildNode;
190 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
191 // read the end-of-list bracket
192 if (isBracketed && theBuffer.LinePtr[0] == ']') {
196 // otherwise read a node
197 if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
199 AddNode (aChildNode);
200 if (isBracketed == Standard_False)
204 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
205 VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
206 Standard_Boolean isBracketed (Standard_False);
207 // Read the opening bracket for the list of children
208 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
211 if (theBuffer.LinePtr[0] == '{') {
213 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
215 isBracketed = Standard_True;
218 // Read the child nodes
219 Handle(VrmlData_Node) aChildNode;
220 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
221 // read the end-of-list bracket
222 if (isBracketed && theBuffer.LinePtr[0] == '}') {
227 // otherwise read a node
228 if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
231 AddNode (aChildNode);
232 if (isBracketed == Standard_False)
236 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) {
238 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
241 if (theBuffer.LinePtr[0] == '{') {
243 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
246 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
247 // read the end-of-list bracket
248 if (theBuffer.LinePtr[0] == '}') {
255 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center"))
257 aStatus = Scene().ReadXYZ (theBuffer, aCenter,
258 Standard_True, Standard_False);
260 aStatus = VrmlData_VrmlFormatError;
263 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "rotation"))
265 if (OK(aStatus, Scene().ReadXYZ (theBuffer, aRotAxis,
266 Standard_False, Standard_False)))
268 if (aRotAxis.SquareModulus() < Precision::Confusion())
270 aStatus = Scene().ReadReal (theBuffer, aRotAngle,
271 Standard_False, Standard_False);
274 aStatus = VrmlData_VrmlFormatError;
277 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scaleOrientation"))
279 if (OK(aStatus, Scene().ReadXYZ (theBuffer, aScaleAxis,
280 Standard_False, Standard_False)))
281 aStatus = Scene().ReadReal (theBuffer, aScaleAngle,
282 Standard_False, Standard_False);
284 aStatus = VrmlData_VrmlFormatError;
287 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scale"))
289 aStatus = Scene().ReadXYZ (theBuffer, aScale,
290 Standard_False, Standard_True);
292 aStatus = VrmlData_VrmlFormatError;
295 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "translation"))
297 aStatus = Scene().ReadXYZ (theBuffer, aTrans,
298 Standard_True, Standard_False);
300 aStatus = VrmlData_VrmlFormatError;
303 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) {
304 NCollection_List<TCollection_AsciiString> lstURL;
305 if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) {
306 NCollection_List<TCollection_AsciiString>::Iterator anIter (lstURL);
307 for (; anIter.More(); anIter.Next()) {
309 const TCollection_AsciiString& aFileName = anIter.Value();
310 if (!OK(aStatus, openFile (aStream, aFileName)))
312 VrmlData_Scene aScene (Scene().Allocator());
313 aScene.myLinearScale = Scene().myLinearScale;
314 aScene.myVrmlDir = Scene().myVrmlDir;
316 if (!OK(aStatus, aScene.Status()))
318 VrmlData_Scene::Iterator anIterN = aScene.GetIterator();
319 for (; anIterN.More(); anIterN.Next())
320 if (!anIterN.Value()->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
321 AddNode (anIterN.Value());
322 VrmlData_Scene::Iterator anAllIter(aScene.myAllNodes);
323 for (; anAllIter.More(); anAllIter.Next()) {
324 const Handle(VrmlData_Node)& aNode = anAllIter.Value();
325 if (aNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
327 const_cast <VrmlData_Scene&> (Scene()).myAllNodes.Append (aNode);
328 aNode->myScene = &Scene();
329 // The name of the imported node should be prefixed by the URL
330 // because each name must remain unique in the global scene.
332 if (* aNode->Name() != '\0') {
333 TCollection_AsciiString buf;
335 Standard_Integer aCharLocation = buf.Location (1, '.', 1, buf.Length());
336 if (aCharLocation != 0)
338 buf.Remove (aCharLocation, buf.Length() - aCharLocation + 1);
341 buf += aNode->Name();
342 const size_t len = buf.Length();
344 static_cast<char *> (Scene().Allocator()->Allocate (len));
346 aNode->myName = aNewName;
347 memcpy (aNewName, buf.ToCString(), len);
360 // Read the terminating (closing) brace
362 aStatus = readBrace (theBuffer);
364 // Check if the Bounding Box has been imported
365 if (aBoxSize.X() > -Precision::Confusion() &&
366 aBoxSize.Y() > -Precision::Confusion() &&
367 aBoxSize.Z() > -Precision::Confusion())
369 myBox.SetCenter (aBoxCenter);
370 myBox.SetHSize (aBoxSize*0.5);
373 // Create the corresponding transformation.
374 gp_Trsf tRot, tCentInv;
375 myTrsf.SetTranslation(aTrans+aCenter);
376 gp_Ax1 aRotation (gp::Origin(), aRotAxis);
377 tRot.SetRotation(gp_Ax1 (gp::Origin(), aRotAxis), aRotAngle);
378 myTrsf.Multiply (tRot);
379 // Check that the scale is uniform (the same value in all 3 directions.
380 // Only in this case the scaling is applied.
381 const Standard_Real aScaleDiff[2] = {
382 aScale.X()-aScale.Y(),
383 aScale.X()-aScale.Z()
385 if (aScaleDiff[0]*aScaleDiff[0] + aScaleDiff[1]*aScaleDiff[1]
386 < Precision::Confusion())
389 tScale.SetScale (gp::Origin(), (aScale.X()+aScale.Y()+aScale.Z())/3.);
390 myTrsf.Multiply (tScale);
392 tCentInv.SetTranslation (aCenter.Reversed());
393 myTrsf.Multiply (tCentInv);
399 //=======================================================================
402 //=======================================================================
404 void VrmlData_Group::Shape (TopoDS_Shape& theShape,
405 VrmlData_DataMapOfShapeAppearance * pMapApp)
407 VrmlData_Scene::createShape (theShape, myNodes, pMapApp);
408 theShape.Location(myTrsf);
411 //=======================================================================
412 //function : openFile
414 //=======================================================================
416 VrmlData_ErrorStatus VrmlData_Group::openFile
417 (Standard_IStream& theStream,
418 const TCollection_AsciiString& theFilename)
420 ifstream& aStream = static_cast<ifstream&> (theStream);
421 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
422 NCollection_List<TCollection_ExtendedString>::Iterator aDirIter =
423 Scene().VrmlDirIterator();
424 for (; aDirIter.More(); aDirIter.Next()) {
425 if (!aDirIter.Value().IsAscii())
427 const TCollection_AsciiString aFullName =
428 TCollection_AsciiString (aDirIter.Value()) + theFilename;
429 aStream.open (aFullName.ToCString(), ios::in);
433 aStatus = VrmlData_StatusOK;
437 if (aStatus == VrmlData_EmptyData) {
438 aStream.open (theFilename.ToCString(), ios::in);
440 aStatus = VrmlData_StatusOK;
442 if (aStatus == VrmlData_EmptyData)
443 aStatus = VrmlData_CannotOpenFile;
447 //=======================================================================
450 //=======================================================================
452 VrmlData_ErrorStatus VrmlData_Group::Write (const char * thePrefix) const
454 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
455 if (myNodes.IsEmpty() == Standard_False) {
456 const VrmlData_Scene& aScene = Scene();
457 Standard_Boolean isTransform = myIsTransform;
458 if (isTransform && myTrsf.Form() == gp_Identity)
459 isTransform = Standard_False;
460 static const char * header[2] = { "Group {" , "Transform {" };
461 if (OK (aStatus, aScene.WriteLine (thePrefix, header[isTransform ? 1 : 0],
465 if (OK(aStatus) && aScene.IsDummyWrite() == Standard_False)
467 const gp_XYZ aBoxCorner[2] = {
471 // Check that the box is not void
472 if (aBoxCorner[0].X() < aBoxCorner[1].X() + Precision::Confusion()) {
473 Sprintf (buf, "bboxCenter %.9g %.9g %.9g",
474 0.5 * (aBoxCorner[0].X() + aBoxCorner[1].X()),
475 0.5 * (aBoxCorner[0].Y() + aBoxCorner[1].Y()),
476 0.5 * (aBoxCorner[0].Z() + aBoxCorner[1].Z()));
477 aStatus = aScene.WriteLine (buf);
479 Sprintf (buf, "bboxSize %.9g %.9g %.9g",
480 aBoxCorner[1].X() - aBoxCorner[0].X(),
481 aBoxCorner[1].Y() - aBoxCorner[0].Y(),
482 aBoxCorner[1].Z() - aBoxCorner[0].Z());
483 aStatus = aScene.WriteLine (buf);
487 if (OK(aStatus) && isTransform && aScene.IsDummyWrite() == Standard_False)
490 const Standard_Real aScaleFactor = myTrsf.ScaleFactor();
491 if ((aScaleFactor - 1.)*(aScaleFactor - 1.) >
492 0.0001*Precision::Confusion())
494 Sprintf (buf, "scale %.12g %.12g %.12g",
495 aScaleFactor, aScaleFactor, aScaleFactor);
496 aStatus = aScene.WriteLine (buf);
499 // Output the Translation
500 const gp_XYZ& aTrans = myTrsf.TranslationPart();
501 if (aTrans.SquareModulus() > 0.0001*Precision::Confusion()) {
502 Sprintf (buf, "translation %.12g %.12g %.12g",
503 aTrans.X(), aTrans.Y(), aTrans.Z());
504 aStatus = aScene.WriteLine (buf);
507 // Output the Rotation
509 Standard_Real anAngle;
510 if (myTrsf.GetRotation (anAxis, anAngle)) {
511 // output the Rotation
512 Sprintf (buf, "rotation %.12g %.12g %.12g %.9g",
513 anAxis.X(), anAxis.Y(), anAxis.Z(), anAngle);
514 aStatus = aScene.WriteLine (buf);
520 aStatus = aScene.WriteLine ("children [", 0L, GlobalIndent());
522 VrmlData_ListOfNode::Iterator anIterChild (myNodes);
523 for (; anIterChild.More() && OK(aStatus); anIterChild.Next()) {
524 const Handle(VrmlData_Node)& aNode = anIterChild.Value();
525 aScene.WriteNode (0L, aNode);
529 aStatus = aScene.WriteLine ("]", 0L, -GlobalIndent());
532 aStatus = WriteClosing();