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