Salome HOME
d495c72e7d5835ec894d7531ea4ac0d5e8f0420b
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_STEPImportXCAF.cpp
1 // Copyright (C) 2014-2023  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <GeomAlgoAPI_STEPImportXCAF.h>
21
22 #include <BRep_Builder.hxx>
23
24 #include <Interface_EntityIterator.hxx>
25 #include <Interface_Graph.hxx>
26 #include <Interface_InterfaceModel.hxx>
27
28 #include <Quantity_Color.hxx>
29
30 #include <StepRepr_DescriptiveRepresentationItem.hxx>
31 #include <StepRepr_ProductDefinitionShape.hxx>
32 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
33 #include <StepRepr_Representation.hxx>
34
35 #include <TDataStd_Name.hxx>
36 #include <TDF_ChildIDIterator.hxx>
37 #include <TDocStd_Document.hxx>
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS.hxx>
41 #include <Transfer_TransientProcess.hxx>
42 #include <TransferBRep.hxx>
43 #include <TopTools_IndexedMapOfShape.hxx>
44
45 #include <XCAFApp_Application.hxx>
46 #include <XCAFDoc_DocumentTool.hxx>
47 #include <XCAFDoc_Location.hxx>
48 #include <XCAFDoc_ShapeTool.hxx>
49 #include <XSControl_TransferReader.hxx>
50 #include <XSControl_WorkSession.hxx>
51 #include <XCAFDoc_ColorTool.hxx>
52 #include <XCAFDoc_MaterialTool.hxx>
53
54 #include <Locale_Convert.h>
55
56 // read geometry
57 std::shared_ptr<GeomAPI_Shape> setGeom(const Handle(XCAFDoc_ShapeTool) &shapeTool,
58   const TDF_Label &theLabel,
59   std::string& theError);
60
61 /// read attributs for  label
62 void setShapeAttributes(const Handle(XCAFDoc_ShapeTool) &theShapeTool,
63   const Handle(XCAFDoc_ColorTool) &theColorTool,
64   const Handle(XCAFDoc_MaterialTool) &TheMaterialTool,
65   const TDF_Label &theLabel,
66   const TopLoc_Location &theLoc,
67   std::shared_ptr<ModelAPI_ResultBody> theResultBody,
68   std::map< std::wstring, std::list<std::wstring>> &theMaterialShape,
69   bool theIsRef);
70
71 // store Materiel for theShapeLabel in the map theMaterialShape
72 void storeMaterial(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
73   const Handle(Standard_Transient) &theEnti,
74   const TopTools_IndexedMapOfShape &theIndices,
75   const Handle(Transfer_TransientProcess) &theTP,
76   const TDF_Label &theShapeLabel,
77   std::map< std::wstring, std::list<std::wstring>> &theMaterialShape);
78
79 //=============================================================================
80 TopoDS_Shape getShape(const Handle(Standard_Transient) &theEnti,
81                       const Handle(Transfer_TransientProcess) &theTP)
82 {
83   TopoDS_Shape aResult;
84   Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
85
86   if (aBinder.IsNull()) {
87     return aResult;
88   }
89
90   aResult = TransferBRep::ShapeResult(aBinder);
91
92   return aResult;
93 }
94
95 //=============================================================================
96 std::shared_ptr<GeomAPI_Shape> readAttributes(STEPCAFControl_Reader &theReader,
97                                std::shared_ptr<ModelAPI_ResultBody> theResultBody,
98                                const bool  theIsMaterials,
99                                std::map< std::wstring,std::list<std::wstring>> &theMaterialShape,
100                                std::string& theError)
101 {
102   // dummy XCAF Application to handle the STEP XCAF Document
103   Handle(XCAFApp_Application) dummy_app = XCAFApp_Application::GetApplication();
104   // XCAF Document to contain the STEP/IGES file itself
105   Handle(TDocStd_Document) adoc;
106
107   dummy_app->NewDocument( TCollection_ExtendedString("MDTV-CAF"), adoc);
108   // transfer STEP/IGES into the document, and get the main label
109   theReader.Transfer(adoc);
110   TDF_Label mainLabel = adoc->Main();
111   Handle_XCAFDoc_ShapeTool shapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
112   Handle_XCAFDoc_ColorTool colorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
113   Handle(XCAFDoc_MaterialTool) materialTool = XCAFDoc_DocumentTool::MaterialTool(mainLabel);
114   // traverse the labels recursively to set attributes on shapes
115   setShapeAttributes(shapeTool, colorTool, materialTool, mainLabel,
116                      TopLoc_Location(),theResultBody,theMaterialShape,false);
117
118   std::shared_ptr<GeomAPI_Shape> ageom =  setGeom(shapeTool,mainLabel,theError);
119
120   STEPControl_Reader aReader = theReader.ChangeReader();
121
122   // BEGIN: reading materials of sub-shapes from file
123   if (theIsMaterials) {
124     TopTools_IndexedMapOfShape anIndices;
125     TopExp::MapShapes(ageom->impl<TopoDS_Shape>(), anIndices);
126
127     Handle(Interface_InterfaceModel) Model = aReader.WS()->Model();
128     Handle(XSControl_TransferReader) TR = aReader.WS()->TransferReader();
129     if (!TR.IsNull()) {
130       Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
131
132       Standard_Integer nb = Model->NbEntities();
133
134       for (Standard_Integer ie = 1; ie <= nb; ie++) {
135         Handle(Standard_Transient) enti = Model->Value(ie);
136
137         // Store materials.
138         storeMaterial(theResultBody,enti, anIndices, TP, mainLabel,theMaterialShape);
139       }
140     }
141   }
142   if (adoc->CanClose() == CDM_CCS_OK)
143     adoc->Close();
144   return ageom;
145 }
146
147 //=============================================================================
148 std::shared_ptr<GeomAPI_Shape> setGeom(const Handle(XCAFDoc_ShapeTool) &theShapeTool,
149                                        const TDF_Label& /*theLabel*/,
150                                        std::string& theError)
151 {
152   BRep_Builder aB;
153   TopoDS_Compound aCompound;
154   aB.MakeCompound(aCompound);
155
156   TDF_LabelSequence aFrshapes;
157   theShapeTool->GetShapes(aFrshapes);
158
159   std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
160
161   if (aFrshapes.Length() == 0) {
162       aGeomShape->setImpl(new TopoDS_Shape());
163       return aGeomShape;
164   } else if (aFrshapes.Length() == 1) {
165     TopoDS_Shape shape = theShapeTool->GetShape(aFrshapes.Value(1));
166     aGeomShape->setImpl(new TopoDS_Shape(shape));
167     return aGeomShape;
168   } else {
169     for (Standard_Integer i=1; i<=aFrshapes.Length(); i++) {
170       TopoDS_Shape aS = theShapeTool->GetShape(aFrshapes.Value(i));
171       TDF_Label aLabel = theShapeTool->FindShape(aS, Standard_False);
172       if ( (!aLabel.IsNull()) && (theShapeTool->IsShape(aLabel)) ) {
173         if (theShapeTool->IsFree(aLabel) ) {
174           if (aS.IsNull()) {
175             continue;
176           } else {
177             if (aS.ShapeType() != TopAbs_SOLID && !theShapeTool->IsReference(aLabel)){
178               for(TDF_ChildIterator anIt(aLabel); anIt.More(); anIt.Next()) {
179                 aB.Add(aCompound, theShapeTool->GetShape(anIt.Value()) );
180               }
181             } else {
182               aB.Add(aCompound, aS);
183             }
184           }
185         }
186       }
187     }
188
189     TopoDS_Shape aShape = aCompound;
190     // Check if any BRep entity has been read, there must be at least a vertex
191     if (!TopExp_Explorer( aShape, TopAbs_VERTEX ).More()) {
192       theError = "No geometrical data in the imported file.";
193       aGeomShape->setImpl(new TopoDS_Shape());
194       return aGeomShape;
195     }
196
197     aGeomShape->setImpl(new TopoDS_Shape(aShape));
198     return aGeomShape;
199   }
200 }
201 //=============================================================================
202 void setShapeAttributes(const Handle(XCAFDoc_ShapeTool) &theShapeTool,
203                         const Handle(XCAFDoc_ColorTool) &theColorTool,
204                         const Handle(XCAFDoc_MaterialTool) &theMaterialTool,
205                         const TDF_Label &theLabel,
206                         const TopLoc_Location &theLoc,
207                         std::shared_ptr<ModelAPI_ResultBody> theResultBody,
208                         std::map< std::wstring,std::list<std::wstring>> &theMaterialShape,
209                         bool theIsRef)
210 {
211   std::wstring aShapeName;
212   Handle(TDataStd_Name) aN;
213
214   if (theLabel.FindAttribute(TDataStd_Name::GetID(), aN)) {
215     TCollection_ExtendedString aName = aN->Get();
216
217     aShapeName =  Locale::Convert::toWString(TCollection_AsciiString(aName).ToCString()) ;
218   }
219
220   TopLoc_Location aPartLoc = theLoc;
221   Handle(XCAFDoc_Location) al;
222   if (theLabel.FindAttribute(XCAFDoc_Location::GetID(), al)) {
223     if (theIsRef)
224       aPartLoc = aPartLoc * al->Get();
225     else
226       aPartLoc = al->Get();
227   }
228
229   TDF_Label aRef;
230   if (theShapeTool->IsReference(theLabel) && theShapeTool->GetReferredShape(theLabel, aRef)) {
231
232     setShapeAttributes( theShapeTool, theColorTool, theMaterialTool, aRef,
233                         aPartLoc,theResultBody,theMaterialShape,true);
234   }
235
236   if (theShapeTool->IsSimpleShape(theLabel) && (theIsRef || theShapeTool->IsFree(theLabel))) {
237
238     TopoDS_Shape aShape = theShapeTool->GetShape(theLabel);
239
240     std::shared_ptr<GeomAPI_Shape> aShapeGeom(new GeomAPI_Shape);
241     if (!theLoc.IsIdentity()) {
242         aShape.Move(theLoc);
243     }
244     aShapeGeom->setImpl(new TopoDS_Shape(aShape));
245     aShapeName = theResultBody->addShapeName(aShapeGeom, aShapeName);
246
247
248     aShape.Location(theIsRef ? theLoc : aPartLoc);
249     int aDim =
250       (aShape.ShapeType() == TopAbs_VERTEX) ?
251         0 :
252         (aShape.ShapeType() == TopAbs_EDGE || aShape.ShapeType() == TopAbs_WIRE) ?
253         1 :
254         (aShape.ShapeType() == TopAbs_FACE ||
255          aShape.ShapeType() == TopAbs_SHELL) ? 2 :3;
256
257     Handle(TCollection_HAsciiString) aMatName;
258     Handle(TCollection_HAsciiString) aMatDescription;
259     Standard_Real aMatDensity;
260     Handle(TCollection_HAsciiString) aMatDensName;
261     Handle(TCollection_HAsciiString) aMatDensValType;
262
263     if (theMaterialTool->GetMaterial(theLabel, aMatName, aMatDescription, aMatDensity,
264                                  aMatDensName, aMatDensValType)) {
265       std::wstring aNameMaterial = Locale::Convert::toWString(aMatName->ToCString());
266
267       theMaterialShape[aNameMaterial].push_back(aShapeName);
268     }
269
270     Quantity_Color aCol;
271     if (theColorTool->GetColor(theLabel, XCAFDoc_ColorGen, aCol)) {
272       double r = aCol.Red(), g = aCol.Green(), b = aCol.Blue();
273       std::vector<int> ColRGB = {int(r*255),int(g*255),int(b*255)};
274       theResultBody->addShapeColor(aShapeName, ColRGB);
275     } else if (theColorTool->GetColor(theLabel, XCAFDoc_ColorSurf, aCol)) {
276       double r = aCol.Red(), g = aCol.Green(), b = aCol.Blue();
277       std::vector<int> aColRGB = {int(r*255),int(g*255),int(b*255)};
278       theResultBody->addShapeColor(aShapeName, aColRGB);
279     } else if (theColorTool->GetColor(theLabel, XCAFDoc_ColorCurv, aCol)) {
280       double aR = aCol.Red(), aG = aCol.Green(), aB = aCol.Blue();
281       std::vector<int> aColRGB = {int(aR*255),int(aG*255),int(aB*255)};
282       theResultBody->addShapeColor(aShapeName, aColRGB);
283     }
284     // check explicit coloring of boundary entities
285     if (aDim == 3) {
286       TopExp_Explorer aXp2(aShape, TopAbs_FACE);
287       while (aXp2.More()) {
288         if (theColorTool->GetColor(aXp2.Current(), XCAFDoc_ColorGen, aCol) ||
289           theColorTool->GetColor(aXp2.Current(), XCAFDoc_ColorSurf, aCol) ||
290           theColorTool->GetColor(aXp2.Current(), XCAFDoc_ColorCurv, aCol)) {
291           double aR = aCol.Red(), aG = aCol.Green(), aB = aCol.Blue();
292           TopoDS_Face aFace = TopoDS::Face(aXp2.Current());
293           std::vector<int> aColRGB = {int(aR*255),int(aG*255),int(aB*255)};
294           std::wstringstream aNameFace;
295           TopoDS_Shape aShapeface = aXp2.Current();
296           if (!theLoc.IsIdentity()){
297                   aShapeface.Move(theLoc);
298           }
299           aShapeGeom->setImpl(new TopoDS_Shape(aShapeface));
300           theResultBody->addShapeColor(
301           theResultBody->addShapeName(aShapeGeom , aNameFace.str()), aColRGB);
302         }
303         aXp2.Next();
304       }
305     }
306   } else {
307     if (!theShapeTool->IsReference(theLabel) ){
308       TopoDS_Shape aShape = theShapeTool->GetShape(theLabel);
309
310       std::shared_ptr<GeomAPI_Shape> aShapeGeom(new GeomAPI_Shape);
311       if (!theLoc.IsIdentity()){
312           aShape.Move(theLoc);
313       }
314       aShapeGeom->setImpl(new TopoDS_Shape(aShape));
315       aShapeName = theResultBody->addShapeName(aShapeGeom, aShapeName);
316     }
317     for(TDF_ChildIterator anIt(theLabel); anIt.More(); anIt.Next()) {
318
319       setShapeAttributes( theShapeTool, theColorTool, theMaterialTool,
320                          anIt.Value(), aPartLoc,theResultBody,theMaterialShape, theIsRef);
321     }
322   }
323 }
324
325 //=============================================================================
326 void storeMaterial( std::shared_ptr<ModelAPI_ResultBody>    theResultBody,
327                     const Handle(Standard_Transient)        &theEnti,
328                     const TopTools_IndexedMapOfShape        &theIndices,
329                     const Handle(Transfer_TransientProcess) &theTP,
330                     const TDF_Label                         &/*theShapeLabel*/,
331                     std::map< std::wstring, std::list<std::wstring>> &theMaterialShape )
332 {
333   // Treat Product Definition Shape only.
334   Handle(StepRepr_ProductDefinitionShape) aPDS =
335     Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
336   Handle(StepBasic_ProductDefinition)     aProdDef;
337
338   if (!aPDS.IsNull()) {
339     // Product Definition Shape ==> Product Definition
340     aProdDef = aPDS->Definition().ProductDefinition();
341   }
342
343   if (!aProdDef.IsNull()) {
344     // Product Definition ==> Property Definition
345     const Interface_Graph    &aGraph = theTP->Graph();
346     Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
347     TopoDS_Shape              aShape;
348
349     for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
350       Handle(StepRepr_PropertyDefinition) aPropD =
351         Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
352
353       if (!aPropD.IsNull()) {
354         // Property Definition ==> Representation.
355         Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
356
357         for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
358           Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
359             Handle(StepRepr_PropertyDefinitionRepresentation)::
360             DownCast(aSubs1.Value());
361
362           if (!aPDR.IsNull()) {
363             // Property Definition ==> Material Name.
364             Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
365
366             if (!aRepr.IsNull()) {
367               Standard_Integer anIr;
368
369               for(anIr = 1; anIr <= aRepr->NbItems(); anIr++) {
370                 Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(anIr);
371                 Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
372                   Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
373
374                 if (!aDRI.IsNull()) {
375                   // Get shape from Product Definition
376                   Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
377                   if (!aMatName.IsNull()) {
378                     TCollection_ExtendedString
379                       aMatNameExt (aMatName->ToCString());
380
381                     if (aShape.IsNull()) {
382                       //Get the shape.
383                       aShape = getShape(aProdDef, theTP);
384                       if (aShape.IsNull()) {
385                         return;
386                       }
387                     }
388
389                     // as PRODUCT can be included in the main shape
390                     // several times, we look here for all iclusions.
391                     Standard_Integer anISub, aNbSubs = theIndices.Extent();
392
393                     for (anISub = 1; anISub <= aNbSubs; anISub++) {
394                       TopoDS_Shape aSub = theIndices.FindKey(anISub);
395
396                       if (aSub.IsPartner(aShape)) {
397                         std::shared_ptr<GeomAPI_Shape> aShapeGeom(new GeomAPI_Shape);
398                         aShapeGeom->setImpl(new TopoDS_Shape(aSub));
399                         std::wstring aNom = theResultBody->findShapeName(aShapeGeom);
400                         std::wstring aMName= Locale::Convert::toWString(aMatName->ToCString());
401                         theMaterialShape[aMName].push_back(aNom);
402
403                       }
404                     }
405                   }
406                 }
407               }
408             }
409           }
410         }
411       }
412     }
413   }
414 }