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 | { |
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 | } |