Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2006-11-06 |
2 | // Created by: Alexander GRIGORIEV | |
973c2be1 | 3 | // Copyright (c) 2006-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 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 | |
973c2be1 | 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. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
7fd59977 | 15 | |
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> | |
24 | #include <gp_Ax1.hxx> | |
25 | ||
26 | #ifdef WNT | |
27 | #define _CRT_SECURE_NO_DEPRECATE | |
28 | #pragma warning (disable:4996) | |
29 | #endif | |
30 | ||
31 | IMPLEMENT_STANDARD_HANDLE (VrmlData_Group, VrmlData_Node) | |
32 | IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Group, VrmlData_Node) | |
33 | ||
34 | //======================================================================= | |
35 | //function : VrmlData_Group | |
36 | //purpose : Constructor | |
37 | //======================================================================= | |
38 | ||
39 | VrmlData_Group::VrmlData_Group (const VrmlData_Scene& theScene, | |
40 | const char * theName, | |
41 | const Standard_Boolean isTransform) | |
42 | : VrmlData_Node (theScene, theName), | |
43 | myIsTransform (isTransform), | |
44 | myNodes (theScene.Allocator()) | |
45 | {} | |
46 | ||
47 | //======================================================================= | |
48 | //function : RemoveNode | |
49 | //purpose : | |
50 | //======================================================================= | |
51 | ||
52 | Standard_Boolean VrmlData_Group::RemoveNode | |
53 | (const Handle(VrmlData_Node)& theNode) | |
54 | { | |
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); | |
60 | break; | |
61 | } | |
62 | return aResult; | |
63 | } | |
64 | ||
65 | //======================================================================= | |
66 | //function : SetTransform | |
67 | //purpose : | |
68 | //======================================================================= | |
69 | ||
70 | Standard_Boolean VrmlData_Group::SetTransform (const gp_Trsf& theTrsf) | |
71 | { | |
72 | Standard_Boolean aResult (Standard_False); | |
73 | if (myIsTransform) { | |
74 | myTrsf = theTrsf; | |
75 | aResult = Standard_True; | |
76 | } | |
77 | return aResult; | |
78 | } | |
79 | ||
80 | //======================================================================= | |
81 | //function : VrmlData_Group::Clone | |
82 | //purpose : | |
83 | //======================================================================= | |
84 | ||
85 | Handle(VrmlData_Node) VrmlData_Group::Clone | |
86 | (const Handle(VrmlData_Node)& theOther) const | |
87 | { | |
88 | Handle(VrmlData_Group) aResult = | |
89 | Handle(VrmlData_Group)::DownCast (VrmlData_Node::Clone(theOther)); | |
90 | if (aResult.IsNull()) | |
91 | aResult = | |
92 | new VrmlData_Group (theOther.IsNull() ? Scene() : theOther->Scene(), | |
93 | Name(), myIsTransform); | |
94 | ||
95 | aResult->myIsTransform = myIsTransform; | |
96 | if (&aResult->Scene() == &Scene()) | |
97 | aResult->myNodes = myNodes; | |
98 | else { | |
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)); | |
107 | } | |
108 | } | |
109 | if (myIsTransform) | |
110 | aResult->SetTransform (myTrsf); | |
111 | aResult->SetBox (myBox); | |
112 | ||
113 | return aResult; | |
114 | } | |
115 | ||
116 | //======================================================================= | |
117 | //function : FindNode | |
118 | //purpose : | |
119 | //======================================================================= | |
120 | ||
121 | Handle(VrmlData_Node) VrmlData_Group::FindNode | |
122 | (const char * theName, | |
123 | gp_Trsf& theLocation) const | |
124 | { | |
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) | |
131 | { | |
132 | aResult = aNode; | |
133 | theLocation = myTrsf; | |
134 | break; | |
135 | } | |
136 | // Try a Group type of node | |
137 | if (aNode->IsKind(STANDARD_TYPE(VrmlData_Group))) | |
138 | { | |
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); | |
146 | break; | |
147 | } | |
148 | } | |
149 | } | |
150 | } | |
151 | } | |
152 | return aResult; | |
153 | } | |
154 | ||
155 | //======================================================================= | |
156 | //function : VrmlData_Group::Read | |
157 | //purpose : | |
158 | //======================================================================= | |
159 | ||
160 | VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer) | |
161 | { | |
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.); | |
167 | ||
168 | while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) | |
169 | { | |
170 | if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxCenter")) | |
171 | aStatus = Scene().ReadXYZ (theBuffer, aBoxCenter, | |
172 | Standard_True, Standard_False); | |
173 | ||
174 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "bboxSize")) | |
175 | aStatus = Scene().ReadXYZ (theBuffer, aBoxSize, | |
176 | Standard_True, Standard_False); | |
177 | ||
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))) | |
182 | break; | |
183 | if (theBuffer.LinePtr[0] == '[') { | |
184 | theBuffer.LinePtr++; | |
185 | if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) | |
186 | break; | |
187 | isBracketed = Standard_True; | |
188 | } | |
189 | ||
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] == ']') { | |
195 | theBuffer.LinePtr++; | |
196 | break; | |
197 | } | |
198 | // otherwise read a node | |
199 | if (!OK(aStatus, ReadNode (theBuffer, aChildNode))) | |
200 | break; | |
201 | AddNode (aChildNode); | |
202 | if (isBracketed == Standard_False) | |
203 | break; | |
204 | } | |
bd754989 V |
205 | } |
206 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") || | |
207 | VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) { | |
208 | Standard_Boolean isBracketed (Standard_False); | |
209 | // Read the opening bracket for the list of children | |
210 | if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) | |
211 | break; | |
212 | ||
213 | if (theBuffer.LinePtr[0] == '{') { | |
214 | theBuffer.LinePtr++; | |
215 | if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) | |
216 | break; | |
217 | isBracketed = Standard_True; | |
218 | } | |
219 | ||
220 | // Read the child nodes | |
221 | Handle(VrmlData_Node) aChildNode; | |
222 | while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) { | |
223 | // read the end-of-list bracket | |
224 | if (isBracketed && theBuffer.LinePtr[0] == '}') { | |
225 | theBuffer.LinePtr++; | |
226 | break; | |
227 | } | |
228 | ||
229 | // otherwise read a node | |
230 | if (!OK(aStatus, ReadNode (theBuffer, aChildNode))) | |
231 | break; | |
232 | ||
233 | AddNode (aChildNode); | |
234 | if (isBracketed == Standard_False) | |
235 | break; | |
236 | } | |
237 | } | |
238 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) { | |
239 | // Skip this tag | |
240 | if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) | |
241 | break; | |
242 | ||
243 | if (theBuffer.LinePtr[0] == '{') { | |
244 | theBuffer.LinePtr++; | |
245 | if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) | |
246 | break; | |
247 | ||
248 | while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) { | |
249 | // read the end-of-list bracket | |
250 | if (theBuffer.LinePtr[0] == '}') { | |
251 | theBuffer.LinePtr++; | |
252 | break; | |
253 | } | |
254 | theBuffer.LinePtr++; | |
255 | } | |
256 | } | |
7fd59977 | 257 | } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "center")) |
258 | if (myIsTransform) | |
259 | aStatus = Scene().ReadXYZ (theBuffer, aCenter, | |
260 | Standard_True, Standard_False); | |
261 | else { | |
262 | aStatus = VrmlData_VrmlFormatError; | |
263 | break; | |
264 | } | |
265 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "rotation")) | |
266 | if (myIsTransform) { | |
267 | if (OK(aStatus, Scene().ReadXYZ (theBuffer, aRotAxis, | |
268 | Standard_False, Standard_False))) | |
269 | { | |
270 | if (aRotAxis.SquareModulus() < Precision::Confusion()) | |
271 | aRotAxis.SetZ (1.0); | |
272 | aStatus = Scene().ReadReal (theBuffer, aRotAngle, | |
273 | Standard_False, Standard_False); | |
274 | } | |
275 | } else { | |
276 | aStatus = VrmlData_VrmlFormatError; | |
277 | break; | |
278 | } | |
4366363b | 279 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scaleOrientation")) |
7fd59977 | 280 | if (myIsTransform) { |
281 | if (OK(aStatus, Scene().ReadXYZ (theBuffer, aScaleAxis, | |
282 | Standard_False, Standard_False))) | |
283 | aStatus = Scene().ReadReal (theBuffer, aScaleAngle, | |
284 | Standard_False, Standard_False); | |
285 | } else { | |
286 | aStatus = VrmlData_VrmlFormatError; | |
287 | break; | |
288 | } | |
4366363b | 289 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "scale")) |
290 | if (myIsTransform) | |
291 | aStatus = Scene().ReadXYZ (theBuffer, aScale, | |
292 | Standard_False, Standard_True); | |
293 | else { | |
294 | aStatus = VrmlData_VrmlFormatError; | |
295 | break; | |
296 | } | |
7fd59977 | 297 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "translation")) |
298 | if (myIsTransform) | |
299 | aStatus = Scene().ReadXYZ (theBuffer, aTrans, | |
300 | Standard_True, Standard_False); | |
301 | else { | |
302 | aStatus = VrmlData_VrmlFormatError; | |
303 | break; | |
304 | } | |
305 | else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) { | |
306 | NCollection_List<TCollection_AsciiString> lstURL; | |
307 | if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) { | |
308 | NCollection_List<TCollection_AsciiString>::Iterator anIter (lstURL); | |
309 | for (; anIter.More(); anIter.Next()) { | |
310 | ifstream aStream; | |
311 | const TCollection_AsciiString& aFileName = anIter.Value(); | |
312 | if (!OK(aStatus, openFile (aStream, aFileName))) | |
313 | break; | |
314 | VrmlData_Scene aScene (Scene().Allocator()); | |
315 | aScene.myLinearScale = Scene().myLinearScale; | |
316 | aScene.myVrmlDir = Scene().myVrmlDir; | |
317 | aScene << aStream; | |
318 | if (!OK(aStatus, aScene.Status())) | |
319 | break; | |
320 | VrmlData_Scene::Iterator anIterN = aScene.GetIterator(); | |
321 | for (; anIterN.More(); anIterN.Next()) | |
322 | if (!anIterN.Value()->IsKind(STANDARD_TYPE(VrmlData_WorldInfo))) | |
323 | AddNode (anIterN.Value()); | |
324 | VrmlData_Scene::Iterator anAllIter(aScene.myAllNodes); | |
325 | for (; anAllIter.More(); anAllIter.Next()) { | |
326 | const Handle(VrmlData_Node)& aNode = anAllIter.Value(); | |
327 | if (aNode->IsKind(STANDARD_TYPE(VrmlData_WorldInfo))) | |
328 | continue; | |
329 | const_cast <VrmlData_Scene&> (Scene()).myAllNodes.Append (aNode); | |
330 | aNode->myScene = &Scene(); | |
331 | // The name of the imported node should be prefixed by the URL | |
332 | // because each name must remain unique in the global scene. | |
333 | if (aNode->Name()) | |
334 | if (* aNode->Name() != '\0') { | |
b6710675 | 335 | TCollection_AsciiString buf; |
336 | buf += aFileName; | |
337 | Standard_Integer aCharLocation = buf.Location (1, '.', 1, buf.Length()); | |
338 | if (aCharLocation != 0) | |
339 | { | |
340 | buf.Remove (aCharLocation, buf.Length() - aCharLocation + 1); | |
341 | } | |
342 | buf += '_'; | |
343 | buf += aNode->Name(); | |
344 | const size_t len = buf.Length(); | |
7fd59977 | 345 | char * aNewName = |
346 | static_cast<char *> (Scene().Allocator()->Allocate (len)); | |
347 | if (aNewName) { | |
348 | aNode->myName = aNewName; | |
b6710675 | 349 | memcpy (aNewName, buf.ToCString(), len); |
7fd59977 | 350 | } |
351 | } | |
352 | } | |
353 | } | |
354 | } | |
355 | } else | |
356 | break; | |
357 | ||
358 | if (!OK(aStatus)) | |
359 | break; | |
360 | } | |
361 | ||
362 | // Read the terminating (closing) brace | |
363 | if (OK(aStatus)) | |
364 | aStatus = readBrace (theBuffer); | |
365 | if (OK(aStatus)) { | |
366 | // Check if the Bounding Box has been imported | |
367 | if (aBoxSize.X() > -Precision::Confusion() && | |
368 | aBoxSize.Y() > -Precision::Confusion() && | |
369 | aBoxSize.Z() > -Precision::Confusion()) | |
370 | { | |
371 | myBox.SetCenter (aBoxCenter); | |
372 | myBox.SetHSize (aBoxSize*0.5); | |
373 | } | |
374 | if (myIsTransform) { | |
375 | // Create the corresponding transformation. | |
376 | gp_Trsf tRot, tCentInv; | |
377 | myTrsf.SetTranslation(aTrans+aCenter); | |
378 | gp_Ax1 aRotation (gp::Origin(), aRotAxis); | |
379 | tRot.SetRotation(gp_Ax1 (gp::Origin(), aRotAxis), aRotAngle); | |
380 | myTrsf.Multiply (tRot); | |
381 | // Check that the scale is uniform (the same value in all 3 directions. | |
382 | // Only in this case the scaling is applied. | |
383 | const Standard_Real aScaleDiff[2] = { | |
384 | aScale.X()-aScale.Y(), | |
385 | aScale.X()-aScale.Z() | |
386 | }; | |
387 | if (aScaleDiff[0]*aScaleDiff[0] + aScaleDiff[1]*aScaleDiff[1] | |
388 | < Precision::Confusion()) | |
389 | { | |
390 | gp_Trsf tScale; | |
391 | tScale.SetScale (gp::Origin(), (aScale.X()+aScale.Y()+aScale.Z())/3.); | |
392 | myTrsf.Multiply (tScale); | |
393 | } | |
394 | tCentInv.SetTranslation (aCenter.Reversed()); | |
395 | myTrsf.Multiply (tCentInv); | |
396 | } | |
397 | } | |
398 | return aStatus; | |
399 | } | |
400 | ||
401 | //======================================================================= | |
402 | //function : Shape | |
403 | //purpose : | |
404 | //======================================================================= | |
405 | ||
406 | void VrmlData_Group::Shape (TopoDS_Shape& theShape, | |
407 | VrmlData_DataMapOfShapeAppearance * pMapApp) | |
408 | { | |
409 | VrmlData_Scene::createShape (theShape, myNodes, pMapApp); | |
410 | theShape.Location(myTrsf); | |
411 | } | |
412 | ||
413 | //======================================================================= | |
414 | //function : openFile | |
415 | //purpose : | |
416 | //======================================================================= | |
417 | ||
418 | VrmlData_ErrorStatus VrmlData_Group::openFile | |
419 | (Standard_IStream& theStream, | |
420 | const TCollection_AsciiString& theFilename) | |
421 | { | |
422 | ifstream& aStream = static_cast<ifstream&> (theStream); | |
423 | VrmlData_ErrorStatus aStatus (VrmlData_EmptyData); | |
424 | NCollection_List<TCollection_ExtendedString>::Iterator aDirIter = | |
425 | Scene().VrmlDirIterator(); | |
426 | for (; aDirIter.More(); aDirIter.Next()) { | |
427 | if (!aDirIter.Value().IsAscii()) | |
428 | continue; | |
429 | const TCollection_AsciiString aFullName = | |
430 | TCollection_AsciiString (aDirIter.Value()) + theFilename; | |
431 | aStream.open (aFullName.ToCString(), ios::in); | |
432 | if (aStream.fail()) | |
433 | aStream.clear(); | |
434 | else { | |
435 | aStatus = VrmlData_StatusOK; | |
436 | break; | |
437 | } | |
438 | } | |
439 | if (aStatus == VrmlData_EmptyData) { | |
440 | aStream.open (theFilename.ToCString(), ios::in); | |
441 | if (!aStream.fail()) | |
442 | aStatus = VrmlData_StatusOK; | |
443 | } | |
444 | if (aStatus == VrmlData_EmptyData) | |
445 | aStatus = VrmlData_CannotOpenFile; | |
446 | return aStatus; | |
447 | } | |
448 | ||
449 | //======================================================================= | |
450 | //function : Write | |
451 | //purpose : | |
452 | //======================================================================= | |
453 | ||
454 | VrmlData_ErrorStatus VrmlData_Group::Write (const char * thePrefix) const | |
455 | { | |
456 | VrmlData_ErrorStatus aStatus (VrmlData_StatusOK); | |
457 | if (myNodes.IsEmpty() == Standard_False) { | |
458 | const VrmlData_Scene& aScene = Scene(); | |
459 | Standard_Boolean isTransform = myIsTransform; | |
460 | if (isTransform && myTrsf.Form() == gp_Identity) | |
461 | isTransform = Standard_False; | |
462 | static const char * header[2] = { "Group {" , "Transform {" }; | |
463 | if (OK (aStatus, aScene.WriteLine (thePrefix, header[isTransform ? 1 : 0], | |
464 | GlobalIndent()))) | |
465 | { | |
466 | char buf[240]; | |
467 | if (OK(aStatus) && aScene.IsDummyWrite() == Standard_False) | |
468 | { | |
469 | const gp_XYZ aBoxCorner[2] = { | |
470 | myBox.CornerMin(), | |
471 | myBox.CornerMax() | |
472 | }; | |
473 | // Check that the box is not void | |
474 | if (aBoxCorner[0].X() < aBoxCorner[1].X() + Precision::Confusion()) { | |
91322f44 | 475 | Sprintf (buf, "bboxCenter %.9g %.9g %.9g", |
7fd59977 | 476 | 0.5 * (aBoxCorner[0].X() + aBoxCorner[1].X()), |
477 | 0.5 * (aBoxCorner[0].Y() + aBoxCorner[1].Y()), | |
478 | 0.5 * (aBoxCorner[0].Z() + aBoxCorner[1].Z())); | |
479 | aStatus = aScene.WriteLine (buf); | |
480 | if (OK(aStatus)) { | |
91322f44 | 481 | Sprintf (buf, "bboxSize %.9g %.9g %.9g", |
7fd59977 | 482 | aBoxCorner[1].X() - aBoxCorner[0].X(), |
483 | aBoxCorner[1].Y() - aBoxCorner[0].Y(), | |
484 | aBoxCorner[1].Z() - aBoxCorner[0].Z()); | |
485 | aStatus = aScene.WriteLine (buf); | |
486 | } | |
487 | } | |
488 | } | |
489 | if (OK(aStatus) && isTransform && aScene.IsDummyWrite() == Standard_False) | |
490 | { | |
491 | // Output the Scale | |
492 | const Standard_Real aScaleFactor = myTrsf.ScaleFactor(); | |
493 | if ((aScaleFactor - 1.)*(aScaleFactor - 1.) > | |
494 | 0.0001*Precision::Confusion()) | |
495 | { | |
91322f44 | 496 | Sprintf (buf, "scale %.12g %.12g %.12g", |
7fd59977 | 497 | aScaleFactor, aScaleFactor, aScaleFactor); |
498 | aStatus = aScene.WriteLine (buf); | |
499 | } | |
500 | ||
501 | // Output the Translation | |
502 | const gp_XYZ& aTrans = myTrsf.TranslationPart(); | |
503 | if (aTrans.SquareModulus() > 0.0001*Precision::Confusion()) { | |
91322f44 | 504 | Sprintf (buf, "translation %.12g %.12g %.12g", |
7fd59977 | 505 | aTrans.X(), aTrans.Y(), aTrans.Z()); |
506 | aStatus = aScene.WriteLine (buf); | |
507 | } | |
508 | ||
509 | // Output the Rotation | |
510 | gp_XYZ anAxis; | |
511 | Standard_Real anAngle; | |
512 | if (myTrsf.GetRotation (anAxis, anAngle)) { | |
513 | // output the Rotation | |
91322f44 | 514 | Sprintf (buf, "rotation %.12g %.12g %.12g %.9g", |
7fd59977 | 515 | anAxis.X(), anAxis.Y(), anAxis.Z(), anAngle); |
516 | aStatus = aScene.WriteLine (buf); | |
517 | } | |
518 | } | |
519 | ||
520 | if (OK(aStatus)) { | |
521 | ||
522 | aStatus = aScene.WriteLine ("children [", 0L, GlobalIndent()); | |
523 | ||
524 | VrmlData_ListOfNode::Iterator anIterChild (myNodes); | |
525 | for (; anIterChild.More() && OK(aStatus); anIterChild.Next()) { | |
526 | const Handle(VrmlData_Node)& aNode = anIterChild.Value(); | |
527 | aScene.WriteNode (0L, aNode); | |
528 | } | |
529 | ||
530 | if (OK(aStatus)) { | |
531 | aStatus = aScene.WriteLine ("]", 0L, -GlobalIndent()); | |
532 | } | |
533 | } | |
534 | aStatus = WriteClosing(); | |
535 | } | |
536 | } | |
537 | return aStatus; | |
538 | } |