0030809: Data Exchange - fix misprint in RWMesh_CafReader::generateNames()
[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
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, aNewRootLabels, XCAFPrs_DocumentExplorerFlags_NoStyle);
370          aDocIter.More(); aDocIter.Next())
371     {
372       if (aDocIter.CurrentDepth() == 0
373        || aDocIter.Current().RefLabel.FindAttribute (TDataStd_Name::GetID(), aNodeName))
374       {
375         continue;
376       }
377
378       const TopoDS_Shape aShape = XCAFDoc_ShapeTool::GetShape (aDocIter.Current().RefLabel);
379       if (!aShape.IsNull())
380       {
381         TDataStd_Name::Set (aDocIter.Current().RefLabel, shapeTypeToString (aShape.ShapeType()));
382       }
383     }
384   }
385 }