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