0030811: Data Exchange, RWGltf_CafReader - fix inaccessibility of properties
[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;
fc552d84 93 if (!myXdeDoc.IsNull())
94 {
95 TDF_LabelSequence aRootLabels;
82c59511 96 XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main())->GetFreeShapes (aRootLabels);
fc552d84 97 aNewRootsLower = aRootLabels.Upper() + 1;
98 }
99
100 OSD_Timer aLoadingTimer;
101 aLoadingTimer.Start();
102 const Standard_Boolean isDone = performMesh (theFile, theProgress, theToProbe);
103 if (theToProbe
104 || (!theProgress.IsNull() && theProgress->UserBreak()))
105 {
106 return isDone;
107 }
108 else if (!isDone)
109 {
110 if (!myToFillIncomplete)
111 {
112 return Standard_False;
113 }
114
115 myExtraStatus |= RWMesh_CafReaderStatusEx_Partial;
116 }
117
82c59511 118 TopLoc_Location aDummyLoc;
fc552d84 119 Standard_Integer aNbNodes = 0, aNbElems = 0, aNbFaces = 0;
82c59511 120 for (TopTools_SequenceOfShape::Iterator aRootIter (myRootShapes); aRootIter.More(); aRootIter.Next())
fc552d84 121 {
82c59511 122 for (TopExp_Explorer aFaceIter (aRootIter.Value(), TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
fc552d84 123 {
124 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
125 if (const Handle(Poly_Triangulation)& aPolyTri = BRep_Tool::Triangulation (aFace, aDummyLoc))
126 {
127 ++aNbFaces;
128 aNbNodes += aPolyTri->NbNodes();
129 aNbElems += aPolyTri->NbTriangles();
130 }
131 }
132 }
133 if (!isDone && aNbElems < 100)
134 {
135 return Standard_False;
136 }
137
82c59511 138 fillDocument();
139 generateNames (theFile, aNewRootsLower, Standard_False);
fc552d84 140
141 aLoadingTimer.Stop();
142
82c59511 143 Message::DefaultMessenger()->Send (TCollection_AsciiString ("Mesh ") + theFile
144 + "\n[" + aNbNodes + " nodes] [" + aNbElems + " 2d elements]"
145 + "\n[" + (!isDone ? "PARTIALLY " : "") + "read in " + aLoadingTimer.ElapsedTime() + " s]", Message_Info);
146 return Standard_True;
147}
148
149// =======================================================================
150// function : fillDocument
151// purpose :
152// =======================================================================
153void RWMesh_CafReader::fillDocument()
154{
155 if (!myToFillDoc
156 || myXdeDoc.IsNull()
157 || myRootShapes.IsEmpty())
fc552d84 158 {
82c59511 159 return;
fc552d84 160 }
82c59511 161
162 const Standard_Boolean wasAutoNaming = XCAFDoc_ShapeTool::AutoNaming();
163 XCAFDoc_ShapeTool::SetAutoNaming (Standard_False);
164 const TCollection_AsciiString aRootName; // = generateRootName (theFile);
165 for (TopTools_SequenceOfShape::Iterator aRootIter (myRootShapes); aRootIter.More(); aRootIter.Next())
fc552d84 166 {
82c59511 167 addShapeIntoDoc (aRootIter.Value(), TDF_Label(), aRootName);
fc552d84 168 }
82c59511 169 XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main())->UpdateAssemblies();
170 XCAFDoc_ShapeTool::SetAutoNaming (wasAutoNaming);
fc552d84 171}
172
173// =======================================================================
174// function : addShapeIntoDoc
175// purpose :
176// =======================================================================
177Standard_Boolean RWMesh_CafReader::addShapeIntoDoc (const TopoDS_Shape& theShape,
178 const TDF_Label& theLabel,
179 const TCollection_AsciiString& theParentName)
180{
181 if (theShape.IsNull()
182 || myXdeDoc.IsNull())
183 {
184 return Standard_False;
185 }
186
187 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main());
188
189 TopLoc_Location aDummyLoc;
190
191 const TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
192 TopoDS_Shape aShapeToAdd = theShape;
193 Standard_Boolean toMakeAssembly = Standard_False;
194 if (theShape.ShapeType() == TopAbs_COMPOUND)
195 {
196 TCollection_AsciiString aFirstName;
197 RWMesh_NodeAttributes aSubFaceAttribs;
198 for (TopoDS_Iterator aSubShapeIter (theShape, Standard_True, Standard_False); !toMakeAssembly && aSubShapeIter.More(); aSubShapeIter.Next())
199 {
200 if (aSubShapeIter.Value().ShapeType() != TopAbs_FACE)
201 {
202 toMakeAssembly = Standard_True;
203 break;
204 }
205
206 const TopoDS_Face& aFace = TopoDS::Face (aSubShapeIter.Value());
207 toMakeAssembly = toMakeAssembly
208 || (myAttribMap.Find (aFace, aSubFaceAttribs) && !aSubFaceAttribs.Name.IsEmpty());
209 }
210
211 // create empty compound to add as assembly
212 if (toMakeAssembly)
213 {
214 TopoDS_Compound aCompound;
215 BRep_Builder aBuilder;
216 aBuilder.MakeCompound (aCompound);
217 aCompound.Location (theShape.Location());
218 aShapeToAdd = aCompound;
219 }
220 }
221
222 TDF_Label aNewLabel;
223 if (theLabel.IsNull())
224 {
225 // add new shape
226 aNewLabel = aShapeTool->AddShape (aShapeToAdd, toMakeAssembly);
227 }
228 else if (aShapeTool->IsAssembly (theLabel))
229 {
230 // add shape as component
231 aNewLabel = aShapeTool->AddComponent (theLabel, aShapeToAdd, toMakeAssembly);
232 }
233 else
234 {
235 // add shape as sub-shape
236 aNewLabel = aShapeTool->AddSubShape (theLabel, theShape);
237 if (!aNewLabel.IsNull())
238 {
239 Handle(XCAFDoc_ShapeMapTool) aShapeMapTool = XCAFDoc_ShapeMapTool::Set (aNewLabel);
240 aShapeMapTool->SetShape (theShape);
241 }
242 }
243 if (aNewLabel.IsNull())
244 {
245 return Standard_False;
246 }
247
248 // if new label is a reference get referred shape
249 TDF_Label aNewRefLabel = aNewLabel;
250 aShapeTool->GetReferredShape (aNewLabel, aNewRefLabel);
251
252 // store name
253 RWMesh_NodeAttributes aShapeAttribs;
254 myAttribMap.Find (theShape, aShapeAttribs);
255 if (aShapeAttribs.Name.IsEmpty())
256 {
257 if (theLabel.IsNull())
258 {
259 aShapeAttribs.Name = theParentName;
260 }
261 if (aShapeAttribs.Name.IsEmpty()
262 && !theLabel.IsNull())
263 {
264 aShapeAttribs.Name = shapeTypeToString (aShapeType);
265 }
266 }
267 if (!aShapeAttribs.Name.IsEmpty())
268 {
269 TDataStd_Name::Set (aNewRefLabel, aShapeAttribs.Name);
270 }
271
272 // store color
273 Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool (myXdeDoc->Main());
274 if (aShapeAttribs.Style.IsSetColorSurf())
275 {
276 aColorTool->SetColor (aNewRefLabel, aShapeAttribs.Style.GetColorSurfRGBA(), XCAFDoc_ColorSurf);
277 }
278 if (aShapeAttribs.Style.IsSetColorCurv())
279 {
280 aColorTool->SetColor (aNewRefLabel, aShapeAttribs.Style.GetColorCurv(), XCAFDoc_ColorCurv);
281 }
282
283 // store sub-shapes (iterator is set to ignore Location)
284 TCollection_AsciiString aDummyName;
285 for (TopoDS_Iterator aSubShapeIter (theShape, Standard_True, Standard_False); aSubShapeIter.More(); aSubShapeIter.Next())
286 {
287 addShapeIntoDoc (aSubShapeIter.Value(), aNewRefLabel, aDummyName);
288 }
289 return Standard_True;
290}
291
292// =======================================================================
293// function : generateNames
294// purpose :
295// =======================================================================
296void RWMesh_CafReader::generateNames (const TCollection_AsciiString& theFile,
297 const Standard_Integer theRootLower,
298 const Standard_Boolean theWithSubLabels)
299{
300 if (myXdeDoc.IsNull())
301 {
302 return;
303 }
304
305 TCollection_AsciiString aDummyFolder, aFileName;
306 OSD_Path::FolderAndFileFromPath (theFile, aDummyFolder, aFileName);
307 const TCollection_AsciiString aRootName = myRootPrefix + aFileName;
308
309 Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myXdeDoc->Main());
310 TDF_LabelSequence aRootLabels;
311 aShapeTool->GetFreeShapes (aRootLabels);
312 if (aRootLabels.Upper() < theRootLower)
313 {
314 return;
315 }
316
317 // replace empty names
318 Handle(TDataStd_Name) aNodeName;
319 Standard_Integer aRootIndex = aRootLabels.Lower();
320 TDF_LabelSequence aNewRootLabels;
321 for (TDF_LabelSequence::Iterator aRootIter (aRootLabels); aRootIter.More(); ++aRootIndex, aRootIter.Next())
322 {
323 if (aRootIndex < theRootLower)
324 {
325 continue;
326 }
327 else if (theWithSubLabels)
328 {
329 aNewRootLabels.Append (aRootIter.Value());
330 }
331
332 const TDF_Label aLabel = aRootIter.Value();
333 TDF_Label aRefLab = aLabel;
334 XCAFDoc_ShapeTool::GetReferredShape (aLabel, aRefLab);
335 if (!aRefLab.FindAttribute (TDataStd_Name::GetID(), aNodeName))
336 {
337 TDataStd_Name::Set (aRefLab, aRootName);
338 }
339 if (aLabel != aRefLab
340 && !aLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName))
341 {
342 TDataStd_Name::Set (aLabel, aRootName);
343 }
344 }
345
346 if (theWithSubLabels)
347 {
62810a3c 348 for (XCAFPrs_DocumentExplorer aDocIter (myXdeDoc, aNewRootLabels, XCAFPrs_DocumentExplorerFlags_NoStyle);
fc552d84 349 aDocIter.More(); aDocIter.Next())
350 {
351 if (aDocIter.CurrentDepth() == 0
352 || aDocIter.Current().RefLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName))
353 {
354 continue;
355 }
356
357 const TopoDS_Shape aShape = XCAFDoc_ShapeTool::GetShape (aDocIter.Current().RefLabel);
358 if (!aShape.IsNull())
359 {
360 TDataStd_Name::Set (aDocIter.Current().RefLabel, shapeTypeToString (aShape.ShapeType()));
361 }
362 }
363 }
364}