0030692: Data Exchange - introduce base framework RWMesh for importing mesh data...
[occt.git] / src / RWMesh / RWMesh_CafReader.cxx
CommitLineData
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
36IMPLEMENT_STANDARD_RTTIEXT(RWMesh_CafReader, Standard_Transient)
37
38// =======================================================================
39// function : RWMesh_CafReader
40// purpose :
41// =======================================================================
42RWMesh_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// =======================================================================
55RWMesh_CafReader::~RWMesh_CafReader()
56{
57 //
58}
59
60// =======================================================================
61// function : SingleShape
62// purpose :
63// =======================================================================
64TopoDS_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// =======================================================================
88Standard_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// =======================================================================
198Standard_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// =======================================================================
317void 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}