Salome HOME
Bos #20438: [CEA] SIGSEGV in SHAPER and GEOM in Pipe binormal. Correction to obtain...
[modules/geom.git] / src / STEPPlugin / STEPPlugin_ImportDriver.cxx
index 1ca22118e79163203ee7375690a15dac40610f6a..25637a7439f6f76610397e53f067795334af5165 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2014-2021  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -47,6 +47,7 @@
 #include <StepGeom_GeometricRepresentationItem.hxx>
 #include <StepShape_TopologicalRepresentationItem.hxx>
 #include <StepRepr_DescriptiveRepresentationItem.hxx>
+#include <StepRepr_NextAssemblyUsageOccurrence.hxx>
 #include <StepRepr_ProductDefinitionShape.hxx>
 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
 #include <StepRepr_Representation.hxx>
 #include <BRep_Builder.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TColStd_SequenceOfAsciiString.hxx>
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
-//=============================================================================
-/*!
- *  GetShape()
- */
-//=============================================================================
-
-TopoDS_Shape GetShape(const Handle(Standard_Transient)        &theEnti,
-                      const Handle(Transfer_TransientProcess) &theTP)
+namespace
 {
-  TopoDS_Shape            aResult;
-  Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
+  //=============================================================================
+  /*!
+   *  GetShape()
+   */
+  //=============================================================================
+
+  TopoDS_Shape GetShape(const Handle(Standard_Transient)        &theEnti,
+                        const Handle(Transfer_TransientProcess) &theTP)
+  {
+    TopoDS_Shape            aResult;
+    Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
+
+    if (aBinder.IsNull()) {
+      return aResult;
+    }
+
+    aResult = TransferBRep::ShapeResult(aBinder);
 
-  if (aBinder.IsNull()) {
     return aResult;
   }
 
-  aResult = TransferBRep::ShapeResult(aBinder);
+  //=============================================================================
+  /*!
+   *  GetLabel()
+   */
+  //=============================================================================
 
-  return aResult;
-}
+  TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
+                     const TDF_Label                  &theShapeLabel,
+                     const TopoDS_Shape               &aShape)
+  {
+    TDF_Label aResult;
 
-//=============================================================================
-/*!
- *  GetLabel()
- */
-//=============================================================================
+    if (theEnti->IsKind
+        (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
+      // check all named shapes using iterator
+      TDF_ChildIDIterator anIt
+        (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
 
-TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
-                   const TDF_Label                  &theShapeLabel,
-                   const TopoDS_Shape               &aShape)
-{
-  TDF_Label aResult;
+      for (; anIt.More(); anIt.Next()) {
+        Handle(TDataStd_Name) nameAttr =
+          Handle(TDataStd_Name)::DownCast(anIt.Value());
 
-  if (theEnti->IsKind
-            (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
-    // check all named shapes using iterator
-    TDF_ChildIDIterator anIt
-      (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
+        if (nameAttr.IsNull()) {
+          continue;
+        }
 
-    for (; anIt.More(); anIt.Next()) {
-      Handle(TDataStd_Name) nameAttr =
-        Handle(TDataStd_Name)::DownCast(anIt.Value());
+        TDF_Label aLab = nameAttr->Label();
+        Handle(TNaming_NamedShape) shAttr;
 
-      if (nameAttr.IsNull()) {
-        continue;
+        if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
+            shAttr->Get().IsEqual(aShape)) {
+          aResult = aLab;
+        }
       }
+    }
 
-      TDF_Label aLab = nameAttr->Label();
-      Handle(TNaming_NamedShape) shAttr;
+    // create label and set shape
+    if (aResult.IsNull()) {
+      TDF_TagSource aTag;
 
-      if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
-          shAttr->Get().IsEqual(aShape)) {
-        aResult = aLab;
-      }
+      aResult = aTag.NewChild(theShapeLabel);
+
+      TNaming_Builder tnBuild (aResult);
+
+      tnBuild.Generated(aShape);
     }
+
+    return aResult;
   }
 
-  // create label and set shape
-  if (aResult.IsNull()) {
-    TDF_TagSource aTag;
+  //=============================================================================
+  /*!
+   *  GetAllParents()
+   */
+  //=============================================================================
 
-    aResult = aTag.NewChild(theShapeLabel);
+  Standard_Boolean GetAllParents(const TopoDS_Shape         &theShape,
+                                 const TopoDS_Shape         &theSubShape,
+                                       TopTools_ListOfShape &theParents)
+  {
+    const TopAbs_ShapeEnum aSubShType = theSubShape.ShapeType();
+    Standard_Boolean       aResult    = Standard_False;
 
-    TNaming_Builder tnBuild (aResult);
+    if (theShape.ShapeType() >= aSubShType) {
+      return aResult; // NULL shape
+    }
 
-    tnBuild.Generated(aShape);
-  }
+    TopoDS_Iterator     anIt(theShape);
+    TopTools_MapOfShape aMapFence;
 
-  return aResult;
-}
+    for (; anIt.More(); anIt.Next()) {
+      const TopoDS_Shape &aSubShape = anIt.Value();
 
-//=============================================================================
-/*!
- *  StoreName()
- */
-//=============================================================================
+      if (aMapFence.Add(aSubShape)) {
+        if (theSubShape.IsSame(aSubShape)) {
+          // The sub-shape is found. theShape is its parent.
+          theParents.Append(theShape);
+          aResult = Standard_True;
+          break;
+        }
 
-void StoreName( const Handle(Standard_Transient)        &theEnti,
-                const TopTools_IndexedMapOfShape        &theIndices,
-                const Handle(Transfer_TransientProcess) &theTP,
-                const TDF_Label                         &theShapeLabel)
-{
-  Handle(TCollection_HAsciiString) aName;
-
-  if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
-      theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
-    aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
-  } else {
-    Handle(StepBasic_ProductDefinition) PD =
-      Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
-
-    if (PD.IsNull() == Standard_False) {
-      Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
-      aName = Prod->Name();
+        if (aSubShape.ShapeType() < aSubShType) {
+          if (GetAllParents(aSubShape, theSubShape, theParents)) {
+            // The sub-shape is found.
+            theParents.Append(theShape);
+            aResult = Standard_True;
+            break;
+          }
+        }
+      }
     }
+
+    return aResult;
   }
 
-  bool isValidName = false;
+  //=============================================================================
+  /*!
+   *  BuildModifiedShape()
+   */
+  //=============================================================================
+
+  TopoDS_Shape BuildModifiedShape
+              (const TopoDS_Shape                 &theShape,
+                     TopTools_DataMapOfShapeShape &theMapModified)
+  {
+    // Check if the shape is modified.
+    TopoDS_Shape     aFwdShape  = theShape.Oriented(TopAbs_FORWARD);
+    TopoDS_Iterator  anIt(aFwdShape);
+    Standard_Boolean isModified = Standard_False;
+
+    for (; anIt.More(); anIt.Next()) {
+      if (theMapModified.IsBound(anIt.Value())) {
+        isModified = Standard_True;
+        break;
+      }
+    }
+
+    TopoDS_Shape aResult;
+
+    if (isModified) {
+      BRep_Builder aBuilder;
+
+      aResult = aFwdShape.EmptyCopied();
+
+      for (anIt.Initialize(aFwdShape); anIt.More(); anIt.Next()) {
+        const TopoDS_Shape &aSubShape = anIt.Value();
+
+        if (theMapModified.IsBound(aSubShape)) {
+          TopoDS_Shape aModifSubShape = theMapModified.Find(aSubShape);
+
+          if (aModifSubShape.IsNull()) {
+            // Recursively compute the sub-shape.
+            aModifSubShape = BuildModifiedShape(aSubShape, theMapModified);
+          }
 
-  if (aName.IsNull() == Standard_False) {
-    isValidName = true;
+          aBuilder.Add(aResult, aModifSubShape);
+        } else {
+          aBuilder.Add(aResult, aSubShape);
+        }
+      }
 
-    if (aName->UsefullLength() < 1) {
-      isValidName = false;
-    } else if (aName->UsefullLength() == 4 &&
-               toupper (aName->Value(1)) == 'N' &&
-               toupper (aName->Value(2)) == 'O' &&
-               toupper (aName->Value(3)) == 'N' &&
-               toupper (aName->Value(4)) == 'E') {
-      // skip 'N0NE' name
-      isValidName = false;
+      // Set the result shape orientation.
+      aResult.Orientation(theShape.Orientation());
+      theMapModified.Bind(theShape, aResult);
     } else {
-      // special check to pass names like "Open CASCADE STEP translator 6.3 1"
-      TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
+      aResult = theShape;
+    }
+
+    return aResult;
+  }
+
+  //=============================================================================
+  /*!
+   *  CreateAssemblies()
+   */
+  //=============================================================================
 
-      if (aName->Length() >= aSkipName.Length()) {
-        if (aName->String().SubString
-                            (1, aSkipName.Length()).IsEqual(aSkipName)) {
-          isValidName = false;
+  TopoDS_Shape CreateAssemblies
+              (const STEPControl_Reader           &theReader,
+               const TopoDS_Shape                 &theShape,
+                     TopTools_DataMapOfShapeShape &theMapShapeAssembly)
+  {
+    TopoDS_Shape                     aResult = theShape;
+    Handle(XSControl_TransferReader) aTR     = theReader.WS()->TransferReader();
+    TopTools_ListOfShape             aListAssemblies;
+
+    if (!aTR.IsNull()) {
+      Handle(Interface_InterfaceModel)  aModel      = theReader.WS()->Model();
+      Handle(Transfer_TransientProcess) aTP         = aTR->TransientProcess();
+      Standard_Integer                  aNbEntities = aModel->NbEntities();
+      Standard_Integer                  i;
+      Handle(Standard_Type)             aNAUOType   =
+              STANDARD_TYPE(StepRepr_NextAssemblyUsageOccurrence);
+
+      for (i = 1; i <= aNbEntities; i++) {
+        Handle(Standard_Transient) anEnti = aModel->Value(i);
+
+        if (anEnti->IsKind(aNAUOType)) {
+          // This is an assembly. Find target shape
+          TopoDS_Shape aShape = GetShape(anEnti, aTP);
+
+          if (aShape.IsNull()) {
+            continue;
+          }
+
+          if (aShape.ShapeType() != TopAbs_COMPOUND) {
+            aListAssemblies.Append(aShape);
+          }
         }
       }
     }
+
+    // Create assemblies.
+    if (!aListAssemblies.IsEmpty()) {
+      TopTools_ListIteratorOfListOfShape anIter(aListAssemblies);
+      BRep_Builder                       aBuilder;
+
+      for (; anIter.More(); anIter.Next()) {
+        const TopoDS_Shape   &aShape  = anIter.Value();
+        TopTools_ListOfShape  aParents;
+
+        if (GetAllParents(theShape, aShape, aParents) &&
+            aParents.First().ShapeType() == TopAbs_COMPOUND) {
+          TopoDS_Compound                    aComp;
+          TopTools_ListIteratorOfListOfShape aParentIter(aParents);
+
+          // Fill theMapShapeAssembly.
+          for (; aParentIter.More(); aParentIter.Next()) {
+            theMapShapeAssembly.Bind(aParentIter.Value(), TopoDS_Shape());
+          }
+
+          aBuilder.MakeCompound(aComp);
+          aBuilder.Add(aComp, aShape);
+          theMapShapeAssembly.Bind(aShape, aComp);
+        }
+      }
+
+      // Build a new shape.
+      aResult = BuildModifiedShape(theShape, theMapShapeAssembly);
+    }
+
+    return aResult;
   }
 
-  if (isValidName) {
-    TCollection_ExtendedString aNameExt (aName->ToCString());
+  //=============================================================================
+  /*!
+   *  StoreName()
+   */
+  //=============================================================================
+
+  void StoreName(const Handle(Standard_Transient)        &theEnti,
+                 const TopTools_IndexedMapOfShape        &theIndices,
+                 const Handle(XSControl_WorkSession)     &theWS,
+                 const Handle(Transfer_TransientProcess) &theTP,
+                 const TDF_Label                         &theShapeLabel,
+                       TopTools_DataMapOfShapeShape      &theMapShapeAssembly)
+  {
+    Handle(TCollection_HAsciiString) aName;
 
-    // find target shape
-    TopoDS_Shape S = GetShape(theEnti, theTP);
+    if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
+        theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
+      aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
+    } else if (theEnti->IsKind(STANDARD_TYPE(StepRepr_NextAssemblyUsageOccurrence))) {
+      Handle(StepRepr_NextAssemblyUsageOccurrence) aNAUO =
+        Handle(StepRepr_NextAssemblyUsageOccurrence)::DownCast(theEnti);
+
+      Interface_EntityIterator aSubs = theWS->Graph().Sharings(aNAUO);
+
+      for (aSubs.Start(); aSubs.More(); aSubs.Next()) {
+        Handle(StepRepr_ProductDefinitionShape) aPDS =
+          Handle(StepRepr_ProductDefinitionShape)::DownCast(aSubs.Value());
+
+        if(aPDS.IsNull()) {
+          continue;
+        }
 
-    if (S.IsNull()) {
-      return;
+        Handle(StepBasic_ProductDefinitionRelationship) aPDR =
+          aPDS->Definition().ProductDefinitionRelationship();
+
+        if (aPDR.IsNull()) {
+          continue;
+        }
+
+        if (aPDR->HasDescription() && aPDR->Description()->UsefullLength() >0) {
+          aName = aPDR->Description();
+        } else if (!aPDR->Name().IsNull() && aPDR->Name()->UsefullLength() >0 ) {
+          aName = aPDR->Name();
+        } else if (!aPDR->Id().IsNull()) {
+          aName = aPDR->Id();
+        }
+      }
+    } else {
+      Handle(StepBasic_ProductDefinition) PD =
+        Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
+
+      if (PD.IsNull() == Standard_False) {
+        Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
+        aName = Prod->Name();
+      }
+    }
+
+    bool isValidName = false;
+
+    if (aName.IsNull() == Standard_False) {
+      isValidName = true;
+
+      if (aName->UsefullLength() < 1) {
+        isValidName = false;
+      } else if (aName->UsefullLength() == 4 &&
+                 toupper (aName->Value(1)) == 'N' &&
+                 toupper (aName->Value(2)) == 'O' &&
+                 toupper (aName->Value(3)) == 'N' &&
+                 toupper (aName->Value(4)) == 'E') {
+        // skip 'N0NE' name
+        isValidName = false;
+      } else {
+        // special check to pass names like "Open CASCADE STEP translator 6.3 1"
+        TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
+
+        if (aName->Length() >= aSkipName.Length()) {
+          if (aName->String().SubString
+              (1, aSkipName.Length()).IsEqual(aSkipName)) {
+            isValidName = false;
+          }
+        }
+      }
     }
 
-    // as PRODUCT can be included in the main shape
-    // several times, we look here for all iclusions.
-    Standard_Integer isub, nbSubs = theIndices.Extent();
+    if (isValidName) {
+      TCollection_ExtendedString aNameExt (aName->ToCString());
+
+      // find target shape
+      TopoDS_Shape S = GetShape(theEnti, theTP);
+
+      if (theMapShapeAssembly.IsBound(S)) {
+        S = theMapShapeAssembly.Find(S);
+      }
+
+      if (S.IsNull()) {
+        return;
+      }
 
-    for (isub = 1; isub <= nbSubs; isub++) {
-      TopoDS_Shape aSub = theIndices.FindKey(isub);
+      // as PRODUCT can be included in the main shape
+      // several times, we look here for all iclusions.
+      Standard_Integer isub, nbSubs = theIndices.Extent();
 
-      if (aSub.IsPartner(S)) {
-        TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
+      for (isub = 1; isub <= nbSubs; isub++) {
+        TopoDS_Shape aSub = theIndices.FindKey(isub);
 
-        // set a name
-        TDataStd_Name::Set(L, aNameExt);
+        if (aSub.IsPartner(S)) {
+          TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
+
+          // set a name
+          TDataStd_Name::Set(L, aNameExt);
+        }
       }
     }
   }
-}
 
-//=============================================================================
-/*!
- *  StoreMaterial()
- */
-//=============================================================================
+  //=============================================================================
+  /*!
  *  StoreMaterial()
  */
+  //=============================================================================
 
-void StoreMaterial( const Handle(Standard_Transient)        &theEnti,
-                    const TopTools_IndexedMapOfShape        &theIndices,
-                    const Handle(Transfer_TransientProcess) &theTP,
-                    const TDF_Label                         &theShapeLabel )
-{
-  // Treat Product Definition Shape only.
-  Handle(StepRepr_ProductDefinitionShape) aPDS =
+  void StoreMaterial( const Handle(Standard_Transient)        &theEnti,
+                      const TopTools_IndexedMapOfShape        &theIndices,
+                      const Handle(Transfer_TransientProcess) &theTP,
+                      const TDF_Label                         &theShapeLabel )
+  {
+    // Treat Product Definition Shape only.
+    Handle(StepRepr_ProductDefinitionShape) aPDS =
       Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
-  Handle(StepBasic_ProductDefinition)     aProdDef;
+    Handle(StepBasic_ProductDefinition)     aProdDef;
 
-  if(aPDS.IsNull() == Standard_False) {
-    // Product Definition Shape ==> Product Definition
-    aProdDef = aPDS->Definition().ProductDefinition();
-  }
+    if(aPDS.IsNull() == Standard_False) {
+      // Product Definition Shape ==> Product Definition
+      aProdDef = aPDS->Definition().ProductDefinition();
+    }
 
-  if (aProdDef.IsNull() == Standard_False) {
-    // Product Definition ==> Property Definition
-    const Interface_Graph    &aGraph = theTP->Graph();
-    Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
-    TopoDS_Shape              aShape;
+    if (aProdDef.IsNull() == Standard_False) {
+      // Product Definition ==> Property Definition
+      const Interface_Graph    &aGraph = theTP->Graph();
+      Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
+      TopoDS_Shape              aShape;
 
-    for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
-      Handle(StepRepr_PropertyDefinition) aPropD =
-        Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
+      for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
+        Handle(StepRepr_PropertyDefinition) aPropD =
+          Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
 
-      if(aPropD.IsNull() == Standard_False) {
-        // Property Definition ==> Representation.
-        Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
+        if(aPropD.IsNull() == Standard_False) {
+          // Property Definition ==> Representation.
+          Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
 
-        for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
-          Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
-            Handle(StepRepr_PropertyDefinitionRepresentation)::
+          for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
+            Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
+              Handle(StepRepr_PropertyDefinitionRepresentation)::
               DownCast(aSubs1.Value());
 
-          if(aPDR.IsNull() == Standard_False) {
-            // Property Definition ==> Material Name.
-            Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
-
-            if(aRepr.IsNull() == Standard_False) {
-              Standard_Integer ir;
+            if(aPDR.IsNull() == Standard_False) {
+              // Property Definition ==> Material Name.
+              Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
 
-              for(ir = 1; ir <= aRepr->NbItems(); ir++) {
-                Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
-                Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
-                  Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
+              if(aRepr.IsNull() == Standard_False) {
+                Standard_Integer ir;
 
-                if(aDRI.IsNull() == Standard_False) {
-                  // Get shape from Product Definition
-                  Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
+                for(ir = 1; ir <= aRepr->NbItems(); ir++) {
+                  Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
+                  Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
+                    Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
 
-                  if(aMatName.IsNull() == Standard_False) {
-                    TCollection_ExtendedString
-                                 aMatNameExt (aMatName->ToCString());
+                  if(aDRI.IsNull() == Standard_False) {
+                    // Get shape from Product Definition
+                    Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
 
-                    if (aShape.IsNull()) {
-                      // Get the shape.
-                      aShape = GetShape(aProdDef, theTP);
+                    if(aMatName.IsNull() == Standard_False) {
+                      TCollection_ExtendedString
+                        aMatNameExt (aMatName->ToCString());
 
                       if (aShape.IsNull()) {
-                        return;
+                        // Get the shape.
+                        aShape = GetShape(aProdDef, theTP);
+
+                        if (aShape.IsNull()) {
+                          return;
+                        }
                       }
-                    }
 
-                    // as PRODUCT can be included in the main shape
-                    // several times, we look here for all iclusions.
-                    Standard_Integer isub, nbSubs = theIndices.Extent();
+                      // as PRODUCT can be included in the main shape
+                      // several times, we look here for all iclusions.
+                      Standard_Integer isub, nbSubs = theIndices.Extent();
 
-                    for (isub = 1; isub <= nbSubs; isub++) {
-                      TopoDS_Shape aSub = theIndices.FindKey(isub);
+                      for (isub = 1; isub <= nbSubs; isub++) {
+                        TopoDS_Shape aSub = theIndices.FindKey(isub);
 
-                      if (aSub.IsPartner(aShape)) {
-                        TDF_Label aLabel =
-                          GetLabel(aProdDef, theShapeLabel, aSub);
+                        if (aSub.IsPartner(aShape)) {
+                          TDF_Label aLabel =
+                            GetLabel(aProdDef, theShapeLabel, aSub);
 
-                        // set a name
-                        TDataStd_Comment::Set(aLabel, aMatNameExt);
+                          // set a name
+                          TDataStd_Comment::Set(aLabel, aMatNameExt);
+                        }
                       }
                     }
                   }
@@ -310,7 +527,53 @@ void StoreMaterial( const Handle(Standard_Transient)        &theEnti,
       }
     }
   }
-}
+
+  TCollection_AsciiString ToNamedUnit( const TCollection_AsciiString& unit )
+  {
+    TCollection_AsciiString result = unit;
+    result.LowerCase();
+    if ( result == "mil" ) result = "milliinch";
+    return result;
+  }
+
+  TCollection_AsciiString ToOcctUnit( const TCollection_AsciiString& unit, TCollection_AsciiString& error )
+  {
+    TCollection_AsciiString result = "M", u = ToNamedUnit(unit);
+    u.LowerCase();
+
+    if (u == "inch")
+      result = "INCH";
+    else if (u == "milliinch")
+      result = "MIL";
+    else if (u == "microinch")
+      result = "UIN";
+    else if (u == "foot")
+      result = "FT";
+    else if (u == "mile")
+      result = "MI";
+    else if (u == "metre")
+      result = "M";
+    else if (u == "kilometre")
+      result = "KM";
+    else if (u == "millimetre")
+      result = "MM";
+    else if (u == "centimetre")
+      result = "CM";
+    else if (u == "micrometre")
+      result = "UM";
+    else if (u.IsEmpty())
+      result = "M";
+    else
+      error = "The file contains not supported units";
+
+    // TODO (for other units)
+    // else
+    //  result = "??"
+
+    return result;
+  }
+
+} // end of namespace
 
 //=======================================================================
 //function : GetID
@@ -334,7 +597,7 @@ STEPPlugin_ImportDriver::STEPPlugin_ImportDriver()
 //function : Execute
 //purpose  :
 //=======================================================================
-Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) const
+Standard_Integer STEPPlugin_ImportDriver::Execute(Handle(TFunction_Logbook)& log) const
 {
   if( Label().IsNull() ) return 0;
   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction( Label() );
@@ -343,6 +606,7 @@ Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) cons
 
   TCollection_AsciiString aFileName = aData.GetFileName().ToCString();
   bool anIsIgnoreUnits = aData.GetIsIgnoreUnits();
+  bool isCreateAssemblies = aData.GetIsCreateAssemblies();
   TDF_Label aShapeLabel = aFunction->GetNamingEntry();
 
   MESSAGE("Import STEP from file " << aFileName.ToCString() );
@@ -377,21 +641,8 @@ Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) cons
         TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
         aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
         if (anUnitLengthNames.Length() > 0) {
-          TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
-          if (aLenUnits == "millimetre")
-            Interface_Static::SetCVal("xstep.cascade.unit", "MM");
-          else if (aLenUnits == "centimetre")
-            Interface_Static::SetCVal("xstep.cascade.unit", "CM");
-          else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
-            Interface_Static::SetCVal("xstep.cascade.unit", "M");
-          else if (aLenUnits == "INCH")
-            Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
-          else {
-            anError = "The file contains not supported units.";
-          }
-          // TODO (for other units than mm, cm, m or inch)
-          // else if (aLenUnits == "")
-          // Interface_Static::SetCVal("xstep.cascade.unit", "???");
+          TCollection_AsciiString aLenUnits = ToOcctUnit(anUnitLengthNames.First(), anError);
+          Interface_Static::SetCVal("xstep.cascade.unit", aLenUnits.ToCString());
         }
       }
       else {
@@ -403,48 +654,94 @@ Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) cons
       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
 
       // Root transfers
-      Standard_Integer nbr = aReader.NbRootsForTransfer();
+      Standard_Integer aNbRoots = aReader.NbRootsForTransfer();
+      Standard_Integer i;
+
       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
 
-      for (Standard_Integer n = 1; n <= nbr; n++) {
-        Standard_Boolean ok = aReader.TransferRoot(n);
-        // Collecting resulting entities
-        Standard_Integer nbs = aReader.NbShapes();
-        if (!ok || nbs == 0)
-          continue; // skip empty root
-
-        // For a single entity
-        else if (nbr == 1 && nbs == 1) {
-          aResShape = aReader.Shape(1);
-          if (aResShape.ShapeType() == TopAbs_COMPOUND) {
-            int nbSub1 = 0;
-            TopoDS_Shape currShape;
-            TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
-            for (; It.More(); It.Next()) {
-              nbSub1++;
-              currShape = It.Value();
-            }
-            if (nbSub1 == 1)
-              aResShape = currShape;
+      for (i = 1; i <= aNbRoots; i++) {
+        aReader.TransferRoot(i);
+      }
+
+      // Create result shape
+      const Standard_Integer aNbShapes = aReader.NbShapes();
+      TopTools_ListOfShape   aListResShapes;
+
+      if (isCreateAssemblies) {
+        for (i = 1; i <= aNbShapes; i++) {
+          TopoDS_Shape aShape = aReader.Shape(i);
+
+          if (aShape.IsNull()) {
+            continue;
           }
-          break;
-        }
 
-        for (Standard_Integer i = 1; i <= nbs; i++) {
+          aListResShapes.Append(aShape);
+        }
+      } else {
+        for (i = 1; i <= aNbShapes; i++) {
           TopoDS_Shape aShape = aReader.Shape(i);
-          if (aShape.IsNull())
+
+          if (aShape.IsNull()) {
             continue;
-          else
-            B.Add(compound, aShape);
+          }
+
+          if (aShape.ShapeType() == TopAbs_COMPOUND) {
+            int             aNbSub = 0;
+            TopoDS_Shape    aSubShape;
+            TopoDS_Iterator anIt (aShape, Standard_True, Standard_True);
+
+            for (; anIt.More(); anIt.Next()) {
+              aNbSub++;
+              aSubShape = anIt.Value();
+            }
+
+            if (aNbSub == 1) {
+              // Use the single sub-shape
+              aListResShapes.Append(aSubShape);
+            } else if (aNbSub > 1) {
+              // Use the shape
+              aListResShapes.Append(aShape);
+            }
+          } else {
+            // Use the shape itself
+            aListResShapes.Append(aShape);
+          }
         }
       }
-      if( aResShape.IsNull() )
-        aResShape = compound;
+
+      // Construct result shape.
+      if (!aListResShapes.IsEmpty()) {
+        if (aListResShapes.Extent() == 1) {
+          // Use the single shape.
+          aResShape = aListResShapes.First();
+        } else {
+          // Make a compound of result shapes.
+          TopTools_ListIteratorOfListOfShape anIt(aListResShapes);
+
+          for (; anIt.More(); anIt.Next()) {
+            B.Add(compound, anIt.Value());
+          }
+
+          aResShape = compound;
+        }
+      }
+
+      if( aResShape.IsNull() ) {
+        StdFail_NotDone::Raise("Null result shape");
+        return 0;
+      }
 
       // Check if any BRep entity has been read, there must be at least a vertex
       if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
         StdFail_NotDone::Raise( "No geometrical data in the imported file." );
 
+      // Create assemblies in the shape, if they are not created yet.
+      TopTools_DataMapOfShapeShape aMapShapeAssembly;
+
+      if (isCreateAssemblies) {
+        aResShape = CreateAssemblies(aReader, aResShape, aMapShapeAssembly);
+      }
+
       // BEGIN: Store names and materials of sub-shapes from file
       TopTools_IndexedMapOfShape anIndices;
       TopExp::MapShapes(aResShape, anIndices);
@@ -460,7 +757,8 @@ Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) cons
           Handle(Standard_Transient) enti = Model->Value(ie);
 
           // Store names.
-          StoreName(enti, anIndices, TP, aShapeLabel);
+          StoreName(enti, anIndices, aReader.WS(),
+                    TP, aShapeLabel, aMapShapeAssembly);
 
           // Store materials.
           StoreMaterial(enti, anIndices, TP, aShapeLabel);
@@ -489,9 +787,8 @@ Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) cons
       aResShape.Nullify();
     }
   }
-  catch( Standard_Failure ) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    anError = aFail->GetMessageString();
+  catch( Standard_Failure& aFail ) {
+    anError = aFail.GetMessageString();
     aResShape.Nullify();
   }
 
@@ -502,20 +799,11 @@ Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) cons
 
   aFunction->SetValue( aResShape );
 
-  log.SetTouched( Label() );
+  log->SetTouched(Label());
 
   return 1;
 }
 
-//=======================================================================
-//function : MustExecute
-//purpose  :
-//=======================================================================
-Standard_Boolean STEPPlugin_ImportDriver::MustExecute( const TFunction_Logbook& ) const
-{
-  return Standard_True;
-}
-
 //================================================================================
 /*!
  * \brief Returns a name of creation operation and names and values of creation parameters
@@ -539,6 +827,7 @@ GetCreationInformation( std::string&             theOperationName,
     AddParam( theParams, "File name", aCI.GetFileName() );
     if( aCI.GetIsIgnoreUnits() )
       AddParam( theParams, "Format", "STEP_SCALE" );
+    AddParam( theParams, "Create Assemblies", aCI.GetIsCreateAssemblies() );
     break;
   default:
     return false;
@@ -548,10 +837,10 @@ GetCreationInformation( std::string&             theOperationName,
 
 TCollection_AsciiString
 STEPPlugin_ImportDriver::GetValue( const TCollection_AsciiString& theFileName,
-                                     const TCollection_AsciiString& theParameterName,
-                                     TCollection_AsciiString&       theError )
+                                   const TCollection_AsciiString& theParameterName,
+                                   TCollection_AsciiString&       theError )
 {
-  Handle(TCollection_HAsciiString) aValue;
+  TCollection_AsciiString aValue;
 
   if (theParameterName != "LEN_UNITS") {
     theError = theParameterName + " parameter reading is not supported by STEP plugin";
@@ -575,38 +864,17 @@ STEPPlugin_ImportDriver::GetValue( const TCollection_AsciiString& theFileName,
       TColStd_SequenceOfAsciiString anUnitAngleNames;
       TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
       aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
-      if (anUnitLengthNames.Length() > 0) {
-        aValue = new TCollection_HAsciiString( anUnitLengthNames.First() );
-        /*
-        TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
-        if (aLenUnits == "millimetre")
-          aValue = new TCollection_HAsciiString ("MM");
-        else if (aLenUnits == "centimetre")
-          aValue = new TCollection_HAsciiString ("CM");
-        else if (aLenUnits == "metre")
-          aValue = new TCollection_HAsciiString ("M");
-        else if (aLenUnits == "INCH")
-          aValue = new TCollection_HAsciiString ("INCH");
-        // TODO (for other units than mm, cm, m or inch)
-        //else if (aLenUnits == "")
-        //  aValue = new TCollection_HAsciiString ("");
-        */
-      }
+      if (anUnitLengthNames.Length() > 0)
+        aValue = ToNamedUnit( anUnitLengthNames.First() );
     }
     else {
       theError = theFileName + " reading failed";
     }
   }
-  catch( Standard_Failure ) {
-    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
-    theError = aFail->GetMessageString();
+  catch( Standard_Failure& aFail ) {
+    theError = aFail.GetMessageString();
   }
-  if (!aValue.IsNull())
-    return aValue->String();
-  else
-    return TCollection_AsciiString();
+  return aValue;
 }
 
-
-IMPLEMENT_STANDARD_HANDLE( STEPPlugin_ImportDriver, GEOM_BaseDriver );
-IMPLEMENT_STANDARD_RTTIEXT( STEPPlugin_ImportDriver, GEOM_BaseDriver );
+IMPLEMENT_STANDARD_RTTIEXT( STEPPlugin_ImportDriver, GEOM_BaseDriver )