0031139: Data Exchange - fix misprint in RWObj_CafReader
[occt.git] / src / XCAFPrs / XCAFPrs_DocumentExplorer.cxx
1 // Author: Kirill Gavrilov
2 // Copyright (c) 2017-2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <XCAFPrs_DocumentExplorer.hxx>
16
17 #include <TDF_Tool.hxx>
18 #include <TDocStd_Document.hxx>
19 #include <XCAFDoc_ColorTool.hxx>
20 #include <XCAFDoc_DocumentTool.hxx>
21 #include <XCAFDoc_ShapeTool.hxx>
22 #include <XCAFDoc_VisMaterialTool.hxx>
23 #include <XCAFPrs_DocumentIdIterator.hxx>
24
25 namespace
26 {
27   //! Return merged style for the child node.
28   static XCAFPrs_Style mergedStyle (const Handle(XCAFDoc_ColorTool)& theColorTool,
29                                     const Handle(XCAFDoc_VisMaterialTool)& theVisMatTool,
30                                     const XCAFPrs_Style& theParenStyle,
31                                     const TDF_Label& theLabel,
32                                     const TDF_Label& theRefLabel)
33   {
34     if (theColorTool.IsNull())
35     {
36       return theParenStyle;
37     }
38
39     XCAFPrs_Style aStyle = theParenStyle;
40     if (Handle(XCAFDoc_VisMaterial) aVisMat = theVisMatTool->GetShapeMaterial (theRefLabel))
41     {
42       aStyle.SetMaterial (aVisMat);
43     }
44     Quantity_ColorRGBA aColor;
45     if (theColorTool->GetColor (theRefLabel, XCAFDoc_ColorGen, aColor))
46     {
47       aStyle.SetColorCurv (aColor.GetRGB());
48       aStyle.SetColorSurf (aColor);
49     }
50     if (theColorTool->GetColor (theRefLabel, XCAFDoc_ColorSurf, aColor))
51     {
52       aStyle.SetColorSurf (aColor);
53     }
54     if (theColorTool->GetColor (theRefLabel, XCAFDoc_ColorCurv, aColor))
55     {
56       aStyle.SetColorCurv (aColor.GetRGB());
57     }
58
59     if (theLabel != theRefLabel)
60     {
61       // override Reference style with Instance style when defined (bad model?)
62       if (Handle(XCAFDoc_VisMaterial) aVisMat = theVisMatTool->GetShapeMaterial (theLabel))
63       {
64         aStyle.SetMaterial (aVisMat);
65       }
66       if (theColorTool->GetColor (theLabel, XCAFDoc_ColorGen, aColor))
67       {
68         aStyle.SetColorCurv (aColor.GetRGB());
69         aStyle.SetColorSurf (aColor);
70       }
71       if (theColorTool->GetColor (theLabel, XCAFDoc_ColorSurf, aColor))
72       {
73         aStyle.SetColorSurf (aColor);
74       }
75       if (theColorTool->GetColor (theLabel, XCAFDoc_ColorCurv, aColor))
76       {
77         aStyle.SetColorCurv (aColor.GetRGB());
78       }
79     }
80
81     return aStyle;
82   }
83 }
84
85 // =======================================================================
86 // function : DefineChildId
87 // purpose  :
88 // =======================================================================
89 TCollection_AsciiString XCAFPrs_DocumentExplorer::DefineChildId (const TDF_Label& theLabel,
90                                                                  const TCollection_AsciiString& theParentId)
91 {
92   TCollection_AsciiString anEntryId;
93   TDF_Tool::Entry (theLabel, anEntryId);
94   return !theParentId.IsEmpty()
95         ? theParentId + "/" + anEntryId + "."
96         : anEntryId + ".";
97 }
98
99 // =======================================================================
100 // function : FindLabelFromPathId
101 // purpose  :
102 // =======================================================================
103 TDF_Label XCAFPrs_DocumentExplorer::FindLabelFromPathId (const Handle(TDocStd_Document)& theDocument,
104                                                          const TCollection_AsciiString& theId,
105                                                          TopLoc_Location& theParentLocation,
106                                                          TopLoc_Location& theLocation)
107 {
108   theParentLocation = TopLoc_Location();
109   theLocation = TopLoc_Location();
110   TDF_Label anInstanceLabel;
111   for (XCAFPrs_DocumentIdIterator anPathIter (theId); anPathIter.More();)
112   {
113     TDF_Label aSubLabel;
114     {
115       const TCollection_AsciiString& anOcafId = anPathIter.Value();
116       TDF_Tool::Label (theDocument->Main().Data(), anOcafId, aSubLabel);
117       if (aSubLabel.IsNull())
118       {
119         return TDF_Label();
120       }
121     }
122
123     anPathIter.Next();
124     if (!anPathIter.More())
125     {
126       theParentLocation = theLocation;
127     }
128
129     TopLoc_Location aLocTrsf = XCAFDoc_ShapeTool::GetLocation (aSubLabel);
130     theLocation = theLocation * aLocTrsf;
131     anInstanceLabel = aSubLabel;
132   }
133   return anInstanceLabel;
134 }
135
136 // =======================================================================
137 // function : FindShapeFromPathId
138 // purpose  :
139 // =======================================================================
140 TopoDS_Shape XCAFPrs_DocumentExplorer::FindShapeFromPathId (const Handle(TDocStd_Document)& theDocument,
141                                                             const TCollection_AsciiString& theId)
142 {
143   TopLoc_Location aLocation;
144   TDF_Label anInstanceLabel = FindLabelFromPathId (theDocument, theId, aLocation);
145   if (anInstanceLabel.IsNull())
146   {
147     return TopoDS_Shape();
148   }
149
150   TDF_Label aRefLabel = anInstanceLabel;
151   XCAFDoc_ShapeTool::GetReferredShape (anInstanceLabel, aRefLabel);
152   if (aRefLabel.IsNull())
153   {
154     return TopoDS_Shape();
155   }
156
157   TopoDS_Shape aShape = XCAFDoc_ShapeTool::GetShape (aRefLabel);
158   if (aShape.IsNull())
159   {
160     return TopoDS_Shape();
161   }
162
163   aShape.Location (aLocation);
164   return aShape;
165 }
166
167 // =======================================================================
168 // function : XCAFPrs_DocumentExplorer
169 // purpose  :
170 // =======================================================================
171 XCAFPrs_DocumentExplorer::XCAFPrs_DocumentExplorer()
172 : myTop (-1),
173   myHasMore (Standard_False),
174   myFlags (XCAFPrs_DocumentExplorerFlags_None)
175 {
176   //
177 }
178
179 // =======================================================================
180 // function : XCAFPrs_DocumentExplorer
181 // purpose  :
182 // =======================================================================
183 XCAFPrs_DocumentExplorer::XCAFPrs_DocumentExplorer (const Handle(TDocStd_Document)& theDocument,
184                                                     const XCAFPrs_DocumentExplorerFlags theFlags,
185                                                     const XCAFPrs_Style& theDefStyle)
186 : myTop (-1),
187   myHasMore (Standard_False),
188   myFlags (XCAFPrs_DocumentExplorerFlags_None)
189 {
190   Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (theDocument->Main());
191   TDF_LabelSequence aRootLabels;
192   aShapeTool->GetFreeShapes (aRootLabels);
193   Init (theDocument, aRootLabels, theFlags, theDefStyle);
194 }
195
196 // =======================================================================
197 // function : XCAFPrs_DocumentExplorer
198 // purpose  :
199 // =======================================================================
200 XCAFPrs_DocumentExplorer::XCAFPrs_DocumentExplorer (const Handle(TDocStd_Document)& theDocument,
201                                                     const TDF_LabelSequence& theRoots,
202                                                     const XCAFPrs_DocumentExplorerFlags theFlags,
203                                                     const XCAFPrs_Style& theDefStyle)
204 : myTop (-1),
205   myHasMore (Standard_False),
206   myFlags (XCAFPrs_DocumentExplorerFlags_None)
207 {
208   Init (theDocument, theRoots, theFlags, theDefStyle);
209 }
210
211 // =======================================================================
212 // function : Init
213 // purpose  :
214 // =======================================================================
215 void XCAFPrs_DocumentExplorer::Init (const Handle(TDocStd_Document)& theDocument,
216                                      const TDF_Label& theRoot,
217                                      const XCAFPrs_DocumentExplorerFlags theFlags,
218                                      const XCAFPrs_Style& theDefStyle)
219 {
220   TDF_LabelSequence aSeq;
221   aSeq.Append (theRoot);
222   Init (theDocument, aSeq, theFlags, theDefStyle);
223 }
224
225 // =======================================================================
226 // function : Init
227 // purpose  :
228 // =======================================================================
229 void XCAFPrs_DocumentExplorer::Init (const Handle(TDocStd_Document)& theDocument,
230                                      const TDF_LabelSequence& theRoots,
231                                      const XCAFPrs_DocumentExplorerFlags theFlags,
232                                      const XCAFPrs_Style& theDefStyle)
233 {
234   if ((theFlags & XCAFPrs_DocumentExplorerFlags_NoStyle) == 0)
235   {
236     myColorTool = XCAFDoc_DocumentTool::ColorTool (theDocument->Main());
237     myVisMatTool = XCAFDoc_DocumentTool::VisMaterialTool (theDocument->Main());
238   }
239   else
240   {
241     myColorTool.Nullify();
242     myVisMatTool.Nullify();
243   }
244
245   myDefStyle  = theDefStyle;
246   myRoots     = theRoots;
247   myRootIter  = TDF_LabelSequence::Iterator (myRoots);
248   myFlags     = theFlags;
249   initRoot();
250 }
251
252 // =======================================================================
253 // function : initRoot
254 // purpose  :
255 // =======================================================================
256 void XCAFPrs_DocumentExplorer::initRoot()
257 {
258   for (;;)
259   {
260     // reset the stack
261     for (Standard_Integer aStackIter = 0; aStackIter <= myTop; ++aStackIter)
262     {
263       myNodeStack.SetValue (aStackIter, XCAFPrs_DocumentNode());
264     }
265     myTop = -1;
266     if (!myRootIter.More())
267     {
268       myHasMore = Standard_False;
269       initCurrent (Standard_False);
270       return;
271     }
272
273     const TDF_Label& aRootLab = myRootIter.Value();
274     if (aRootLab.IsNull())
275     {
276       // assert - invalid input
277       //Standard_ProgramError::Raise ("XCAFPrs_DocumentExplorer - NULL label in the input");
278       myRootIter.Next();
279       continue;
280     }
281
282     myHasMore = Standard_True;
283     TDF_Label aRefLabel = aRootLab;
284     XCAFDoc_ShapeTool::GetReferredShape (aRootLab, aRefLabel);
285     if (XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
286     {
287       Next();
288     }
289     else
290     {
291       initCurrent (Standard_False);
292     }
293     return;
294   }
295 }
296
297 // =======================================================================
298 // function : initCurrent
299 // purpose  :
300 // =======================================================================
301 void XCAFPrs_DocumentExplorer::initCurrent (Standard_Boolean theIsAssmebly)
302 {
303   myCurrent = XCAFPrs_DocumentNode();
304   if (theIsAssmebly)
305   {
306     if (myTop < 0)
307     {
308       Standard_ProgramError::Raise ("XCAFPrs_DocumentExplorer - internal error");
309     }
310     myCurrent = myNodeStack.Value (myTop);
311   }
312   else if (myTop < 0)
313   {
314     if (!myRootIter.More())
315     {
316       return;
317     }
318
319     myCurrent.Label    = myRootIter.Value();
320     myCurrent.RefLabel = myCurrent.Label;
321     XCAFDoc_ShapeTool::GetReferredShape (myCurrent.Label, myCurrent.RefLabel);
322     myCurrent.LocalTrsf= XCAFDoc_ShapeTool::GetLocation (myCurrent.Label);
323     myCurrent.Location = myCurrent.LocalTrsf;
324     myCurrent.Style    = mergedStyle (myColorTool, myVisMatTool, myDefStyle, myCurrent.Label, myCurrent.RefLabel);
325     myCurrent.Id       = DefineChildId (myCurrent.Label, TCollection_AsciiString());
326   }
327   else
328   {
329     const XCAFPrs_DocumentNode& aTopNodeInStack = myNodeStack.Value (myTop);
330     myCurrent.Label    = aTopNodeInStack.ChildIter.Value();
331     myCurrent.RefLabel = myCurrent.Label;
332     XCAFDoc_ShapeTool::GetReferredShape (myCurrent.Label, myCurrent.RefLabel);
333     myCurrent.LocalTrsf= XCAFDoc_ShapeTool::GetLocation (myCurrent.Label);
334     myCurrent.Location = aTopNodeInStack.Location * myCurrent.LocalTrsf;
335     myCurrent.Style    = mergedStyle (myColorTool, myVisMatTool, aTopNodeInStack.Style, myCurrent.Label, myCurrent.RefLabel);
336     myCurrent.Id       = DefineChildId (myCurrent.Label, aTopNodeInStack.Id);
337   }
338 }
339
340 // =======================================================================
341 // function : Next
342 // purpose  :
343 // =======================================================================
344 void XCAFPrs_DocumentExplorer::Next()
345 {
346   if (!myHasMore)
347   {
348     Standard_ProgramError::Raise ("XCAFPrs_DocumentExplorer::Next() - out of range");
349     return; // assert
350   }
351
352   if (myTop < 0)
353   {
354     const TDF_Label& aRootLab  = myRootIter.Value();
355     TDF_Label        aRefLabel = aRootLab;
356     XCAFDoc_ShapeTool::GetReferredShape (aRootLab, aRefLabel);
357     if (!XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
358     {
359       // already visited once
360       myRootIter.Next();
361       initRoot();
362       return;
363     }
364
365     // push and try to find
366     myTop = 0;
367     XCAFPrs_DocumentNode aNodeInStack;
368     aNodeInStack.IsAssembly = Standard_True;
369     aNodeInStack.Label      = aRootLab;
370     aNodeInStack.RefLabel   = aRefLabel;
371     aNodeInStack.ChildIter  = TDF_ChildIterator (aNodeInStack.RefLabel);
372     aNodeInStack.LocalTrsf  = XCAFDoc_ShapeTool::GetLocation (aNodeInStack.Label);
373     aNodeInStack.Location   = aNodeInStack.LocalTrsf;
374     aNodeInStack.Style      = mergedStyle (myColorTool, myVisMatTool, myDefStyle, aNodeInStack.Label, aNodeInStack.RefLabel);
375     aNodeInStack.Id         = DefineChildId (aNodeInStack.Label, TCollection_AsciiString());
376     myNodeStack.SetValue (0, aNodeInStack);
377     if ((myFlags & XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes) == 0)
378     {
379       initCurrent (Standard_True);
380       return;
381     }
382   }
383   else
384   {
385     if (!myCurrent.IsAssembly)
386     {
387       myNodeStack.ChangeValue (myTop).ChildIter.Next();
388     }
389   }
390
391   for (;;)
392   {
393     if (myNodeStack.Value (myTop).ChildIter.More())
394     {
395       const TDF_Label& aNodeTop = myNodeStack.Value (myTop).ChildIter.Value();
396       if (aNodeTop.IsNull()
397        || (!aNodeTop.HasChild() && !aNodeTop.HasAttribute()))
398       {
399         myNodeStack.ChangeValue (myTop).ChildIter.Next();
400         continue;
401       }
402
403       TDF_Label aRefLabel = aNodeTop;
404       XCAFDoc_ShapeTool::GetReferredShape (aNodeTop, aRefLabel);
405       if (!XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
406       {
407         myHasMore = Standard_True;
408         initCurrent (Standard_False);
409         return;
410       }
411       else if (aRefLabel.HasAttribute()
412             || aRefLabel.HasChild())
413       {
414         const XCAFPrs_DocumentNode& aParent = myNodeStack.Value (myTop);
415         ++myTop;
416
417         XCAFPrs_DocumentNode aNodeInStack;
418         aNodeInStack.IsAssembly = Standard_True;
419         aNodeInStack.Label      = aNodeTop;
420         aNodeInStack.RefLabel   = aRefLabel;
421         aNodeInStack.LocalTrsf  = XCAFDoc_ShapeTool::GetLocation (aNodeInStack.Label);
422         aNodeInStack.Location   = aParent.Location * aNodeInStack.LocalTrsf;
423         aNodeInStack.Style      = mergedStyle (myColorTool, myVisMatTool, aParent.Style, aNodeInStack.Label, aNodeInStack.RefLabel);
424         aNodeInStack.Id         = DefineChildId (aNodeInStack.Label, aParent.Id);
425         aNodeInStack.ChildIter  = TDF_ChildIterator (aNodeInStack.RefLabel);
426         myNodeStack.SetValue (myTop, aNodeInStack);
427         if ((myFlags & XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes) == 0)
428         {
429           initCurrent (Standard_True);
430           return;
431         }
432       }
433       else
434       {
435         myNodeStack.ChangeValue (myTop).ChildIter.Next();
436       }
437     }
438     else
439     {
440       myNodeStack.SetValue (myTop, XCAFPrs_DocumentNode());
441       --myTop;
442       if (myTop < 0)
443       {
444         myRootIter.Next();
445         initRoot();
446         return;
447       }
448
449       myNodeStack.ChangeValue (myTop).ChildIter.Next();
450     }
451   }
452 }