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>
26 IMPLEMENT_STANDARD_RTTIEXT(VrmlData_Group,VrmlData_Node)
29 #define _CRT_SECURE_NO_DEPRECATE
30 #pragma warning (disable:4996)
34 //=======================================================================
35 //function : VrmlData_Group
36 //purpose : Constructor
37 //=======================================================================
39 VrmlData_Group::VrmlData_Group (const VrmlData_Scene& theScene,
41 const Standard_Boolean isTransform)
42 : VrmlData_Node (theScene, theName),
43 myIsTransform (isTransform),
44 myNodes (theScene.Allocator())
47 //=======================================================================
48 //function : RemoveNode
50 //=======================================================================
52 Standard_Boolean VrmlData_Group::RemoveNode
53 (const Handle(VrmlData_Node)& theNode)
55 Standard_Boolean aResult (Standard_False);
56 for (Iterator anIter = NodeIterator(); anIter.More(); anIter.Next())
57 if (anIter.Value() == theNode) {
58 aResult = Standard_True;
59 myNodes.Remove (anIter);
65 //=======================================================================
66 //function : SetTransform
68 //=======================================================================
70 Standard_Boolean VrmlData_Group::SetTransform (const gp_Trsf& theTrsf)
72 Standard_Boolean aResult (Standard_False);
75 aResult = Standard_True;
80 //=======================================================================
81 //function : VrmlData_Group::Clone
83 //=======================================================================
85 Handle(VrmlData_Node) VrmlData_Group::Clone
86 (const Handle(VrmlData_Node)& theOther) const
88 Handle(VrmlData_Group) aResult =
89 Handle(VrmlData_Group)::DownCast (VrmlData_Node::Clone(theOther));
92 new VrmlData_Group (theOther.IsNull() ? Scene() : theOther->Scene(),
93 Name(), myIsTransform);
95 aResult->myIsTransform = myIsTransform;
96 if (&aResult->Scene() == &Scene())
97 aResult->myNodes = myNodes;
99 // Create a dummy node to pass the different Scene instance to methods Clone
100 const Handle(VrmlData_UnknownNode) aDummyNode =
101 new VrmlData_UnknownNode (aResult->Scene());
102 Iterator anIter (myNodes);
103 for (; anIter.More(); anIter.Next()) {
104 const Handle(VrmlData_Node)& aNode = anIter.Value();
105 if (aNode.IsNull() == Standard_False)
106 aResult->myNodes.Append(aNode->Clone (aDummyNode));
110 aResult->SetTransform (myTrsf);
111 aResult->SetBox (myBox);
116 //=======================================================================
117 //function : FindNode
119 //=======================================================================
121 Handle(VrmlData_Node) VrmlData_Group::FindNode
122 (const char * theName,
123 gp_Trsf& theLocation) const
125 Handle(VrmlData_Node) aResult;
126 Iterator anIter (myNodes);
127 for (; anIter.More(); anIter.Next()) {
128 const Handle(VrmlData_Node)& aNode = anIter.Value();
129 if (aNode.IsNull() == Standard_False) {
130 if (strcmp(aNode->Name(), theName) == 0)
133 theLocation = myTrsf;
136 // Try a Group type of node
137 if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group)))
139 const Handle(VrmlData_Group) aGroup =
140 Handle(VrmlData_Group)::DownCast (aNode);
141 if (aGroup.IsNull() == Standard_False) {
142 aResult = aGroup->FindNode(theName, theLocation);
143 if (aResult.IsNull() == Standard_False) {
144 //theLocation *= myTrsf;
145 theLocation.PreMultiply(myTrsf);
155 //=======================================================================
156 //function : VrmlData_Group::Read
158 //=======================================================================
160 VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
162 VrmlData_ErrorStatus aStatus;
163 gp_XYZ aBoxCenter(0., 0., 0.), aBoxSize(-1., -1., -1.);
164 gp_XYZ aCenter (0., 0., 0.), aScale (1., 1., 1.), aTrans (0., 0., 0.);
165 gp_XYZ aRotAxis (0., 0., 1.), aScaleAxis (0., 0., 1.);
166 Standard_Real aRotAngle (0.), aScaleAngle(0.);
168 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
170 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxCenter"))
171 aStatus = Scene().ReadXYZ (theBuffer, aBoxCenter,
172 Standard_True, Standard_False);
174 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxSize"))
175 aStatus = Scene().ReadXYZ (theBuffer, aBoxSize,
176 Standard_True, Standard_False);
178 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "children")) {
179 Standard_Boolean isBracketed (Standard_False);
180 // Read the opening bracket for the list of children
181 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
183 if (theBuffer.LinePtr[0] == '[') {
185 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
187 isBracketed = Standard_True;
190 // Read the child nodes
191 Handle(VrmlData_Node) aChildNode;
192 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
193 // read the end-of-list bracket
194 if (isBracketed && theBuffer.LinePtr[0] == ']') {
198 // otherwise read a node
199 if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
201 AddNode (aChildNode);
202 if (isBracketed == Standard_False)
206 else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "collide")) {
207 TCollection_AsciiString aDummy;
208 aStatus = Scene().ReadWord (theBuffer, aDummy);
210 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
211 VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
212 Standard_Boolean isBracketed (Standard_False);
213 // Read the opening bracket for the list of children
214 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
217 if (theBuffer.LinePtr[0] == '{') {
219 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
221 isBracketed = Standard_True;
224 // Read the child nodes
225 Handle(VrmlData_Node) aChildNode;
226 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
227 // read the end-of-list bracket
228 if (isBracketed && theBuffer.LinePtr[0] == '}') {
233 // otherwise read a node
234 if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
237 AddNode (aChildNode);
238 if (isBracketed == Standard_False)
242 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) {
244 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
247 if (theBuffer.LinePtr[0] == '{') {
249 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
252 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
253 // read the end-of-list bracket
254 if (theBuffer.LinePtr[0] == '}') {
261 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center"))
263 aStatus = Scene().ReadXYZ (theBuffer, aCenter,
264 Standard_True, Standard_False);
266 aStatus = VrmlData_VrmlFormatError;
269 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "rotation"))
271 if (OK(aStatus, Scene().ReadXYZ (theBuffer, aRotAxis,
272 Standard_False, Standard_False)))
274 if (aRotAxis.SquareModulus() < Precision::Confusion())
276 aStatus = Scene().ReadReal (theBuffer, aRotAngle,
277 Standard_False, Standard_False);
280 aStatus = VrmlData_VrmlFormatError;
283 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scaleOrientation"))
285 if (OK(aStatus, Scene().ReadXYZ (theBuffer, aScaleAxis,
286 Standard_False, Standard_False)))
287 aStatus = Scene().ReadReal (theBuffer, aScaleAngle,
288 Standard_False, Standard_False);
290 aStatus = VrmlData_VrmlFormatError;
293 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scale"))
295 aStatus = Scene().ReadXYZ (theBuffer, aScale,
296 Standard_False, Standard_True);
298 aStatus = VrmlData_VrmlFormatError;
301 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "translation"))
303 aStatus = Scene().ReadXYZ (theBuffer, aTrans,
304 Standard_True, Standard_False);
306 aStatus = VrmlData_VrmlFormatError;
309 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) {
310 NCollection_List<TCollection_AsciiString> lstURL;
311 if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) {
312 NCollection_List<TCollection_AsciiString>::Iterator anIter (lstURL);
313 for (; anIter.More(); anIter.Next()) {
315 const TCollection_AsciiString& aFileName = anIter.Value();
316 if (!OK(aStatus, openFile (aStream, aFileName)))
318 VrmlData_Scene aScene (Scene().Allocator());
319 aScene.myLinearScale = Scene().myLinearScale;
320 aScene.myVrmlDir = Scene().myVrmlDir;
322 if (!OK(aStatus, aScene.Status()))
324 VrmlData_Scene::Iterator anIterN = aScene.GetIterator();
325 for (; anIterN.More(); anIterN.Next())
326 if (!anIterN.Value()->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
327 AddNode (anIterN.Value());
328 VrmlData_Scene::Iterator anAllIter(aScene.myAllNodes);
329 for (; anAllIter.More(); anAllIter.Next()) {
330 const Handle(VrmlData_Node)& aNode = anAllIter.Value();
331 if (aNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
333 const_cast <VrmlData_Scene&> (Scene()).myAllNodes.Append (aNode);
334 aNode->myScene = &Scene();
335 // The name of the imported node should be prefixed by the URL
336 // because each name must remain unique in the global scene.
338 if (* aNode->Name() != '\0') {
339 TCollection_AsciiString buf;
341 Standard_Integer aCharLocation = buf.Location (1, '.', 1, buf.Length());
342 if (aCharLocation != 0)
344 buf.Remove (aCharLocation, buf.Length() - aCharLocation + 1);
347 buf += aNode->Name();
348 const size_t len = buf.Length();
350 static_cast<char *> (Scene().Allocator()->Allocate (len));
352 aNode->myName = aNewName;
353 memcpy (aNewName, buf.ToCString(), len);
366 // Read the terminating (closing) brace
368 aStatus = readBrace (theBuffer);
370 // Check if the Bounding Box has been imported
371 if (aBoxSize.X() > -Precision::Confusion() &&
372 aBoxSize.Y() > -Precision::Confusion() &&
373 aBoxSize.Z() > -Precision::Confusion())
375 myBox.SetCenter (aBoxCenter);
376 myBox.SetHSize (aBoxSize*0.5);
379 // Create the corresponding transformation.
380 gp_Trsf tRot, tCentInv;
381 myTrsf.SetTranslation(aTrans+aCenter);
382 gp_Ax1 aRotation (gp::Origin(), aRotAxis);
383 tRot.SetRotation(gp_Ax1 (gp::Origin(), aRotAxis), aRotAngle);
384 myTrsf.Multiply (tRot);
385 // Check that the scale is uniform (the same value in all 3 directions.
386 // Only in this case the scaling is applied.
387 const Standard_Real aScaleDiff[2] = {
388 aScale.X()-aScale.Y(),
389 aScale.X()-aScale.Z()
391 if (aScaleDiff[0]*aScaleDiff[0] + aScaleDiff[1]*aScaleDiff[1]
392 < Precision::Confusion())
395 tScale.SetScale (gp::Origin(), (aScale.X()+aScale.Y()+aScale.Z())/3.);
396 myTrsf.Multiply (tScale);
398 tCentInv.SetTranslation (aCenter.Reversed());
399 myTrsf.Multiply (tCentInv);
405 //=======================================================================
408 //=======================================================================
410 void VrmlData_Group::Shape (TopoDS_Shape& theShape,
411 VrmlData_DataMapOfShapeAppearance * pMapApp)
413 VrmlData_Scene::createShape (theShape, myNodes, pMapApp);
414 theShape.Location(myTrsf);
417 //=======================================================================
418 //function : openFile
420 //=======================================================================
422 VrmlData_ErrorStatus VrmlData_Group::openFile
423 (Standard_IStream& theStream,
424 const TCollection_AsciiString& theFilename)
426 ifstream& aStream = static_cast<ifstream&> (theStream);
427 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
428 NCollection_List<TCollection_ExtendedString>::Iterator aDirIter =
429 Scene().VrmlDirIterator();
430 for (; aDirIter.More(); aDirIter.Next()) {
431 if (!aDirIter.Value().IsAscii())
433 const TCollection_AsciiString aFullName =
434 TCollection_AsciiString (aDirIter.Value()) + theFilename;
435 aStream.open (aFullName.ToCString(), ios::in);
439 aStatus = VrmlData_StatusOK;
443 if (aStatus == VrmlData_EmptyData) {
444 aStream.open (theFilename.ToCString(), ios::in);
446 aStatus = VrmlData_StatusOK;
448 if (aStatus == VrmlData_EmptyData)
449 aStatus = VrmlData_CannotOpenFile;
453 //=======================================================================
456 //=======================================================================
458 VrmlData_ErrorStatus VrmlData_Group::Write (const char * thePrefix) const
460 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
461 if (myNodes.IsEmpty() == Standard_False) {
462 const VrmlData_Scene& aScene = Scene();
463 Standard_Boolean isTransform = myIsTransform;
464 if (isTransform && myTrsf.Form() == gp_Identity)
465 isTransform = Standard_False;
466 static const char * header[2] = { "Group {" , "Transform {" };
467 if (OK (aStatus, aScene.WriteLine (thePrefix, header[isTransform ? 1 : 0],
471 if (OK(aStatus) && aScene.IsDummyWrite() == Standard_False)
473 const gp_XYZ aBoxCorner[2] = {
477 // Check that the box is not void
478 if (aBoxCorner[0].X() < aBoxCorner[1].X() + Precision::Confusion()) {
479 Sprintf (buf, "bboxCenter %.9g %.9g %.9g",
480 0.5 * (aBoxCorner[0].X() + aBoxCorner[1].X()),
481 0.5 * (aBoxCorner[0].Y() + aBoxCorner[1].Y()),
482 0.5 * (aBoxCorner[0].Z() + aBoxCorner[1].Z()));
483 aStatus = aScene.WriteLine (buf);
485 Sprintf (buf, "bboxSize %.9g %.9g %.9g",
486 aBoxCorner[1].X() - aBoxCorner[0].X(),
487 aBoxCorner[1].Y() - aBoxCorner[0].Y(),
488 aBoxCorner[1].Z() - aBoxCorner[0].Z());
489 aStatus = aScene.WriteLine (buf);
493 if (OK(aStatus) && isTransform && aScene.IsDummyWrite() == Standard_False)
496 const Standard_Real aScaleFactor = myTrsf.ScaleFactor();
497 if ((aScaleFactor - 1.)*(aScaleFactor - 1.) >
498 0.0001*Precision::Confusion())
500 Sprintf (buf, "scale %.12g %.12g %.12g",
501 aScaleFactor, aScaleFactor, aScaleFactor);
502 aStatus = aScene.WriteLine (buf);
505 // Output the Translation
506 const gp_XYZ& aTrans = myTrsf.TranslationPart();
507 if (aTrans.SquareModulus() > 0.0001*Precision::Confusion()) {
508 Sprintf (buf, "translation %.12g %.12g %.12g",
509 aTrans.X(), aTrans.Y(), aTrans.Z());
510 aStatus = aScene.WriteLine (buf);
513 // Output the Rotation
515 Standard_Real anAngle;
516 if (myTrsf.GetRotation (anAxis, anAngle)) {
517 // output the Rotation
518 Sprintf (buf, "rotation %.12g %.12g %.12g %.9g",
519 anAxis.X(), anAxis.Y(), anAxis.Z(), anAngle);
520 aStatus = aScene.WriteLine (buf);
526 aStatus = aScene.WriteLine ("children [", 0L, GlobalIndent());
528 VrmlData_ListOfNode::Iterator anIterChild (myNodes);
529 for (; anIterChild.More() && OK(aStatus); anIterChild.Next()) {
530 const Handle(VrmlData_Node)& aNode = anIterChild.Value();
531 aScene.WriteNode (0L, aNode);
535 aStatus = aScene.WriteLine ("]", 0L, -GlobalIndent());
538 aStatus = WriteClosing();