fc552d84 |
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 | { |
f6abd02c |
224 | if ((theFlags & XCAFPrs_DocumentExplorerFlags_NoStyle) == 0) |
fc552d84 |
225 | { |
226 | myColorTool = XCAFDoc_DocumentTool::ColorTool (theDocument->Main()); |
227 | } |
228 | else |
229 | { |
230 | myColorTool.Nullify(); |
231 | } |
232 | |
fc552d84 |
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 |
f6abd02c |
265 | //Standard_ProgramError::Raise ("XCAFPrs_DocumentExplorer - NULL label in the input"); |
fc552d84 |
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 | { |
f6abd02c |
296 | Standard_ProgramError::Raise ("XCAFPrs_DocumentExplorer - internal error"); |
fc552d84 |
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 | { |
f6abd02c |
336 | Standard_ProgramError::Raise ("XCAFPrs_DocumentExplorer::Next() - out of range"); |
fc552d84 |
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 | } |