fc552d84 |
1 | // Author: Kirill Gavrilov |
2 | // Copyright (c) 2016-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 <RWMesh_CafReader.hxx> |
16 | |
17 | #include <XCAFPrs_DocumentExplorer.hxx> |
18 | |
19 | #include <Message.hxx> |
20 | #include <Message_Messenger.hxx> |
21 | #include <Message_ProgressIndicator.hxx> |
22 | #include <BRep_Builder.hxx> |
23 | #include <OSD_Path.hxx> |
24 | #include <OSD_Timer.hxx> |
25 | #include <TDataStd_Name.hxx> |
26 | #include <TDocStd_Document.hxx> |
27 | #include <TopExp_Explorer.hxx> |
28 | #include <TopoDS.hxx> |
29 | #include <TopoDS_Iterator.hxx> |
30 | #include <XCAFDoc_ColorTool.hxx> |
31 | #include <XCAFDoc_ColorType.hxx> |
32 | #include <XCAFDoc_DocumentTool.hxx> |
33 | #include <XCAFDoc_ShapeMapTool.hxx> |
34 | #include <XCAFDoc_ShapeTool.hxx> |
35 | |
36 | IMPLEMENT_STANDARD_RTTIEXT(RWMesh_CafReader, Standard_Transient) |
37 | |
38 | // ======================================================================= |
39 | // function : RWMesh_CafReader |
40 | // purpose : |
41 | // ======================================================================= |
42 | RWMesh_CafReader::RWMesh_CafReader() |
43 | : myToFillDoc (Standard_True), |
44 | myToFillIncomplete (Standard_True), |
45 | myMemoryLimitMiB (-1), |
46 | myExtraStatus (RWMesh_CafReaderStatusEx_NONE) |
47 | { |
48 | // |
49 | } |
50 | |
51 | // ======================================================================= |
52 | // function : ~RWMesh_CafReader |
53 | // purpose : |
54 | // ======================================================================= |
55 | RWMesh_CafReader::~RWMesh_CafReader() |
56 | { |
57 | // |
58 | } |
59 | |
60 | // ======================================================================= |
61 | // function : SingleShape |
62 | // purpose : |
63 | // ======================================================================= |
64 | TopoDS_Shape RWMesh_CafReader::SingleShape() const |
65 | { |
66 | if (myRootShapes.Size() > 1) |
67 | { |
68 | BRep_Builder aBuilder; |
69 | TopoDS_Compound aCompound; |
70 | aBuilder.MakeCompound (aCompound); |
71 | for (TopTools_SequenceOfShape::Iterator aRootIter (myRootShapes); aRootIter.More(); aRootIter.Next()) |
72 | { |
73 | aBuilder.Add (aCompound, aRootIter.Value()); |
74 | } |
75 | return aCompound; |
76 | } |
77 | else if (!myRootShapes.IsEmpty()) |
78 | { |
79 | return myRootShapes.First(); |
80 | } |
81 | return TopoDS_Shape(); |
82 | } |
83 | |
84 | // ======================================================================= |
85 | // function : perform |
86 | // purpose : |
87 | // ======================================================================= |
88 | Standard_Boolean RWMesh_CafReader::perform (const TCollection_AsciiString& theFile, |
89 | const Handle(Message_ProgressIndicator)& theProgress, |
90 | const Standard_Boolean theToProbe) |
91 | { |
92 | Standard_Integer aNewRootsLower = 1; |
93 | Handle(XCAFDoc_ShapeTool) aShapeTool = !myXdeDoc.IsNull() |
94 | ? XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main()) |
95 | : Handle(XCAFDoc_ShapeTool)(); |
96 | if (!myXdeDoc.IsNull()) |
97 | { |
98 | TDF_LabelSequence aRootLabels; |
99 | aShapeTool->GetFreeShapes (aRootLabels); |
100 | aNewRootsLower = aRootLabels.Upper() + 1; |
101 | } |
102 | |
103 | OSD_Timer aLoadingTimer; |
104 | aLoadingTimer.Start(); |
105 | const Standard_Boolean isDone = performMesh (theFile, theProgress, theToProbe); |
106 | if (theToProbe |
107 | || (!theProgress.IsNull() && theProgress->UserBreak())) |
108 | { |
109 | return isDone; |
110 | } |
111 | else if (!isDone) |
112 | { |
113 | if (!myToFillIncomplete) |
114 | { |
115 | return Standard_False; |
116 | } |
117 | |
118 | myExtraStatus |= RWMesh_CafReaderStatusEx_Partial; |
119 | } |
120 | |
121 | BRep_Builder aBuilder; |
122 | TopoDS_Shape aShape; |
123 | if (myRootShapes.Size() > 1) |
124 | { |
125 | TopoDS_Compound aCompound; |
126 | aBuilder.MakeCompound (aCompound); |
127 | for (TopTools_SequenceOfShape::Iterator aRootIter (myRootShapes); aRootIter.More(); aRootIter.Next()) |
128 | { |
129 | aBuilder.Add (aCompound, aRootIter.Value()); |
130 | } |
131 | aShape = aCompound; |
132 | } |
133 | else if (!myRootShapes.IsEmpty()) |
134 | { |
135 | aShape = myRootShapes.First(); |
136 | } |
137 | |
138 | Standard_Integer aNbNodes = 0, aNbElems = 0, aNbFaces = 0; |
139 | if (!aShape.IsNull()) |
140 | { |
141 | TopLoc_Location aDummyLoc; |
142 | for (TopExp_Explorer aFaceIter (aShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) |
143 | { |
144 | const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); |
145 | if (const Handle(Poly_Triangulation)& aPolyTri = BRep_Tool::Triangulation (aFace, aDummyLoc)) |
146 | { |
147 | ++aNbFaces; |
148 | aNbNodes += aPolyTri->NbNodes(); |
149 | aNbElems += aPolyTri->NbTriangles(); |
150 | } |
151 | } |
152 | } |
153 | if (!isDone && aNbElems < 100) |
154 | { |
155 | return Standard_False; |
156 | } |
157 | |
158 | if (myToFillDoc |
159 | && !myXdeDoc.IsNull()) |
160 | { |
161 | const Standard_Boolean wasAutoNaming = aShapeTool->AutoNaming(); |
162 | aShapeTool->SetAutoNaming (Standard_False); |
163 | const TCollection_AsciiString aRootName; // = generateRootName (theFile); |
164 | for (TopTools_SequenceOfShape::Iterator aRootIter (myRootShapes); aRootIter.More(); aRootIter.Next()) |
165 | { |
166 | addShapeIntoDoc (aRootIter.Value(), TDF_Label(), aRootName); |
167 | } |
168 | aShapeTool->UpdateAssemblies(); |
169 | aShapeTool->SetAutoNaming (wasAutoNaming); |
170 | } |
171 | if (!myXdeDoc.IsNull()) |
172 | { |
173 | generateNames (theFile, aNewRootsLower, Standard_False); |
174 | } |
175 | |
176 | aLoadingTimer.Stop(); |
177 | |
178 | TCollection_AsciiString aStats = TCollection_AsciiString("[") + aNbNodes + " nodes] [" + aNbElems + " 2d elements]"; |
179 | if (!isDone) |
180 | { |
181 | Message::DefaultMessenger()->Send (TCollection_AsciiString ("Mesh ") + theFile |
182 | + "\n" + aStats |
183 | + "\n[PARTIALLY read in " + aLoadingTimer.ElapsedTime() + " s]", Message_Info); |
184 | } |
185 | else |
186 | { |
187 | Message::DefaultMessenger()->Send (TCollection_AsciiString ("Mesh ") + theFile |
188 | + "\n" + aStats |
189 | + "\n[read in " + aLoadingTimer.ElapsedTime() + " s]", Message_Info); |
190 | } |
191 | return Standard_True; |
192 | } |
193 | |
194 | // ======================================================================= |
195 | // function : addShapeIntoDoc |
196 | // purpose : |
197 | // ======================================================================= |
198 | Standard_Boolean RWMesh_CafReader::addShapeIntoDoc (const TopoDS_Shape& theShape, |
199 | const TDF_Label& theLabel, |
200 | const TCollection_AsciiString& theParentName) |
201 | { |
202 | if (theShape.IsNull() |
203 | || myXdeDoc.IsNull()) |
204 | { |
205 | return Standard_False; |
206 | } |
207 | |
208 | Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main()); |
209 | |
210 | TopLoc_Location aDummyLoc; |
211 | |
212 | const TopAbs_ShapeEnum aShapeType = theShape.ShapeType(); |
213 | TopoDS_Shape aShapeToAdd = theShape; |
214 | Standard_Boolean toMakeAssembly = Standard_False; |
215 | if (theShape.ShapeType() == TopAbs_COMPOUND) |
216 | { |
217 | TCollection_AsciiString aFirstName; |
218 | RWMesh_NodeAttributes aSubFaceAttribs; |
219 | for (TopoDS_Iterator aSubShapeIter (theShape, Standard_True, Standard_False); !toMakeAssembly && aSubShapeIter.More(); aSubShapeIter.Next()) |
220 | { |
221 | if (aSubShapeIter.Value().ShapeType() != TopAbs_FACE) |
222 | { |
223 | toMakeAssembly = Standard_True; |
224 | break; |
225 | } |
226 | |
227 | const TopoDS_Face& aFace = TopoDS::Face (aSubShapeIter.Value()); |
228 | toMakeAssembly = toMakeAssembly |
229 | || (myAttribMap.Find (aFace, aSubFaceAttribs) && !aSubFaceAttribs.Name.IsEmpty()); |
230 | } |
231 | |
232 | // create empty compound to add as assembly |
233 | if (toMakeAssembly) |
234 | { |
235 | TopoDS_Compound aCompound; |
236 | BRep_Builder aBuilder; |
237 | aBuilder.MakeCompound (aCompound); |
238 | aCompound.Location (theShape.Location()); |
239 | aShapeToAdd = aCompound; |
240 | } |
241 | } |
242 | |
243 | TDF_Label aNewLabel; |
244 | if (theLabel.IsNull()) |
245 | { |
246 | // add new shape |
247 | aNewLabel = aShapeTool->AddShape (aShapeToAdd, toMakeAssembly); |
248 | } |
249 | else if (aShapeTool->IsAssembly (theLabel)) |
250 | { |
251 | // add shape as component |
252 | aNewLabel = aShapeTool->AddComponent (theLabel, aShapeToAdd, toMakeAssembly); |
253 | } |
254 | else |
255 | { |
256 | // add shape as sub-shape |
257 | aNewLabel = aShapeTool->AddSubShape (theLabel, theShape); |
258 | if (!aNewLabel.IsNull()) |
259 | { |
260 | Handle(XCAFDoc_ShapeMapTool) aShapeMapTool = XCAFDoc_ShapeMapTool::Set (aNewLabel); |
261 | aShapeMapTool->SetShape (theShape); |
262 | } |
263 | } |
264 | if (aNewLabel.IsNull()) |
265 | { |
266 | return Standard_False; |
267 | } |
268 | |
269 | // if new label is a reference get referred shape |
270 | TDF_Label aNewRefLabel = aNewLabel; |
271 | aShapeTool->GetReferredShape (aNewLabel, aNewRefLabel); |
272 | |
273 | // store name |
274 | RWMesh_NodeAttributes aShapeAttribs; |
275 | myAttribMap.Find (theShape, aShapeAttribs); |
276 | if (aShapeAttribs.Name.IsEmpty()) |
277 | { |
278 | if (theLabel.IsNull()) |
279 | { |
280 | aShapeAttribs.Name = theParentName; |
281 | } |
282 | if (aShapeAttribs.Name.IsEmpty() |
283 | && !theLabel.IsNull()) |
284 | { |
285 | aShapeAttribs.Name = shapeTypeToString (aShapeType); |
286 | } |
287 | } |
288 | if (!aShapeAttribs.Name.IsEmpty()) |
289 | { |
290 | TDataStd_Name::Set (aNewRefLabel, aShapeAttribs.Name); |
291 | } |
292 | |
293 | // store color |
294 | Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool (myXdeDoc->Main()); |
295 | if (aShapeAttribs.Style.IsSetColorSurf()) |
296 | { |
297 | aColorTool->SetColor (aNewRefLabel, aShapeAttribs.Style.GetColorSurfRGBA(), XCAFDoc_ColorSurf); |
298 | } |
299 | if (aShapeAttribs.Style.IsSetColorCurv()) |
300 | { |
301 | aColorTool->SetColor (aNewRefLabel, aShapeAttribs.Style.GetColorCurv(), XCAFDoc_ColorCurv); |
302 | } |
303 | |
304 | // store sub-shapes (iterator is set to ignore Location) |
305 | TCollection_AsciiString aDummyName; |
306 | for (TopoDS_Iterator aSubShapeIter (theShape, Standard_True, Standard_False); aSubShapeIter.More(); aSubShapeIter.Next()) |
307 | { |
308 | addShapeIntoDoc (aSubShapeIter.Value(), aNewRefLabel, aDummyName); |
309 | } |
310 | return Standard_True; |
311 | } |
312 | |
313 | // ======================================================================= |
314 | // function : generateNames |
315 | // purpose : |
316 | // ======================================================================= |
317 | void RWMesh_CafReader::generateNames (const TCollection_AsciiString& theFile, |
318 | const Standard_Integer theRootLower, |
319 | const Standard_Boolean theWithSubLabels) |
320 | { |
321 | if (myXdeDoc.IsNull()) |
322 | { |
323 | return; |
324 | } |
325 | |
326 | TCollection_AsciiString aDummyFolder, aFileName; |
327 | OSD_Path::FolderAndFileFromPath (theFile, aDummyFolder, aFileName); |
328 | const TCollection_AsciiString aRootName = myRootPrefix + aFileName; |
329 | |
330 | Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main()); |
331 | TDF_LabelSequence aRootLabels; |
332 | aShapeTool->GetFreeShapes (aRootLabels); |
333 | if (aRootLabels.Upper() < theRootLower) |
334 | { |
335 | return; |
336 | } |
337 | |
338 | // replace empty names |
339 | Handle(TDataStd_Name) aNodeName; |
340 | Standard_Integer aRootIndex = aRootLabels.Lower(); |
341 | TDF_LabelSequence aNewRootLabels; |
342 | for (TDF_LabelSequence::Iterator aRootIter (aRootLabels); aRootIter.More(); ++aRootIndex, aRootIter.Next()) |
343 | { |
344 | if (aRootIndex < theRootLower) |
345 | { |
346 | continue; |
347 | } |
348 | else if (theWithSubLabels) |
349 | { |
350 | aNewRootLabels.Append (aRootIter.Value()); |
351 | } |
352 | |
353 | const TDF_Label aLabel = aRootIter.Value(); |
354 | TDF_Label aRefLab = aLabel; |
355 | XCAFDoc_ShapeTool::GetReferredShape (aLabel, aRefLab); |
356 | if (!aRefLab.FindAttribute (TDataStd_Name::GetID(), aNodeName)) |
357 | { |
358 | TDataStd_Name::Set (aRefLab, aRootName); |
359 | } |
360 | if (aLabel != aRefLab |
361 | && !aLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName)) |
362 | { |
363 | TDataStd_Name::Set (aLabel, aRootName); |
364 | } |
365 | } |
366 | |
367 | if (theWithSubLabels) |
368 | { |
369 | for (XCAFPrs_DocumentExplorer aDocIter (myXdeDoc, |
370 | aNewRootLabels, |
371 | XCAFPrs_DocumentExplorerFlags_OnlyLeafNodes | XCAFPrs_DocumentExplorerFlags_NoStyle); |
372 | aDocIter.More(); aDocIter.Next()) |
373 | { |
374 | if (aDocIter.CurrentDepth() == 0 |
375 | || aDocIter.Current().RefLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName)) |
376 | { |
377 | continue; |
378 | } |
379 | |
380 | const TopoDS_Shape aShape = XCAFDoc_ShapeTool::GetShape (aDocIter.Current().RefLabel); |
381 | if (!aShape.IsNull()) |
382 | { |
383 | TDataStd_Name::Set (aDocIter.Current().RefLabel, shapeTypeToString (aShape.ShapeType())); |
384 | } |
385 | } |
386 | } |
387 | } |