c5fbb708911cb44d8c5a0dbf9af703569578dc1c
[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   ///myColorTool = theColorTool;
234   myDefStyle  = theDefStyle;
235   myRoots     = theRoots;
236   myRootIter  = TDF_LabelSequence::Iterator (myRoots);
237   myFlags     = theFlags;
238   initRoot();
239 }
240
241 // =======================================================================
242 // function : initRoot
243 // purpose  :
244 // =======================================================================
245 void XCAFPrs_DocumentExplorer::initRoot()
246 {
247   for (;;)
248   {
249     // reset the stack
250     for (Standard_Integer aStackIter = 0; aStackIter <= myTop; ++aStackIter)
251     {
252       myNodeStack.SetValue (aStackIter, XCAFPrs_DocumentNode());
253     }
254     myTop = -1;
255     if (!myRootIter.More())
256     {
257       myHasMore = Standard_False;
258       initCurrent (Standard_False);
259       return;
260     }
261
262     const TDF_Label& aRootLab = myRootIter.Value();
263     if (aRootLab.IsNull())
264     {
265       // assert - invalid input
266       //Standard_ProgramError::Raise ("CadDocumentExplorer - NULL label in the input");
267       myRootIter.Next();
268       continue;
269     }
270
271     myHasMore = Standard_True;
272     TDF_Label aRefLabel = aRootLab;
273     XCAFDoc_ShapeTool::GetReferredShape (aRootLab, aRefLabel);
274     if (XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
275     {
276       Next();
277     }
278     else
279     {
280       initCurrent (Standard_False);
281     }
282     return;
283   }
284 }
285
286 // =======================================================================
287 // function : initCurrent
288 // purpose  :
289 // =======================================================================
290 void XCAFPrs_DocumentExplorer::initCurrent (Standard_Boolean theIsAssmebly)
291 {
292   myCurrent = XCAFPrs_DocumentNode();
293   if (theIsAssmebly)
294   {
295     if (myTop < 0)
296     {
297       Standard_ProgramError::Raise ("CadDocumentExplorer - internal error");
298     }
299     myCurrent = myNodeStack.Value (myTop);
300   }
301   else if (myTop < 0)
302   {
303     if (!myRootIter.More())
304     {
305       return;
306     }
307
308     myCurrent.Label    = myRootIter.Value();
309     myCurrent.RefLabel = myCurrent.Label;
310     XCAFDoc_ShapeTool::GetReferredShape (myCurrent.Label, myCurrent.RefLabel);
311     myCurrent.LocalTrsf= XCAFDoc_ShapeTool::GetLocation (myCurrent.Label);
312     myCurrent.Location = myCurrent.LocalTrsf;
313     myCurrent.Style    = mergedStyle (myColorTool, myDefStyle, myCurrent.Label, myCurrent.RefLabel);
314     myCurrent.Id       = DefineChildId (myCurrent.Label, TCollection_AsciiString());
315   }
316   else
317   {
318     const XCAFPrs_DocumentNode& aTopNodeInStack = myNodeStack.Value (myTop);
319     myCurrent.Label    = aTopNodeInStack.ChildIter.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 = aTopNodeInStack.Location * myCurrent.LocalTrsf;
324     myCurrent.Style    = mergedStyle (myColorTool, aTopNodeInStack.Style, myCurrent.Label, myCurrent.RefLabel);
325     myCurrent.Id       = DefineChildId (myCurrent.Label, aTopNodeInStack.Id);
326   }
327 }
328
329 // =======================================================================
330 // function : Next
331 // purpose  :
332 // =======================================================================
333 void XCAFPrs_DocumentExplorer::Next()
334 {
335   if (!myHasMore)
336   {
337     Standard_ProgramError::Raise ("CadDocumentExplorer::Next() - out of range");
338     return; // assert
339   }
340
341   if (myTop < 0)
342   {
343     const TDF_Label& aRootLab  = myRootIter.Value();
344     TDF_Label        aRefLabel = aRootLab;
345     XCAFDoc_ShapeTool::GetReferredShape (aRootLab, aRefLabel);
346     if (!XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
347     {
348       // already visited once
349       myRootIter.Next();
350       initRoot();
351       return;
352     }
353
354     // push and try to find
355     myTop = 0;
356     XCAFPrs_DocumentNode aNodeInStack;
357     aNodeInStack.IsAssembly = Standard_True;
358     aNodeInStack.Label      = aRootLab;
359     aNodeInStack.RefLabel   = aRefLabel;
360     aNodeInStack.ChildIter  = TDF_ChildIterator (aNodeInStack.RefLabel);
361     aNodeInStack.LocalTrsf  = XCAFDoc_ShapeTool::GetLocation (aNodeInStack.Label);
362     aNodeInStack.Location   = aNodeInStack.LocalTrsf;
363     aNodeInStack.Style      = mergedStyle (myColorTool, myDefStyle, aNodeInStack.Label, aNodeInStack.RefLabel);
364     aNodeInStack.Id         = DefineChildId (aNodeInStack.Label, TCollection_AsciiString());
365     myNodeStack.SetValue (0, aNodeInStack);
366     if ((myFlags & XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes) == 0)
367     {
368       initCurrent (Standard_True);
369       return;
370     }
371   }
372   else
373   {
374     if (!myCurrent.IsAssembly)
375     {
376       myNodeStack.ChangeValue (myTop).ChildIter.Next();
377     }
378   }
379
380   for (;;)
381   {
382     if (myNodeStack.Value (myTop).ChildIter.More())
383     {
384       const TDF_Label& aNodeTop = myNodeStack.Value (myTop).ChildIter.Value();
385       if (aNodeTop.IsNull()
386        || (!aNodeTop.HasChild() && !aNodeTop.HasAttribute()))
387       {
388         myNodeStack.ChangeValue (myTop).ChildIter.Next();
389         continue;
390       }
391
392       TDF_Label aRefLabel = aNodeTop;
393       XCAFDoc_ShapeTool::GetReferredShape (aNodeTop, aRefLabel);
394       if (!XCAFDoc_ShapeTool::IsAssembly (aRefLabel))
395       {
396         myHasMore = Standard_True;
397         initCurrent (Standard_False);
398         return;
399       }
400       else if (aRefLabel.HasAttribute()
401             || aRefLabel.HasChild())
402       {
403         const XCAFPrs_DocumentNode& aParent = myNodeStack.Value (myTop);
404         ++myTop;
405
406         XCAFPrs_DocumentNode aNodeInStack;
407         aNodeInStack.IsAssembly = Standard_True;
408         aNodeInStack.Label      = aNodeTop;
409         aNodeInStack.RefLabel   = aRefLabel;
410         aNodeInStack.LocalTrsf  = XCAFDoc_ShapeTool::GetLocation (aNodeInStack.Label);
411         aNodeInStack.Location   = aParent.Location * aNodeInStack.LocalTrsf;
412         aNodeInStack.Style      = mergedStyle (myColorTool, aParent.Style, aNodeInStack.Label, aNodeInStack.RefLabel);
413         aNodeInStack.Id         = DefineChildId (aNodeInStack.Label, aParent.Id);
414         aNodeInStack.ChildIter  = TDF_ChildIterator (aNodeInStack.RefLabel);
415         myNodeStack.SetValue (myTop, aNodeInStack);
416         if ((myFlags & XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes) == 0)
417         {
418           initCurrent (Standard_True);
419           return;
420         }
421       }
422       else
423       {
424         myNodeStack.ChangeValue (myTop).ChildIter.Next();
425       }
426     }
427     else
428     {
429       myNodeStack.SetValue (myTop, XCAFPrs_DocumentNode());
430       --myTop;
431       if (myTop < 0)
432       {
433         myRootIter.Next();
434         initRoot();
435         return;
436       }
437
438       myNodeStack.ChangeValue (myTop).ChildIter.Next();
439     }
440   }
441 }