diff --git a/src/STEPControl/STEPControl_ActorRead.cxx b/src/STEPControl/STEPControl_ActorRead.cxx index 4ff530270e..fba9415d53 100644 --- a/src/STEPControl/STEPControl_ActorRead.cxx +++ b/src/STEPControl/STEPControl_ActorRead.cxx @@ -17,6 +17,7 @@ //gka,abv 14.04.99 S4136: maintain unit context, precision and maxtolerance values #include +#include #include #include #include @@ -30,8 +31,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -334,7 +337,10 @@ Handle(Transfer_Binder) STEPControl_ActorRead::Transfer } // [END] Get version of preprocessor (to detect I-Deas case) (ssv; 23.11.2010) Standard_Boolean aTrsfUse = (aStepModel->InternalParameters.ReadRootTransformation == 1); - return TransferShape(start, TP, aLocalFactors, Standard_True, aTrsfUse, theProgress); + auto aResult = TransferShape(start, TP, aLocalFactors, Standard_True, aTrsfUse, theProgress); + if (Interface_Static::IVal("read.step.parallel.healing") == 0) + PostHealing(TP); + return aResult; } @@ -1487,13 +1493,18 @@ Handle(TransferBRep_ShapeBinder) STEPControl_ActorRead::TransferEntity // Apply ShapeFix (on manifold shapes only. Non-manifold topology is processed separately: ssv; 13.11.2010) if (isManifold && aHasGeom) { - Handle(Standard_Transient) info; - mappedShape = - XSAlgo::AlgoContainer()->ProcessShape( mappedShape, myPrecision, myMaxTol, - "read.step.resource.name", - "read.step.sequence", info, - aPS.Next()); - XSAlgo::AlgoContainer()->MergeTransferInfo(TP, info, nbTPitems); + if (Interface_Static::IVal("read.step.parallel.healing") != 0) + { + Handle(Standard_Transient) info; + mappedShape = + XSAlgo::AlgoContainer()->ProcessShape(mappedShape, myPrecision, myMaxTol, + "read.step.resource.name", + "read.step.sequence", info, + aPS.Next()); + XSAlgo::AlgoContainer()->MergeTransferInfo(TP, info, nbTPitems); + } + else + myShapesToHeal.Add(mappedShape); } } found = !mappedShape.IsNull(); @@ -2137,3 +2148,67 @@ TopoDS_Shape STEPControl_ActorRead::TransferRelatedSRR(const Handle(Transfer_Tra } return aResult; } + +//======================================================================= +// Method : PostHealing +// Purpose : postprocess shape healing +//======================================================================= +Standard_EXPORT void STEPControl_ActorRead::PostHealing(const Handle(Transfer_TransientProcess)& TP) +{ + NCollection_Array1 aInfos(1, myShapesToHeal.Size()); + NCollection_Array1 aOrigToCopyMapArr(1, myShapesToHeal.Size()); + NCollection_Array1 aCopyToOrigMapArr(1, myShapesToHeal.Size()); + + auto aForLoop = [&](const int i) { + auto& anOrig = myShapesToHeal.FindKey(i); + BRepBuilderAPI_Copy aCurCopy(anOrig, true, true); + TopoDS_Shape aCopy = aCurCopy.Shape(); + // Collect all the modified shapes in Copy() for further update of binders not to lost attached attributes + for (int aTypeIt = anOrig.ShapeType() + 1; aTypeIt <= TopAbs_VERTEX; aTypeIt++) + { + for (TopExp_Explorer anExp(anOrig, (TopAbs_ShapeEnum)aTypeIt); anExp.More(); anExp.Next()) + { + const TopoDS_Shape& aSx = anExp.Current(); + const TopoDS_Shape& aModifShape = aCurCopy.ModifiedShape(aSx); + aOrigToCopyMapArr.ChangeValue(i).Bind(aSx, aModifShape); + aCopyToOrigMapArr.ChangeValue(i).Bind(aModifShape, aSx); + } + } + Handle(Standard_Transient) anInfo; + aCopy = XSAlgo::AlgoContainer()->ProcessShape(aCopy, myPrecision, myMaxTol, + "read.step.resource.name", + "read.step.sequence", aInfos[i], + Message_ProgressRange()); + *(Handle(TopoDS_TShape)&)anOrig.TShape() = *aCopy.TShape(); + }; + OSD_Parallel::For(1, myShapesToHeal.Size() + 1, aForLoop); + + // Update Shape context for correct attributes attaching + Handle(ShapeProcess_ShapeContext) aFullContext = new ShapeProcess_ShapeContext(TopoDS_Shape(), "", ""); + TopTools_DataMapOfShapeShape& aHealedMap = (TopTools_DataMapOfShapeShape&)aFullContext->Map(); + + // Copy maps to the common binders map + for (int i = 1; i <= aOrigToCopyMapArr.Size(); i++) + { + const auto& aForwMap = aOrigToCopyMapArr.Value(i); + const auto& aRevMap = aCopyToOrigMapArr.Value(i); + Handle(ShapeProcess_ShapeContext) aContext = aInfos.Value(i); + + for (TopTools_DataMapOfShapeShape::Iterator aMapIt(aForwMap); aMapIt.More(); aMapIt.Next()) + { + aHealedMap.Bind(aMapIt.Key(), aMapIt.Value()); + } + for (TopTools_DataMapOfShapeShape::Iterator anIter(aContext->Map()); anIter.More(); anIter.Next()) + { + TopoDS_Shape aShape; + if (aRevMap.Find(anIter.Key(), aShape)) + { + aHealedMap.Bind(aShape, anIter.Value()); + } + } + } + + XSAlgo::AlgoContainer()->MergeTransferInfo(TP, aFullContext); + + CleanShapesToHeal(); +} diff --git a/src/STEPControl/STEPControl_ActorRead.hxx b/src/STEPControl/STEPControl_ActorRead.hxx index 667a8176b7..415917d310 100644 --- a/src/STEPControl/STEPControl_ActorRead.hxx +++ b/src/STEPControl/STEPControl_ActorRead.hxx @@ -26,6 +26,7 @@ #include #include #include +#include #include class StepRepr_Representation; @@ -115,7 +116,14 @@ public: const StepData_Factors& theLocalFactors); + //! Heals the collected during transferring shapes + Standard_EXPORT void PostHealing(const Handle(Transfer_TransientProcess)& TP); + //! Cleans collected for post healing shapes. + inline void CleanShapesToHeal() + { + myShapesToHeal.Clear(); + } DEFINE_STANDARD_RTTIEXT(STEPControl_ActorRead,Transfer_ActorOfTransientProcess) @@ -219,6 +227,7 @@ private: Standard_Real myMaxTol; Handle(StepRepr_Representation) mySRContext; Handle(Interface_InterfaceModel) myModel; + NCollection_IndexedMap myShapesToHeal; }; diff --git a/src/STEPControl/STEPControl_Controller.cxx b/src/STEPControl/STEPControl_Controller.cxx index 2b45463e6a..18d69b587b 100644 --- a/src/STEPControl/STEPControl_Controller.cxx +++ b/src/STEPControl/STEPControl_Controller.cxx @@ -272,6 +272,12 @@ STEPControl_Controller::STEPControl_Controller () Interface_Static::Init("step", "read.step.root.transformation", '&', "eval ON"); Interface_Static::SetCVal("read.step.root.transformation", "ON"); + Interface_Static::Init("step", "read.step.parallel.healing", 'e', ""); + Interface_Static::Init("step", "read.step.parallel.healing", '&', "enum 0"); + Interface_Static::Init("step", "read.step.parallel.healing", '&', "eval ON"); + Interface_Static::Init("step", "read.step.parallel.healing", '&', "eval OFF"); + Interface_Static::SetCVal("read.step.parallel.healing", "ON"); + // STEP file encoding for names translation // Note: the numbers should be consistent with Resource_FormatType enumeration Interface_Static::Init("step", "read.step.codepage", 'e', "");