1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: GEOMALGOAPI_STEPImport.cpp
4 // Created: Dec 24, 2014
5 // Author: Sergey BELASH
7 #include <GeomAlgoAPI_STEPImport.h>
9 #include <TDF_ChildIDIterator.hxx>
10 #include <TDF_Label.hxx>
11 #include <TDataStd_Name.hxx>
12 #include <TDataStd_Comment.hxx>
13 #include <TNaming_Builder.hxx>
14 #include <TNaming_NamedShape.hxx>
16 #include <IFSelect_ReturnStatus.hxx>
17 #include <Interface_EntityIterator.hxx>
18 #include <Interface_Graph.hxx>
19 #include <Interface_InterfaceModel.hxx>
20 #include <Interface_Static.hxx>
21 #include <STEPControl_Reader.hxx>
22 #include <StepBasic_Product.hxx>
23 #include <StepBasic_ProductDefinition.hxx>
24 #include <StepBasic_ProductDefinitionFormation.hxx>
25 #include <StepGeom_GeometricRepresentationItem.hxx>
26 #include <StepShape_TopologicalRepresentationItem.hxx>
27 #include <StepRepr_DescriptiveRepresentationItem.hxx>
28 #include <StepRepr_ProductDefinitionShape.hxx>
29 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
30 #include <StepRepr_Representation.hxx>
31 #include <TransferBRep.hxx>
32 #include <Transfer_Binder.hxx>
33 #include <Transfer_TransientProcess.hxx>
34 #include <XSControl_TransferReader.hxx>
35 #include <XSControl_WorkSession.hxx>
37 #include <BRep_Builder.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TopTools_IndexedMapOfShape.hxx>
42 #include <TopoDS_Compound.hxx>
43 #include <TopoDS_Iterator.hxx>
44 #include <TopoDS_Shape.hxx>
47 #include <TColStd_SequenceOfAsciiString.hxx>
49 #include <Standard_Failure.hxx>
50 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
52 //=============================================================================
56 //=============================================================================
58 static TopoDS_Shape GetShape(const Handle(Standard_Transient) &theEnti,
59 const Handle(Transfer_TransientProcess) &theTP)
62 Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
64 if (aBinder.IsNull()) {
68 aResult = TransferBRep::ShapeResult(aBinder);
73 //=============================================================================
77 //=============================================================================
79 static TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
80 const TDF_Label &theShapeLabel,
81 const TopoDS_Shape &aShape)
86 (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
87 // check all named shapes using iterator
88 TDF_ChildIDIterator anIt
89 (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
91 for (; anIt.More(); anIt.Next()) {
92 Handle(TDataStd_Name) nameAttr =
93 Handle(TDataStd_Name)::DownCast(anIt.Value());
95 if (nameAttr.IsNull()) {
99 TDF_Label aLab = nameAttr->Label();
100 Handle(TNaming_NamedShape) shAttr;
102 if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
103 shAttr->Get().IsEqual(aShape)) {
109 // create label and set shape
110 if (aResult.IsNull()) {
113 aResult = aTag.NewChild(theShapeLabel);
115 TNaming_Builder tnBuild (aResult);
117 tnBuild.Generated(aShape);
123 //=============================================================================
127 //=============================================================================
129 static void StoreName(const Handle(Standard_Transient) &theEnti,
130 const TopTools_IndexedMapOfShape &theIndices,
131 const Handle(Transfer_TransientProcess) &theTP,
132 const TDF_Label &theShapeLabel)
134 Handle(TCollection_HAsciiString) aName;
136 if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
137 theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
138 aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
140 Handle(StepBasic_ProductDefinition) PD =
141 Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
143 if (PD.IsNull() == Standard_False) {
144 Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
145 aName = Prod->Name();
149 bool isValidName = false;
151 if (aName.IsNull() == Standard_False) {
154 if (aName->UsefullLength() < 1) {
156 } else if (aName->UsefullLength() == 4 &&
157 toupper (aName->Value(1)) == 'N' &&
158 toupper (aName->Value(2)) == 'O' &&
159 toupper (aName->Value(3)) == 'N' &&
160 toupper (aName->Value(4)) == 'E') {
164 // special check to pass names like "Open CASCADE STEP translator 6.3 1"
165 TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
167 if (aName->Length() >= aSkipName.Length()) {
168 if (aName->String().SubString
169 (1, aSkipName.Length()).IsEqual(aSkipName)) {
177 TCollection_ExtendedString aNameExt (aName->ToCString());
180 TopoDS_Shape S = GetShape(theEnti, theTP);
186 // as PRODUCT can be included in the main shape
187 // several times, we look here for all iclusions.
188 Standard_Integer isub, nbSubs = theIndices.Extent();
190 for (isub = 1; isub <= nbSubs; isub++) {
191 TopoDS_Shape aSub = theIndices.FindKey(isub);
193 if (aSub.IsPartner(S)) {
194 TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
197 TDataStd_Name::Set(L, aNameExt);
203 //=============================================================================
207 //=============================================================================
209 static void StoreMaterial
210 (const Handle(Standard_Transient) &theEnti,
211 const TopTools_IndexedMapOfShape &theIndices,
212 const Handle(Transfer_TransientProcess) &theTP,
213 const TDF_Label &theShapeLabel)
215 // Treat Product Definition Shape only.
216 Handle(StepRepr_ProductDefinitionShape) aPDS =
217 Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
218 Handle(StepBasic_ProductDefinition) aProdDef;
220 if(aPDS.IsNull() == Standard_False) {
221 // Product Definition Shape ==> Product Definition
222 aProdDef = aPDS->Definition().ProductDefinition();
225 if (aProdDef.IsNull() == Standard_False) {
226 // Product Definition ==> Property Definition
227 const Interface_Graph &aGraph = theTP->Graph();
228 Interface_EntityIterator aSubs = aGraph.Sharings(aProdDef);
231 for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
232 Handle(StepRepr_PropertyDefinition) aPropD =
233 Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
235 if(aPropD.IsNull() == Standard_False) {
236 // Property Definition ==> Representation.
237 Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
239 for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
240 Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
241 Handle(StepRepr_PropertyDefinitionRepresentation)::
242 DownCast(aSubs1.Value());
244 if(aPDR.IsNull() == Standard_False) {
245 // Property Definition ==> Material Name.
246 Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
248 if(aRepr.IsNull() == Standard_False) {
251 for(ir = 1; ir <= aRepr->NbItems(); ir++) {
252 Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
253 Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
254 Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
256 if(aDRI.IsNull() == Standard_False) {
257 // Get shape from Product Definition
258 Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
260 if(aMatName.IsNull() == Standard_False) {
261 TCollection_ExtendedString
262 aMatNameExt (aMatName->ToCString());
264 if (aShape.IsNull()) {
266 aShape = GetShape(aProdDef, theTP);
268 if (aShape.IsNull()) {
273 // as PRODUCT can be included in the main shape
274 // several times, we look here for all iclusions.
275 Standard_Integer isub, nbSubs = theIndices.Extent();
277 for (isub = 1; isub <= nbSubs; isub++) {
278 TopoDS_Shape aSub = theIndices.FindKey(isub);
280 if (aSub.IsPartner(aShape)) {
282 GetLabel(aProdDef, theShapeLabel, aSub);
285 TDataStd_Comment::Set(aLabel, aMatNameExt);
299 //=============================================================================
303 //=============================================================================
305 Handle(TCollection_HAsciiString) GetValue (const TCollection_AsciiString& theFileName,
306 const TCollection_AsciiString& theParameterName,
307 TCollection_AsciiString& theError)
309 Handle(TCollection_HAsciiString) aValue;
311 if (theParameterName != "LEN_UNITS") {
312 theError = theParameterName + " parameter reading is not supported by STEP plugin";
316 // Set "C" numeric locale to save numbers correctly
317 // Kernel_Utils::Localizer loc;
319 STEPControl_Reader aReader;
321 Interface_Static::SetCVal("xstep.cascade.unit","M");
322 Interface_Static::SetIVal("read.step.ideas", 1);
323 Interface_Static::SetIVal("read.step.nonmanifold", 1);
326 #if OCC_VERSION_LARGE > 0x06010000
329 IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.ToCString());
330 if (status == IFSelect_RetDone) {
331 TColStd_SequenceOfAsciiString anUnitLengthNames;
332 TColStd_SequenceOfAsciiString anUnitAngleNames;
333 TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
334 aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
335 if (anUnitLengthNames.Length() > 0) {
336 aValue = new TCollection_HAsciiString( anUnitLengthNames.First() );
338 TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
339 if (aLenUnits == "millimetre")
340 aValue = new TCollection_HAsciiString ("MM");
341 else if (aLenUnits == "centimetre")
342 aValue = new TCollection_HAsciiString ("CM");
343 else if (aLenUnits == "metre")
344 aValue = new TCollection_HAsciiString ("M");
345 else if (aLenUnits == "INCH")
346 aValue = new TCollection_HAsciiString ("INCH");
347 // TODO (for other units than mm, cm, m or inch)
348 //else if (aLenUnits == "")
349 // aValue = new TCollection_HAsciiString ("");
352 //std::cout << "$$$ --- " << anUnitLengthNames.First();
353 //for (int ii = 2; ii <= anUnitLengthNames.Length(); ii++)
354 // std::cout << ", " << anUnitLengthNames.Value(ii);
355 //std::cout << std::endl;
361 theError = theFileName + " reading failed";
364 catch (Standard_Failure) {
365 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
366 theError = aFail->GetMessageString();
372 std::shared_ptr<GeomAPI_Shape> STEPImport(const std::string& theFileName,
373 const std::string& theFormatName,
374 std::string& theError)
376 TopoDS_Shape aResShape;
378 // Set "C" numeric locale to save numbers correctly
379 // Kernel_Utils::Localizer loc;
381 STEPControl_Reader aReader;
383 //VSR: 16/09/09: Convert to METERS
384 Interface_Static::SetCVal("xstep.cascade.unit","M");
385 Interface_Static::SetIVal("read.step.ideas", 1);
386 Interface_Static::SetIVal("read.step.nonmanifold", 1);
389 TopoDS_Compound compound;
390 B.MakeCompound(compound);
395 IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.c_str());
397 if (status == IFSelect_RetDone) {
399 // Regard or not the model units
400 if (theFormatName == "STEP_SCALE") {
401 // set UnitFlag to units from file
402 TColStd_SequenceOfAsciiString anUnitLengthNames;
403 TColStd_SequenceOfAsciiString anUnitAngleNames;
404 TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
405 aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
406 if (anUnitLengthNames.Length() > 0) {
407 TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
408 if (aLenUnits == "millimetre")
409 Interface_Static::SetCVal("xstep.cascade.unit", "MM");
410 else if (aLenUnits == "centimetre")
411 Interface_Static::SetCVal("xstep.cascade.unit", "CM");
412 else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
413 Interface_Static::SetCVal("xstep.cascade.unit", "M");
414 else if (aLenUnits == "INCH")
415 Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
417 theError = "The file contains not supported units.";
418 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
419 aGeomShape->setImpl(new TopoDS_Shape(aResShape));
422 // TODO (for other units than mm, cm, m or inch)
423 //else if (aLenUnits == "")
424 // Interface_Static::SetCVal("xstep.cascade.unit", "???");
428 //cout<<"need re-scale a model"<<endl;
429 // set UnitFlag to 'meter'
430 Interface_Static::SetCVal("xstep.cascade.unit","M");
433 Standard_Boolean failsonly = Standard_False;
434 aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
437 Standard_Integer nbr = aReader.NbRootsForTransfer();
438 aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
440 for (Standard_Integer n = 1; n <= nbr; n++) {
441 Standard_Boolean ok = aReader.TransferRoot(n);
442 /* Collecting resulting entities */
443 Standard_Integer nbs = aReader.NbShapes();
446 // THROW_SALOME_CORBA_EXCEPTION("Exception catched in GEOM_Gen_i::ImportStep", SALOME::BAD_PARAM);
447 continue; // skip empty root
449 /* For a single entity */
450 else if (nbr == 1 && nbs == 1) {
451 aResShape = aReader.Shape(1);
452 // ATTENTION: this is a workaround for mantis issue 0020442 remark 0010776
453 // It should be removed after patching OCCT for bug OCC22436
454 // (fix for OCCT is expected in service pack next to OCCT6.3sp12)
455 if (aResShape.ShapeType() == TopAbs_COMPOUND) {
457 TopoDS_Shape currShape;
458 TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
459 for (; It.More(); It.Next()) {
461 currShape = It.Value();
464 aResShape = currShape;
470 for (Standard_Integer i = 1; i <= nbs; i++) {
471 TopoDS_Shape aShape = aReader.Shape(i);
472 if (aShape.IsNull()) {
473 // THROW_SALOME_CORBA_EXCEPTION("Null shape in GEOM_Gen_i::ImportStep", SALOME::BAD_PARAM) ;
478 B.Add(compound, aShape);
482 if (aResShape.IsNull())
483 aResShape = compound;
485 // Check if any BRep entity has been read, there must be at least a vertex
486 if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
488 theError = "No geometrical data in the imported file.";
489 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
490 aGeomShape->setImpl(new TopoDS_Shape());
494 theError = "Wrong format of the imported file. Can't import file.";
498 catch (Standard_Failure) {
499 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
500 theError = aFail->GetMessageString();
503 // Return previous locale
504 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
505 aGeomShape->setImpl(new TopoDS_Shape(aResShape));