1 // File: VrmlData_Group.cxx
2 // Created: 06.11.06 08:01
3 // Author: Alexander GRIGORIEV
4 // Copyright: Open Cascade 2006
7 #include <VrmlData_Group.hxx>
8 #include <VrmlData_Geometry.hxx>
9 #include <VrmlData_Scene.hxx>
10 #include <VrmlData_WorldInfo.hxx>
11 #include <VrmlData_InBuffer.hxx>
12 #include <VrmlData_ListOfNode.hxx>
13 #include <VrmlData_UnknownNode.hxx>
14 #include <Precision.hxx>
18 #define _CRT_SECURE_NO_DEPRECATE
19 #pragma warning (disable:4996)
22 IMPLEMENT_STANDARD_HANDLE (VrmlData_Group, VrmlData_Node)
23 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Group, VrmlData_Node)
25 //=======================================================================
26 //function : VrmlData_Group
27 //purpose : Constructor
28 //=======================================================================
30 VrmlData_Group::VrmlData_Group (const VrmlData_Scene& theScene,
32 const Standard_Boolean isTransform)
33 : VrmlData_Node (theScene, theName),
34 myIsTransform (isTransform),
35 myNodes (theScene.Allocator())
38 //=======================================================================
39 //function : RemoveNode
41 //=======================================================================
43 Standard_Boolean VrmlData_Group::RemoveNode
44 (const Handle(VrmlData_Node)& theNode)
46 Standard_Boolean aResult (Standard_False);
47 for (Iterator anIter = NodeIterator(); anIter.More(); anIter.Next())
48 if (anIter.Value() == theNode) {
49 aResult = Standard_True;
50 myNodes.Remove (anIter);
56 //=======================================================================
57 //function : SetTransform
59 //=======================================================================
61 Standard_Boolean VrmlData_Group::SetTransform (const gp_Trsf& theTrsf)
63 Standard_Boolean aResult (Standard_False);
66 aResult = Standard_True;
71 //=======================================================================
72 //function : VrmlData_Group::Clone
74 //=======================================================================
76 Handle(VrmlData_Node) VrmlData_Group::Clone
77 (const Handle(VrmlData_Node)& theOther) const
79 Handle(VrmlData_Group) aResult =
80 Handle(VrmlData_Group)::DownCast (VrmlData_Node::Clone(theOther));
83 new VrmlData_Group (theOther.IsNull() ? Scene() : theOther->Scene(),
84 Name(), myIsTransform);
86 aResult->myIsTransform = myIsTransform;
87 if (&aResult->Scene() == &Scene())
88 aResult->myNodes = myNodes;
90 // Create a dummy node to pass the different Scene instance to methods Clone
91 const Handle(VrmlData_UnknownNode) aDummyNode =
92 new VrmlData_UnknownNode (aResult->Scene());
93 Iterator anIter (myNodes);
94 for (; anIter.More(); anIter.Next()) {
95 const Handle(VrmlData_Node)& aNode = anIter.Value();
96 if (aNode.IsNull() == Standard_False)
97 aResult->myNodes.Append(aNode->Clone (aDummyNode));
101 aResult->SetTransform (myTrsf);
102 aResult->SetBox (myBox);
107 //=======================================================================
108 //function : FindNode
110 //=======================================================================
112 Handle(VrmlData_Node) VrmlData_Group::FindNode
113 (const char * theName,
114 gp_Trsf& theLocation) const
116 Handle(VrmlData_Node) aResult;
117 Iterator anIter (myNodes);
118 for (; anIter.More(); anIter.Next()) {
119 const Handle(VrmlData_Node)& aNode = anIter.Value();
120 if (aNode.IsNull() == Standard_False) {
121 if (strcmp(aNode->Name(), theName) == 0)
124 theLocation = myTrsf;
127 // Try a Group type of node
128 if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group)))
130 const Handle(VrmlData_Group) aGroup =
131 Handle(VrmlData_Group)::DownCast (aNode);
132 if (aGroup.IsNull() == Standard_False) {
133 aResult = aGroup->FindNode(theName, theLocation);
134 if (aResult.IsNull() == Standard_False) {
135 //theLocation *= myTrsf;
136 theLocation.PreMultiply(myTrsf);
146 //=======================================================================
147 //function : VrmlData_Group::Read
149 //=======================================================================
151 VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
153 VrmlData_ErrorStatus aStatus;
154 gp_XYZ aBoxCenter(0., 0., 0.), aBoxSize(-1., -1., -1.);
155 gp_XYZ aCenter (0., 0., 0.), aScale (1., 1., 1.), aTrans (0., 0., 0.);
156 gp_XYZ aRotAxis (0., 0., 1.), aScaleAxis (0., 0., 1.);
157 Standard_Real aRotAngle (0.), aScaleAngle(0.);
159 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
161 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxCenter"))
162 aStatus = Scene().ReadXYZ (theBuffer, aBoxCenter,
163 Standard_True, Standard_False);
165 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxSize"))
166 aStatus = Scene().ReadXYZ (theBuffer, aBoxSize,
167 Standard_True, Standard_False);
169 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "children")) {
170 Standard_Boolean isBracketed (Standard_False);
171 // Read the opening bracket for the list of children
172 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
174 if (theBuffer.LinePtr[0] == '[') {
176 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
178 isBracketed = Standard_True;
181 // Read the child nodes
182 Handle(VrmlData_Node) aChildNode;
183 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
184 // read the end-of-list bracket
185 if (isBracketed && theBuffer.LinePtr[0] == ']') {
189 // otherwise read a node
190 if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
192 AddNode (aChildNode);
193 if (isBracketed == Standard_False)
197 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
198 VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
199 Standard_Boolean isBracketed (Standard_False);
200 // Read the opening bracket for the list of children
201 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
204 if (theBuffer.LinePtr[0] == '{') {
206 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
208 isBracketed = Standard_True;
211 // Read the child nodes
212 Handle(VrmlData_Node) aChildNode;
213 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
214 // read the end-of-list bracket
215 if (isBracketed && theBuffer.LinePtr[0] == '}') {
220 // otherwise read a node
221 if (!OK(aStatus, ReadNode (theBuffer, aChildNode)))
224 AddNode (aChildNode);
225 if (isBracketed == Standard_False)
229 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) {
231 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
234 if (theBuffer.LinePtr[0] == '{') {
236 if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
239 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
240 // read the end-of-list bracket
241 if (theBuffer.LinePtr[0] == '}') {
248 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center"))
250 aStatus = Scene().ReadXYZ (theBuffer, aCenter,
251 Standard_True, Standard_False);
253 aStatus = VrmlData_VrmlFormatError;
256 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "rotation"))
258 if (OK(aStatus, Scene().ReadXYZ (theBuffer, aRotAxis,
259 Standard_False, Standard_False)))
261 if (aRotAxis.SquareModulus() < Precision::Confusion())
263 aStatus = Scene().ReadReal (theBuffer, aRotAngle,
264 Standard_False, Standard_False);
267 aStatus = VrmlData_VrmlFormatError;
270 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scale")) {
272 aStatus = Scene().ReadXYZ (theBuffer, aScale,
273 Standard_False, Standard_True);
275 aStatus = VrmlData_VrmlFormatError;
278 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scaleOrientation"))
280 if (OK(aStatus, Scene().ReadXYZ (theBuffer, aScaleAxis,
281 Standard_False, Standard_False)))
282 aStatus = Scene().ReadReal (theBuffer, aScaleAngle,
283 Standard_False, Standard_False);
285 aStatus = VrmlData_VrmlFormatError;
288 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "translation"))
290 aStatus = Scene().ReadXYZ (theBuffer, aTrans,
291 Standard_True, Standard_False);
293 aStatus = VrmlData_VrmlFormatError;
296 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) {
297 NCollection_List<TCollection_AsciiString> lstURL;
298 if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) {
299 NCollection_List<TCollection_AsciiString>::Iterator anIter (lstURL);
300 for (; anIter.More(); anIter.Next()) {
302 const TCollection_AsciiString& aFileName = anIter.Value();
303 if (!OK(aStatus, openFile (aStream, aFileName)))
305 VrmlData_Scene aScene (Scene().Allocator());
306 aScene.myLinearScale = Scene().myLinearScale;
307 aScene.myVrmlDir = Scene().myVrmlDir;
309 if (!OK(aStatus, aScene.Status()))
311 VrmlData_Scene::Iterator anIterN = aScene.GetIterator();
312 for (; anIterN.More(); anIterN.Next())
313 if (!anIterN.Value()->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
314 AddNode (anIterN.Value());
315 VrmlData_Scene::Iterator anAllIter(aScene.myAllNodes);
316 for (; anAllIter.More(); anAllIter.Next()) {
317 const Handle(VrmlData_Node)& aNode = anAllIter.Value();
318 if (aNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo)))
320 const_cast <VrmlData_Scene&> (Scene()).myAllNodes.Append (aNode);
321 aNode->myScene = &Scene();
322 // The name of the imported node should be prefixed by the URL
323 // because each name must remain unique in the global scene.
325 if (* aNode->Name() != '\0') {
327 strncpy (buf, aFileName.ToCString(), sizeof(buf));
328 char * ptr = strchr (buf, '.');
330 ptr = strchr (buf,'\0');
332 strncpy (ptr+1, aNode->Name(), (&buf[sizeof(buf)]-ptr)-2);
333 const size_t len = strlen(buf) + 1;
335 static_cast<char *> (Scene().Allocator()->Allocate (len));
337 aNode->myName = aNewName;
338 memcpy (aNewName, buf, len);
351 // Read the terminating (closing) brace
353 aStatus = readBrace (theBuffer);
355 // Check if the Bounding Box has been imported
356 if (aBoxSize.X() > -Precision::Confusion() &&
357 aBoxSize.Y() > -Precision::Confusion() &&
358 aBoxSize.Z() > -Precision::Confusion())
360 myBox.SetCenter (aBoxCenter);
361 myBox.SetHSize (aBoxSize*0.5);
364 // Create the corresponding transformation.
365 gp_Trsf tRot, tCentInv;
366 myTrsf.SetTranslation(aTrans+aCenter);
367 gp_Ax1 aRotation (gp::Origin(), aRotAxis);
368 tRot.SetRotation(gp_Ax1 (gp::Origin(), aRotAxis), aRotAngle);
369 myTrsf.Multiply (tRot);
370 // Check that the scale is uniform (the same value in all 3 directions.
371 // Only in this case the scaling is applied.
372 const Standard_Real aScaleDiff[2] = {
373 aScale.X()-aScale.Y(),
374 aScale.X()-aScale.Z()
376 if (aScaleDiff[0]*aScaleDiff[0] + aScaleDiff[1]*aScaleDiff[1]
377 < Precision::Confusion())
380 tScale.SetScale (gp::Origin(), (aScale.X()+aScale.Y()+aScale.Z())/3.);
381 myTrsf.Multiply (tScale);
383 tCentInv.SetTranslation (aCenter.Reversed());
384 myTrsf.Multiply (tCentInv);
390 //=======================================================================
393 //=======================================================================
395 void VrmlData_Group::Shape (TopoDS_Shape& theShape,
396 VrmlData_DataMapOfShapeAppearance * pMapApp)
398 VrmlData_Scene::createShape (theShape, myNodes, pMapApp);
399 theShape.Location(myTrsf);
402 //=======================================================================
403 //function : openFile
405 //=======================================================================
407 VrmlData_ErrorStatus VrmlData_Group::openFile
408 (Standard_IStream& theStream,
409 const TCollection_AsciiString& theFilename)
411 ifstream& aStream = static_cast<ifstream&> (theStream);
412 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
413 NCollection_List<TCollection_ExtendedString>::Iterator aDirIter =
414 Scene().VrmlDirIterator();
415 for (; aDirIter.More(); aDirIter.Next()) {
416 if (!aDirIter.Value().IsAscii())
418 const TCollection_AsciiString aFullName =
419 TCollection_AsciiString (aDirIter.Value()) + theFilename;
420 aStream.open (aFullName.ToCString(), ios::in);
424 aStatus = VrmlData_StatusOK;
428 if (aStatus == VrmlData_EmptyData) {
429 aStream.open (theFilename.ToCString(), ios::in);
431 aStatus = VrmlData_StatusOK;
433 if (aStatus == VrmlData_EmptyData)
434 aStatus = VrmlData_CannotOpenFile;
438 //=======================================================================
441 //=======================================================================
443 VrmlData_ErrorStatus VrmlData_Group::Write (const char * thePrefix) const
445 VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
446 if (myNodes.IsEmpty() == Standard_False) {
447 const VrmlData_Scene& aScene = Scene();
448 Standard_Boolean isTransform = myIsTransform;
449 if (isTransform && myTrsf.Form() == gp_Identity)
450 isTransform = Standard_False;
451 static const char * header[2] = { "Group {" , "Transform {" };
452 if (OK (aStatus, aScene.WriteLine (thePrefix, header[isTransform ? 1 : 0],
456 if (OK(aStatus) && aScene.IsDummyWrite() == Standard_False)
458 const gp_XYZ aBoxCorner[2] = {
462 // Check that the box is not void
463 if (aBoxCorner[0].X() < aBoxCorner[1].X() + Precision::Confusion()) {
464 sprintf (buf, "bboxCenter %.9g %.9g %.9g",
465 0.5 * (aBoxCorner[0].X() + aBoxCorner[1].X()),
466 0.5 * (aBoxCorner[0].Y() + aBoxCorner[1].Y()),
467 0.5 * (aBoxCorner[0].Z() + aBoxCorner[1].Z()));
468 aStatus = aScene.WriteLine (buf);
470 sprintf (buf, "bboxSize %.9g %.9g %.9g",
471 aBoxCorner[1].X() - aBoxCorner[0].X(),
472 aBoxCorner[1].Y() - aBoxCorner[0].Y(),
473 aBoxCorner[1].Z() - aBoxCorner[0].Z());
474 aStatus = aScene.WriteLine (buf);
478 if (OK(aStatus) && isTransform && aScene.IsDummyWrite() == Standard_False)
481 const Standard_Real aScaleFactor = myTrsf.ScaleFactor();
482 if ((aScaleFactor - 1.)*(aScaleFactor - 1.) >
483 0.0001*Precision::Confusion())
485 sprintf (buf, "scale %.12g %.12g %.12g",
486 aScaleFactor, aScaleFactor, aScaleFactor);
487 aStatus = aScene.WriteLine (buf);
490 // Output the Translation
491 const gp_XYZ& aTrans = myTrsf.TranslationPart();
492 if (aTrans.SquareModulus() > 0.0001*Precision::Confusion()) {
493 sprintf (buf, "translation %.12g %.12g %.12g",
494 aTrans.X(), aTrans.Y(), aTrans.Z());
495 aStatus = aScene.WriteLine (buf);
498 // Output the Rotation
500 Standard_Real anAngle;
501 if (myTrsf.GetRotation (anAxis, anAngle)) {
502 // output the Rotation
503 sprintf (buf, "rotation %.12g %.12g %.12g %.9g",
504 anAxis.X(), anAxis.Y(), anAxis.Z(), anAngle);
505 aStatus = aScene.WriteLine (buf);
511 aStatus = aScene.WriteLine ("children [", 0L, GlobalIndent());
513 VrmlData_ListOfNode::Iterator anIterChild (myNodes);
514 for (; anIterChild.More() && OK(aStatus); anIterChild.Next()) {
515 const Handle(VrmlData_Node)& aNode = anIterChild.Value();
516 aScene.WriteNode (0L, aNode);
520 aStatus = aScene.WriteLine ("]", 0L, -GlobalIndent());
523 aStatus = WriteClosing();