// Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. //: k8 abv 6 Jan 99: unique names for PRODUCTs //: k9 abv 6 Jan 99: TR10: eliminating duplicated APPLICATION_CONTEXT entities // abv,gka 05.04.99: S4136: change parameters and update units // PTV 22.08.2002 OCC609 transfer solo vertices into step file. // PTV 16.09.2002 OCC725 transfer compound of vertices into one geometrical curve set. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include IMPLEMENT_STANDARD_RTTIEXT(STEPControl_ActorWrite, Transfer_ActorOfFinderProcess) // Transfer // TransferShape //: d6 // Non-manifold topology processing (ssv; 10.11.2010) // ============================================================================ // Function: DumpWhatIs // Purpose: Use it in debug mode to dump your shapes // ============================================================================ #ifdef OCCT_DEBUG static void DumpWhatIs(const TopoDS_Shape& S) { NCollection_Map aMapOfShape; aMapOfShape.Add(S); NCollection_List aListOfShape; aListOfShape.Append(S); NCollection_List::Iterator itL(aListOfShape); int nbSolids = 0, nbShells = 0, nbOpenShells = 0, nbFaces = 0, nbWires = 0, nbEdges = 0, nbVertexes = 0; for (; itL.More(); itL.Next()) { TopoDS_Iterator it(itL.Value()); for (; it.More(); it.Next()) { TopoDS_Shape aSubShape = it.Value(); if (!aMapOfShape.Add(aSubShape)) continue; aListOfShape.Append(aSubShape); if (aSubShape.ShapeType() == TopAbs_SOLID) nbSolids++; if (aSubShape.ShapeType() == TopAbs_SHELL) { if (!aSubShape.Closed()) nbOpenShells++; nbShells++; } if (aSubShape.ShapeType() == TopAbs_FACE) nbFaces++; if (aSubShape.ShapeType() == TopAbs_WIRE) nbWires++; if (aSubShape.ShapeType() == TopAbs_EDGE) nbEdges++; if (aSubShape.ShapeType() == TopAbs_VERTEX) nbVertexes++; } } std::cout << "//What is?// NB SOLIDS: " << nbSolids << std::endl; std::cout << "//What is?// NB SHELLS: " << nbShells << std::endl; std::cout << "//What is?// OPEN SHELLS: " << nbOpenShells << std::endl; std::cout << "//What is?// CLOSED SHELLS: " << nbShells - nbOpenShells << std::endl; std::cout << "//What is?// NB FACES: " << nbFaces << std::endl; std::cout << "//What is?// NB WIRES: " << nbWires << std::endl; std::cout << "//What is?// NB EDGES: " << nbEdges << std::endl; std::cout << "//What is?// NB VERTEXES: " << nbVertexes << std::endl; } #endif static bool hasGeometry(const TopoDS_Shape& theShape) { TopAbs_ShapeEnum aType = theShape.ShapeType(); if (aType == TopAbs_VERTEX) { return true; } else if (aType == TopAbs_EDGE) { occ::handle TE = occ::down_cast(theShape.TShape()); NCollection_List>::Iterator itrc(TE->Curves()); while (itrc.More()) { const occ::handle& CR = itrc.Value(); bool aHasGeometry = (CR->IsCurve3D() && !CR->Curve3D().IsNull()) || CR->IsCurveOnSurface() || CR->IsRegularity() || (CR->IsPolygon3D() && !CR->Polygon3D().IsNull()) || CR->IsPolygonOnTriangulation() || CR->IsPolygonOnSurface(); if (!aHasGeometry) return false; itrc.Next(); } return true; } else if (aType == TopAbs_FACE) { occ::handle TF = occ::down_cast(theShape.TShape()); if (!TF->Surface().IsNull()) { return true; } } else { TopoDS_Iterator anIt(theShape, false, false); for (; anIt.More(); anIt.Next()) { const TopoDS_Shape& aShape = anIt.Value(); bool aHasGeometry = hasGeometry(aShape); if (!aHasGeometry) return false; } return true; } return false; } //======================================================================= // Function : IsManifoldShape // Purpose : Used to define whether the passed shape has manifold // topology or not //======================================================================= static bool IsManifoldShape(const TopoDS_Shape& theShape) { bool aResult = true; // Do not check nested Compounds TopoDS_Compound aDirectShapes; BRep_Builder aBrepBuilder; aBrepBuilder.MakeCompound(aDirectShapes); TopoDS_Iterator anIt(theShape); for (; anIt.More(); anIt.Next()) { const TopoDS_Shape& aDirectChild = anIt.Value(); if (aDirectChild.ShapeType() != TopAbs_COMPOUND) aBrepBuilder.Add(aDirectShapes, aDirectChild); } #ifdef OCCT_DEBUG DumpWhatIs(aDirectShapes); #endif NCollection_IndexedDataMap, TopTools_ShapeMapHasher> aMapEdgeFaces; TopExp::MapShapesAndAncestors(aDirectShapes, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces); int aNbEdges = aMapEdgeFaces.Extent(); #ifdef OCCT_DEBUG std::cout << "Checking whether the topology passed is manifold..." << std::endl; #endif // Check topology for (int i = 1; i <= aNbEdges; i++) { TopoDS_Edge aCurrentEdge = TopoDS::Edge(aMapEdgeFaces.FindKey(i)); if (!BRep_Tool::Degenerated(aCurrentEdge)) { int aNbAncestors = aMapEdgeFaces.FindFromIndex(i).Extent(); if (aNbAncestors > 2) { aResult = false; break; } } } #ifdef OCCT_DEBUG std::cout << "Check result: " << (aResult ? "TRUE" : "FALSE") << std::endl; #endif return aResult; } //================================================================================================= STEPControl_ActorWrite::STEPControl_ActorWrite() : mygroup(0), mytoler(-1.) { SetMode(STEPControl_ShellBasedSurfaceModel); } //======================================================================= // method: getNMSSRForGroup // purpose: allows to get NMSSR (NON_MANIFOLD_SURFACE_SHAPE_REPRESENTATION) // STEP's entity for the group of shells (!) passed //======================================================================= occ::handle STEPControl_ActorWrite:: getNMSSRForGroup(const occ::handle>& shapeGroup, const occ::handle& FP, bool& isNMSSRCreated) const { occ::handle aResult; if (!shapeGroup.IsNull()) { for (int i = 1; i <= shapeGroup->Length(); i++) { TopoDS_Shape aCurrentShape = shapeGroup->Value(i); occ::handle mapper = TransferBRep::ShapeMapper(FP, aCurrentShape); if (FP->FindTypedTransient(mapper, STANDARD_TYPE(StepShape_NonManifoldSurfaceShapeRepresentation), aResult)) break; } } if (aResult.IsNull()) { #ifdef OCCT_DEBUG std::cout << "\nNew NMSSR created" << std::endl; #endif aResult = new StepShape_NonManifoldSurfaceShapeRepresentation; isNMSSRCreated = true; } else { #ifdef OCCT_DEBUG std::cout << "\nExisting NMSSR is used" << std::endl; #endif isNMSSRCreated = false; } return aResult; } //======================================================================= // function : mergeInfoForNM // purpose : bind already written shared faces to STEP entity for non-manifold //======================================================================= void STEPControl_ActorWrite::mergeInfoForNM(const occ::handle& theFP, const occ::handle& theInfo) const { occ::handle aContext = occ::down_cast(theInfo); if (aContext.IsNull()) return; const NCollection_DataMap& aMap = aContext->Map(); NCollection_DataMap::Iterator aShapeShapeIt( aMap); for (; aShapeShapeIt.More(); aShapeShapeIt.Next()) { TopoDS_Shape anOrig = aShapeShapeIt.Key(), aRes = aShapeShapeIt.Value(); if (anOrig.ShapeType() != TopAbs_FACE) continue; occ::handle anOrigMapper = TransferBRep::ShapeMapper(theFP, anOrig); occ::handle anOrigBinder = theFP->Find(anOrigMapper); if (anOrigBinder.IsNull()) continue; occ::handle aResMapper = TransferBRep::ShapeMapper(theFP, aRes); theFP->Bind(aResMapper, anOrigBinder); } } //================================================================================================= bool STEPControl_ActorWrite::separateShapeToSoloVertex( const TopoDS_Shape& theShape, NCollection_Sequence& theVertices) { if (theShape.IsNull()) { return false; } switch (theShape.ShapeType()) { case TopAbs_COMPOUND: { for (TopoDS_Iterator anIter(theShape); anIter.More(); anIter.Next()) { if (!separateShapeToSoloVertex(anIter.Value(), theVertices)) { return false; } } break; } case TopAbs_VERTEX: { theVertices.Append(theShape); break; } default: { theVertices.Clear(); return false; } } return true; } //================================================================================================= void STEPControl_ActorWrite::SetMode(const STEPControl_StepModelType M) { switch (M) { case STEPControl_AsIs: ModeTrans() = 0; break; case STEPControl_ManifoldSolidBrep: ModeTrans() = 3; break; case STEPControl_BrepWithVoids: ModeTrans() = 5; break; case STEPControl_FacetedBrep: ModeTrans() = 1; break; case STEPControl_FacetedBrepAndBrepWithVoids: ModeTrans() = 6; break; case STEPControl_ShellBasedSurfaceModel: ModeTrans() = 2; break; case STEPControl_GeometricCurveSet: ModeTrans() = 4; break; case STEPControl_Hybrid: ModeTrans() = 0; break; // PAS IMPLEMENTE !! default: break; } } //================================================================================================= STEPControl_StepModelType STEPControl_ActorWrite::Mode() const { switch (themodetrans) { case 0: return STEPControl_AsIs; case 1: return STEPControl_FacetedBrep; case 2: return STEPControl_ShellBasedSurfaceModel; case 3: return STEPControl_ManifoldSolidBrep; case 4: return STEPControl_GeometricCurveSet; case 5: return STEPControl_BrepWithVoids; case 6: return STEPControl_FacetedBrepAndBrepWithVoids; default: break; } return STEPControl_AsIs; } //================================================================================================= void STEPControl_ActorWrite::SetGroupMode(const int mode) { if (mode >= 0) mygroup = mode; } //================================================================================================= int STEPControl_ActorWrite::GroupMode() const { return mygroup; } //================================================================================================= void STEPControl_ActorWrite::SetTolerance(const double Tol) { mytoler = Tol; } //======================================================================= // function : Recognize // ATTENTION, Recognize doit s aligner sur ce que Transfer sait faire // purpose : //======================================================================= bool STEPControl_ActorWrite::Recognize(const occ::handle& start) { STEPControl_StepModelType mymode = Mode(); occ::handle mapper = occ::down_cast(start); if (mapper.IsNull()) return false; if (mymode == STEPControl_AsIs) return true; bool yasolid = false, yashell = false, yaface = false; TopoDS_Shape theShape, aShape; // theShape = TopoDSToStep::DirectFaces(mapper->Value()); theShape = mapper->Value(); // pour une reconnaissance c est bien assez if (theShape.ShapeType() == TopAbs_COMPOUND) { TopExp_Explorer SolidExp, ShellExp, FaceExp; for (SolidExp.Init(theShape, TopAbs_SOLID); SolidExp.More(); SolidExp.Next()) yasolid = true; for (ShellExp.Init(theShape, TopAbs_SHELL, TopAbs_SOLID); ShellExp.More(); ShellExp.Next()) yashell = true; for (FaceExp.Init(theShape, TopAbs_FACE, TopAbs_SHELL); FaceExp.More(); FaceExp.Next()) yaface = true; } else if (theShape.ShapeType() == TopAbs_SOLID) yasolid = true; else if (theShape.ShapeType() == TopAbs_SHELL) yashell = true; else if (theShape.ShapeType() == TopAbs_FACE) yaface = true; else if (mymode != STEPControl_GeometricCurveSet) return false; // pour wireframe ? // Faceted : il est OBLIGATOIRE d avoir des surfaces support Plane et des // courbes 3D Line (pcurves ignorees) if (mymode == STEPControl_FacetedBrep || mymode == STEPControl_FacetedBrepAndBrepWithVoids) { for (TopExp_Explorer ffac(theShape, TopAbs_FACE); ffac.More(); ffac.Next()) { const TopoDS_Face& F = TopoDS::Face(ffac.Current()); TopLoc_Location locbid; occ::handle surf = BRep_Tool::Surface(F, locbid); if (surf.IsNull() || !surf->IsKind(STANDARD_TYPE(Geom_Plane))) return false; } for (TopExp_Explorer fedg(theShape, TopAbs_EDGE); fedg.More(); fedg.Next()) { const TopoDS_Edge& E = TopoDS::Edge(fedg.Current()); TopLoc_Location locbid; double first, last; occ::handle curv = BRep_Tool::Curve(E, locbid, first, last); if (curv.IsNull() || !curv->IsKind(STANDARD_TYPE(Geom_Line))) return false; } } switch (mymode) { case STEPControl_ManifoldSolidBrep: return (yasolid || yashell); case STEPControl_BrepWithVoids: case STEPControl_FacetedBrep: case STEPControl_FacetedBrepAndBrepWithVoids: return yasolid; case STEPControl_ShellBasedSurfaceModel: return (yasolid || yashell || yaface); case STEPControl_GeometricCurveSet: return true; // tout OK default: break; } return false; } // ######## MAKE PRODUCT DATA + CONTEXT ######## //================================================================================================= occ::handle STEPControl_ActorWrite::Transfer( const occ::handle& start, const occ::handle& FP, const Message_ProgressRange& theProgress) { occ::handle mapper = occ::down_cast(start); if (mapper.IsNull()) return NullResult(); TopoDS_Shape shape = mapper->Value(); // init context occ::handle model = occ::down_cast(FP->Model()); if (!model.IsNull()) myContext.SetModel(model); //: abv 04.11.00: take APD from model myContext.AddAPD(false); // update APD myContext.SetLevel(1); // set assembly level to 1 (to ensure) if (!model->IsInitializedUnit()) { XSAlgo_ShapeProcessor::PrepareForTransfer(); // update unit info model->SetLocalLengthUnit(UnitsMethods::GetCasCadeLengthUnit()); } double aLFactor = model->WriteLengthUnit(); aLFactor /= model->LocalLengthUnit(); const int anglemode = model->InternalParameters.AngleUnit; StepData_Factors aLocalFactors; aLocalFactors.InitializeFactors(aLFactor, (anglemode <= 1 ? 1. : M_PI / 180.), 1.); // create SDR STEPConstruct_Part SDRTool; SDRTool.MakeSDR(0, myContext.GetProductName(), myContext.GetAPD()->Application(), model); occ::handle sdr = SDRTool.SDRValue(); // transfer shape occ::handle resbind = TransferShape(mapper, sdr, FP, aLocalFactors, 0L, true, theProgress); // occ::handle resultat; // FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat); // sdr->SetUsedRepresentation (resultat); // create binder with all root entities produced from shape occ::handle>> roots = myContext.GetRootsForPart(SDRTool); occ::handle resprod = TransientResult(myContext.GetAPD()); for (int i = 1; i <= roots->Length(); i++) resprod->AddResult(TransientResult(roots->Value(i))); resprod->AddResult(resbind); // bind and exit // FP->Bind (mapper,resprod); myContext.NextIndex(); return resprod; } //========================================== static double UsedTolerance(occ::handle& theStepModel, const double mytoler, const TopoDS_Shape& theShape) { // COMPUTING 3D TOLERANCE // Either from Session, or Computed (Least,Average, or Greatest) // Then given to TopoDSToStep_Tool double Tol = mytoler; int tolmod = theStepModel->InternalParameters.WritePrecisionMode; if (Tol <= 0 && tolmod == 2) Tol = theStepModel->InternalParameters.WritePrecisionVal; if (Tol <= 0) { ShapeAnalysis_ShapeTolerance stu; Tol = stu.Tolerance(theShape, tolmod); // Par defaut, on prend une tolerance moyenne, on elimine les aberrations Tol = Interface_MSG::Intervalled(Tol * 1.5); // arrondi a 1 2 5 ... } if (Tol == 0) Tol = 1.e-07; // minimum ... return Tol; } //================================================================================================= // if GroupMode is >1 downgrades all compounds having single subshape to that // subshape bool STEPControl_ActorWrite::IsAssembly(const occ::handle& theModel, TopoDS_Shape& S) const { if (!GroupMode() || S.ShapeType() != TopAbs_COMPOUND) return false; // PTV 16.09.2002 OCC725 for storing compound of vertices if (theModel->InternalParameters.WriteVertexMode == 0) { // bug 23950 if (S.ShapeType() == TopAbs_COMPOUND) { bool IsOnlyVertices = true; TopoDS_Iterator anItr(S); for (; anItr.More(); anItr.Next()) { if (anItr.Value().ShapeType() != TopAbs_VERTEX) { IsOnlyVertices = false; break; } } if (IsOnlyVertices) return false; } } if (GroupMode() == 1) return true; TopoDS_Iterator it(S); if (!it.More()) return false; TopoDS_Shape shape = it.Value(); it.Next(); if (it.More()) return true; S = shape; return IsAssembly(theModel, S); } // PTV 16.09.2002 added for transferring vertices. static bool transferVertex(const occ::handle& FP, occ::handle>& aGSS, const TopoDS_Shape& aShVrtx, const int theNum, const StepData_Factors& theLocalFactors) { bool IsDone = false; NCollection_DataMap, TopTools_ShapeMapHasher> aMap; occ::handle aStepModel = occ::down_cast(FP->Model()); TopoDSToStep_Tool aTool(aMap, true, aStepModel->InternalParameters.WriteSurfaceCurMode); TopoDSToStep_MakeStepVertex aMkVrtx(TopoDS::Vertex(aShVrtx), aTool, FP, theLocalFactors); if (!aMkVrtx.IsDone()) return IsDone; occ::handle aVP = occ::down_cast(aTool.Find(aShVrtx)); if (aVP.IsNull()) return IsDone; StepShape_GeometricSetSelect select; select.SetValue(aVP->VertexGeometry()); // add current result aGSS->SetValue(theNum, select); IsDone = true; return IsDone; } occ::handle STEPControl_ActorWrite::TransferShape( const occ::handle& start, const occ::handle& SDR0, const occ::handle& FP, const StepData_Factors& theLocalFactors, const occ::handle>& shapeGroup, const bool isManifold, const Message_ProgressRange& theProgress) { STEPControl_StepModelType mymode = Mode(); occ::handle mapper = occ::down_cast(start); occ::handle binder; occ::handle aStepModel = occ::down_cast(FP->Model()); // Indicates whether to use an existing NMSSR to write items to (ss; 13.11.2010) bool useExistingNMSSR = false; if (mapper.IsNull()) return binder; TopoDS_Shape theShape = mapper->Value(); if (theShape.IsNull()) return binder; // INDIVIDUAL SHAPE ALREADY TRANSFERRED : RETURN IT ! binder = FP->Find(start); if (!binder.IsNull()) { if (!binder->HasResult()) binder.Nullify(); } if (!binder.IsNull()) { //: abv 20.05.02: writing box & face from it (shared) in one compound // as assembly - while face already translated, it should be // re-translated to break sharing #ifdef OCCT_DEBUG std::cout << "Warning: STEPControl_ActorWrite::TransferShape(): shape already translated" << std::endl; #endif // return binder; } // MODE ASSEMBLY : if Compound, (sub-)assembly if (IsAssembly(aStepModel, theShape)) return TransferCompound(start, SDR0, FP, theLocalFactors, theProgress); Message_ProgressScope aPSRoot(theProgress, NULL, 2); // [BEGIN] Separate manifold topology from non-manifold in group mode 0 (ssv; 18.11.2010) bool isNMMode = aStepModel->InternalParameters.WriteNonmanifold != 0; occ::handle aNMBinder; if (isNMMode && !GroupMode() && theShape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Compound aNMCompound; TopoDS_Compound aManifoldCompound; BRep_Builder brepBuilder; // Create empty Compounds brepBuilder.MakeCompound(aManifoldCompound); brepBuilder.MakeCompound(aNMCompound); // Indicates whether there is only non-manifold topology detected // (there is no manifold topology found in the Compound passed) bool isOnlyNonManifold = false; // Find a Compound containing non-manifold topology. // NOTE: only one such Compound must exist in the entire Compound passed if (!IsManifoldShape(theShape)) { aNMCompound = TopoDS::Compound(theShape); isOnlyNonManifold = true; } else { NCollection_List aListOfShapes; NCollection_List aListOfManifoldShapes; aListOfShapes.Append(theShape); NCollection_List::Iterator itL(aListOfShapes); for (; itL.More(); itL.Next()) { TopoDS_Shape aParentShape = itL.Value(); TopoDS_Iterator it(aParentShape); for (; it.More(); it.Next()) { TopoDS_Shape aSubShape = it.Value(); if (aSubShape.ShapeType() == TopAbs_COMPOUND && !IsManifoldShape(aSubShape)) aNMCompound = TopoDS::Compound(aSubShape); else if (aSubShape.ShapeType() == TopAbs_COMPOUND) aListOfShapes.Append(aSubShape); else aListOfManifoldShapes.Append(aSubShape); } } // Group manifold topology together. // NOTE: there is no sense that initial Compound structure was lost as // group mode is set to 0 (no Assemblies are mapped) for (itL.Initialize(aListOfManifoldShapes); itL.More(); itL.Next()) { TopoDS_Shape aCurrentManiShape = itL.Value(); brepBuilder.Add(aManifoldCompound, aCurrentManiShape); } } // Process only manifold topology in the current TransferShape invocation. // Invoke TransferShape for non-manifold topology separately (see below) theShape = aManifoldCompound; // List of items to transfer occ::handle> RepItemSeq = new NCollection_HSequence(); // Non-manifold group to pass into TransferShape with each shape from RepItemSeq occ::handle> NonManifoldGroup = new NCollection_HSequence(); // Transfer Solids to closed Shells. Prepare RepItemSeq & NonManifoldGroup for (TopoDS_Iterator iter(aNMCompound); iter.More(); iter.Next()) { const TopoDS_Shape& aSubShape = iter.Value(); if (aSubShape.ShapeType() == TopAbs_SOLID) { for (TopoDS_Iterator aSubIter(aSubShape); aSubIter.More(); aSubIter.Next()) { TopoDS_Shell aSubShell = TopoDS::Shell(aSubIter.Value()); aSubShell.Closed(true); RepItemSeq->Append(aSubShell); NonManifoldGroup->Append(aSubShell); } } else if (!isManifold && (aSubShape.ShapeType() == TopAbs_SHELL)) { RepItemSeq->Append(aSubShape); NonManifoldGroup->Append(aSubShape); } else RepItemSeq->Append(iter.Value()); } int aNMItemsNb = RepItemSeq->Length(); // In case of pure manifold topology do nothing; theShape is processed as usual (see below) if (aNMItemsNb > 0) { // Prepare SDR for non-manifold group. This SDR will be linked to NMSSR by means // of TransferShape invocation. SDR is not created if there is no any manifold // topology in the passed Compound. If topology is pure non-manifold, SDR0 (passed) // is used occ::handle sdr; if (isOnlyNonManifold) sdr = SDR0; else { STEPConstruct_Part SDRTool; SDRTool.MakeSDR(0, myContext.GetProductName(), myContext.GetAPD()->Application(), aStepModel); sdr = SDRTool.SDRValue(); } aNMBinder = TransientResult(sdr); // Complete SDR with shape representations. // NOTE: aNMBinder is connected now with this SDR. It will be added to the resulting // binder in the end of this invocation of TransferShape Message_ProgressScope aPS(aPSRoot.Next(), NULL, aNMItemsNb); for (int i = 1; i <= aNMItemsNb && aPS.More(); i++) { occ::handle aMapper = TransferBRep::ShapeMapper(FP, RepItemSeq->Value(i)); TransferShape(aMapper, sdr, FP, theLocalFactors, NonManifoldGroup, false, aPS.Next()); } // Nothing else needed for pure non-manifold topology, return if (isOnlyNonManifold) return aNMBinder; } } // [END] Separate manifold topology from non-manifold in group mode 0 (ssv; 18.11.2010) if (aPSRoot.UserBreak()) return occ::handle(); // create a list of items to translate occ::handle> RepItemSeq = new NCollection_HSequence(); bool isSeparateVertices = aStepModel->InternalParameters.WriteVertexMode == 0; // bug 23950 // PTV 16.09.2002 OCC725 separate shape from solo vertices. bool isOnlyVertices = false; if (theShape.ShapeType() == TopAbs_COMPOUND && isSeparateVertices) { TopoDS_Compound aNewShape, aCompOfVrtx; BRep_Builder aBuilder; aBuilder.MakeCompound(aNewShape); aBuilder.MakeCompound(aCompOfVrtx); NCollection_Sequence aVertices; isOnlyVertices = separateShapeToSoloVertex(theShape, aVertices); if (!isOnlyVertices) { for (TopoDS_Iterator anCompIt(theShape); anCompIt.More(); anCompIt.Next()) { const TopoDS_Shape& aCurSh = anCompIt.Value(); NCollection_Sequence aVerticesOfSubSh; if (separateShapeToSoloVertex(aCurSh, aVerticesOfSubSh)) { aVertices.Append(aVerticesOfSubSh); } else { aBuilder.Add(aNewShape, aCurSh); } } theShape = aNewShape; } for (NCollection_HSequence::Iterator anIterV(aVertices); anIterV.More(); anIterV.Next()) { aBuilder.Add(aCompOfVrtx, anIterV.Value()); } if (!aVertices.IsEmpty()) { RepItemSeq->Append(aCompOfVrtx); } } if (theShape.ShapeType() == TopAbs_COMPOUND) { TopExp_Explorer SolidExp, ShellExp, FaceExp; if (mymode != STEPControl_GeometricCurveSet) { for (SolidExp.Init(theShape, TopAbs_SOLID); SolidExp.More(); SolidExp.Next()) { RepItemSeq->Append(TopoDS::Solid(SolidExp.Current())); } for (ShellExp.Init(theShape, TopAbs_SHELL, TopAbs_SOLID); ShellExp.More(); ShellExp.Next()) { RepItemSeq->Append(TopoDS::Shell(ShellExp.Current())); } for (FaceExp.Init(theShape, TopAbs_FACE, TopAbs_SHELL); FaceExp.More(); FaceExp.Next()) { RepItemSeq->Append(TopoDS::Face(FaceExp.Current())); } } else { if (!isOnlyVertices) RepItemSeq->Append(theShape); //: j1 } if (mymode == STEPControl_AsIs) { TopExp_Explorer WireExp, EdgeExp; for (WireExp.Init(theShape, TopAbs_WIRE, TopAbs_FACE); WireExp.More(); WireExp.Next()) RepItemSeq->Append(TopoDS::Wire(WireExp.Current())); for (EdgeExp.Init(theShape, TopAbs_EDGE, TopAbs_WIRE); EdgeExp.More(); EdgeExp.Next()) RepItemSeq->Append(TopoDS::Edge(EdgeExp.Current())); } } else if (theShape.ShapeType() == TopAbs_SOLID) { RepItemSeq->Append(TopoDS::Solid(theShape)); } else if (theShape.ShapeType() == TopAbs_SHELL) { RepItemSeq->Append(TopoDS::Shell(theShape)); } else if (theShape.ShapeType() == TopAbs_FACE) { RepItemSeq->Append(TopoDS::Face(theShape)); } else if (theShape.ShapeType() == TopAbs_COMPSOLID) { FP->AddWarning(start, "NonManifold COMPSOLID was translated like a set of SOLIDs"); if (GroupMode() > 0) return TransferCompound(start, SDR0, FP, theLocalFactors, aPSRoot.Next()); else { TopExp_Explorer SolidExp; for (SolidExp.Init(theShape, TopAbs_SOLID); SolidExp.More(); SolidExp.Next()) { RepItemSeq->Append(TopoDS::Solid(SolidExp.Current())); } } } else if (mymode != STEPControl_GeometricCurveSet && mymode != STEPControl_AsIs) { FP->AddFail(start, "The Shape is not a SOLID, nor a SHELL, nor a FACE"); return binder; } else RepItemSeq->Append(theShape); // COMPUTING 3D TOLERANCE // Either from Session, or Computed (Least,Average, or Greatest) // Then given to TopoDSToStep_Tool double Tol = UsedTolerance(aStepModel, mytoler, theShape); // Create a STEP-Entity for each TopoDS_Shape // according to the current StepModelMode int nbs = RepItemSeq->Length(); occ::handle>> ItemSeq = new NCollection_HSequence>(); // ptv 10.11.00: allow to write empty Compound: if (GroupMode() >0) ItemSeq->Append(myContext.GetDefaultAxis()); STEPControl_StepModelType trmode = mymode; Message_ProgressScope aPS(aPSRoot.Next(), NULL, nbs); for (int i = 1; i <= nbs && aPS.More(); i++) { TopoDS_Shape xShape = RepItemSeq->Value(i); if (mymode == STEPControl_AsIs) { switch (xShape.ShapeType()) { case TopAbs_SOLID: trmode = STEPControl_ManifoldSolidBrep; break; case TopAbs_SHELL: trmode = STEPControl_ShellBasedSurfaceModel; break; case TopAbs_FACE: trmode = STEPControl_ShellBasedSurfaceModel; break; default: trmode = STEPControl_GeometricCurveSet; break; } } Message_ProgressScope aPS1(aPS.Next(), NULL, 2); TopoDS_Shape aShape = xShape; XSAlgo_ShapeProcessor::ParameterMap aParameters = GetShapeFixParameters(); XSAlgo_ShapeProcessor::SetParameter("FixShape.Tolerance3d", Tol, true, aParameters); XSAlgo_ShapeProcessor::SetParameter("FixShape.MaxTolerance3d", aStepModel->InternalParameters.ReadMaxPrecisionVal, true, aParameters); XSAlgo_ShapeProcessor aShapeProcessor(aParameters); if (hasGeometry(aShape)) { aShape = aShapeProcessor.ProcessShape(xShape, GetShapeProcessFlags().first, aPS1.Next()); if (aPS1.UserBreak()) { return occ::handle(); } } if (!isManifold) { mergeInfoForNM(FP, aShapeProcessor.GetContext()); } // create a STEP entity corresponding to shape occ::handle item, itemTess; switch (trmode) { case STEPControl_ManifoldSolidBrep: { if (aShape.ShapeType() == TopAbs_SOLID) { TopoDS_Solid aSolid = TopoDS::Solid(aShape); //: d6 abv 13 Mar 98: if solid has more than 1 shell, // try to treat it as solid with voids int nbShells = 0; for (TopoDS_Iterator It(aSolid); It.More(); It.Next()) if (It.Value().ShapeType() == TopAbs_SHELL) nbShells++; if (nbShells > 1) { TopoDSToStep_MakeBrepWithVoids MkBRepWithVoids(aSolid, FP, theLocalFactors, aPS1.Next()); MkBRepWithVoids.Tolerance() = Tol; if (MkBRepWithVoids.IsDone()) { item = MkBRepWithVoids.Value(); itemTess = MkBRepWithVoids.TessellatedValue(); } else nbShells = 1; // smth went wrong; let it will be just Manifold } if (nbShells == 1) { TopoDSToStep_MakeManifoldSolidBrep MkManifoldSolidBrep(aSolid, FP, theLocalFactors, aPS1.Next()); MkManifoldSolidBrep.Tolerance() = Tol; if (MkManifoldSolidBrep.IsDone()) { item = MkManifoldSolidBrep.Value(); itemTess = MkManifoldSolidBrep.TessellatedValue(); } } } else if (aShape.ShapeType() == TopAbs_SHELL) { TopoDS_Shell aShell = TopoDS::Shell(aShape); TopoDSToStep_MakeManifoldSolidBrep MkManifoldSolidBrep(aShell, FP, theLocalFactors, aPS1.Next()); MkManifoldSolidBrep.Tolerance() = Tol; if (MkManifoldSolidBrep.IsDone()) { item = MkManifoldSolidBrep.Value(); itemTess = MkManifoldSolidBrep.TessellatedValue(); } } break; } case STEPControl_BrepWithVoids: { if (aShape.ShapeType() == TopAbs_SOLID) { TopoDS_Solid aSolid = TopoDS::Solid(aShape); TopoDSToStep_MakeBrepWithVoids MkBRepWithVoids(aSolid, FP, theLocalFactors, aPS1.Next()); MkBRepWithVoids.Tolerance() = Tol; if (MkBRepWithVoids.IsDone()) { item = MkBRepWithVoids.Value(); itemTess = MkBRepWithVoids.TessellatedValue(); } } break; } case STEPControl_FacetedBrep: { TopoDSToStep_FacetedError facErr = TopoDSToStep_FacetedTool::CheckTopoDSShape(aShape); if (facErr != TopoDSToStep_FacetedDone) { FP->AddFail(start, "Error in Faceted Shape from TopoDS"); if (facErr == TopoDSToStep_SurfaceNotPlane) { FP->AddFail(start, "-- The TopoDS_Face is not plane"); } else if (facErr == TopoDSToStep_PCurveNotLinear) { FP->AddFail(start, "-- The Face contains non linear PCurves"); } return binder; } if (aShape.ShapeType() == TopAbs_SOLID) { TopoDS_Solid aSolid = TopoDS::Solid(aShape); TopoDSToStep_MakeFacetedBrep MkFacetedBrep(aSolid, FP, theLocalFactors, aPS1.Next()); MkFacetedBrep.Tolerance() = Tol; if (MkFacetedBrep.IsDone()) { item = MkFacetedBrep.Value(); itemTess = MkFacetedBrep.TessellatedValue(); } } break; } case STEPControl_FacetedBrepAndBrepWithVoids: { TopoDSToStep_FacetedError facErr = TopoDSToStep_FacetedTool::CheckTopoDSShape(aShape); if (facErr != TopoDSToStep_FacetedDone) { FP->AddFail(start, "Error in Faceted Shape from TopoDS"); if (facErr == TopoDSToStep_SurfaceNotPlane) { FP->AddFail(start, "-- The TopoDS_Face is not plane"); } else if (facErr == TopoDSToStep_PCurveNotLinear) { FP->AddFail(start, "-- The Face contains non linear PCurves"); } return binder; } if (aShape.ShapeType() == TopAbs_SOLID) { TopoDS_Solid aSolid = TopoDS::Solid(aShape); TopoDSToStep_MakeFacetedBrepAndBrepWithVoids MkFacetedBrepAndBrepWithVoids( aSolid, FP, theLocalFactors, aPS1.Next()); MkFacetedBrepAndBrepWithVoids.Tolerance() = Tol; if (MkFacetedBrepAndBrepWithVoids.IsDone()) { item = MkFacetedBrepAndBrepWithVoids.Value(); itemTess = MkFacetedBrepAndBrepWithVoids.TessellatedValue(); } } break; } case STEPControl_ShellBasedSurfaceModel: { if (aShape.ShapeType() == TopAbs_SOLID) { TopoDS_Solid aSolid = TopoDS::Solid(aShape); TopoDSToStep_MakeShellBasedSurfaceModel MkShellBasedSurfaceModel(aSolid, FP, theLocalFactors, aPS1.Next()); MkShellBasedSurfaceModel.Tolerance() = Tol; if (MkShellBasedSurfaceModel.IsDone()) { item = MkShellBasedSurfaceModel.Value(); itemTess = MkShellBasedSurfaceModel.TessellatedValue(); } } else if (aShape.ShapeType() == TopAbs_SHELL) { TopoDS_Shell aShell = TopoDS::Shell(aShape); // Non-manifold topology is stored via NMSSR containing series of SBSM (ssv; 13.11.2010) TopoDSToStep_MakeShellBasedSurfaceModel MkShellBasedSurfaceModel(aShell, FP, theLocalFactors, aPS1.Next()); MkShellBasedSurfaceModel.Tolerance() = Tol; if (MkShellBasedSurfaceModel.IsDone()) { item = MkShellBasedSurfaceModel.Value(); itemTess = MkShellBasedSurfaceModel.TessellatedValue(); } } else if (aShape.ShapeType() == TopAbs_FACE) { TopoDS_Face aFace = TopoDS::Face(aShape); TopoDSToStep_MakeShellBasedSurfaceModel MkShellBasedSurfaceModel(aFace, FP, theLocalFactors, aPS1.Next()); MkShellBasedSurfaceModel.Tolerance() = Tol; if (MkShellBasedSurfaceModel.IsDone()) { item = MkShellBasedSurfaceModel.Value(); itemTess = MkShellBasedSurfaceModel.TessellatedValue(); } } break; } case STEPControl_GeometricCurveSet: { TopoDSToStep_MakeGeometricCurveSet MkGeometricCurveSet(aShape, FP, theLocalFactors); MkGeometricCurveSet.Tolerance() = Tol; if (MkGeometricCurveSet.IsDone()) { item = MkGeometricCurveSet.Value(); } // PTV 22.08.2002 OCC609 ------------------------- begin -------------------- // modified by PTV 16.09.2002 OCC725 else if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_VERTEX) { // it is compound with solo vertices. int aNbVrtx = 0; int curNb = 0; TopExp_Explorer anExp(aShape, TopAbs_VERTEX); for (; anExp.More(); anExp.Next()) { if (anExp.Current().ShapeType() != TopAbs_VERTEX) continue; aNbVrtx++; } if (aNbVrtx) { // create new geometric curve set for all vertices occ::handle> aGSS = new NCollection_HArray1(1, aNbVrtx); occ::handle empty = new TCollection_HAsciiString(""); occ::handle aGCSet = new StepShape_GeometricCurveSet; aGCSet->SetName(empty); // iterates on compound with vertices and traces each vertex for (anExp.ReInit(); anExp.More(); anExp.Next()) { const TopoDS_Shape& aVertex = anExp.Current(); if (aVertex.ShapeType() != TopAbs_VERTEX) continue; curNb++; transferVertex(FP, aGSS, aVertex, curNb, theLocalFactors); } // end of iteration on compound with vertices. aGCSet->SetElements(aGSS); item = aGCSet; } // end of check that number of vertices is not null } // PTV 22.08.2002 OCC609------------------------- end -------------------- break; } default: break; } if (item.IsNull() && itemTess.IsNull()) continue; // add resulting item to the FP if (!item.IsNull()) { ItemSeq->Append(item); occ::handle submapper; if (xShape.IsSame(mapper->Value())) submapper = occ::down_cast(start); if (submapper.IsNull()) submapper = TransferBRep::ShapeMapper(FP, xShape); occ::handle subbind = FP->Find(submapper); if (subbind.IsNull()) { subbind = TransientResult(item); FP->Bind(submapper, subbind); } else subbind->AddResult(TransientResult(item)); } if (!itemTess.IsNull()) { ItemSeq->Append(itemTess); occ::handle submapper; if (xShape.IsSame(mapper->Value())) submapper = occ::down_cast(start); if (submapper.IsNull()) submapper = TransferBRep::ShapeMapper(FP, xShape); occ::handle subbind = FP->Find(submapper); if (subbind.IsNull()) { subbind = TransientResult(itemTess); FP->Bind(submapper, subbind); } else subbind->AddResult(TransientResult(itemTess)); } // If shape is not processed, this function does nothing. Intentionally. aShapeProcessor.MergeTransferInfo(FP); } // - Make Shape Representation int nCc1 = ItemSeq->Length(); if (nCc1 < 1) { FP->AddFail(start, "The Shape has not the appropriate type"); return binder; } occ::handle shapeRep; if (theShape.ShapeType() == TopAbs_SHAPE) { // for external references shapeRep = new StepShape_ShapeRepresentation; } else { switch (mymode) { case STEPControl_ManifoldSolidBrep: shapeRep = new StepShape_AdvancedBrepShapeRepresentation; break; case STEPControl_FacetedBrep: shapeRep = new StepShape_FacetedBrepShapeRepresentation; break; // NOTE: STEPControl_AsIs mode is normally used to transfer non-manifold topology. // However, as ShellBasedSurfaceModel is used in non-manifold processing // internally, STEPControl_ShellBasedSurfaceModel is also adjusted to // be able to work with non-manifold cases case STEPControl_ShellBasedSurfaceModel: if (isManifold) shapeRep = new StepShape_ManifoldSurfaceShapeRepresentation; else { bool isNewNMSSRCreated; shapeRep = this->getNMSSRForGroup(shapeGroup, FP, isNewNMSSRCreated); useExistingNMSSR = !isNewNMSSRCreated; } break; case STEPControl_GeometricCurveSet: shapeRep = new StepShape_GeometricallyBoundedWireframeShapeRepresentation; break; case STEPControl_AsIs: { if (nbs == 1) { if (trmode == STEPControl_ManifoldSolidBrep) shapeRep = new StepShape_AdvancedBrepShapeRepresentation; else if (trmode == STEPControl_ShellBasedSurfaceModel) // Process non-manifold topology separately (ssv; 13.11.2010) if (isManifold) shapeRep = new StepShape_ManifoldSurfaceShapeRepresentation; else { bool isNewNMSSRCreated; shapeRep = this->getNMSSRForGroup(shapeGroup, FP, isNewNMSSRCreated); useExistingNMSSR = !isNewNMSSRCreated; } else if (trmode == STEPControl_GeometricCurveSet) shapeRep = new StepShape_GeometricallyBoundedWireframeShapeRepresentation; else if (trmode == STEPControl_FacetedBrep) shapeRep = new StepShape_FacetedBrepShapeRepresentation; } else shapeRep = new StepShape_ShapeRepresentation; } break; default: break; } } if (shapeRep.IsNull()) { occ::handle resb; return resb; } occ::handle>> items = new NCollection_HArray1>(1, nCc1); for (int rep = 1; rep <= nCc1; rep++) { occ::handle repit = GetCasted(StepRepr_RepresentationItem, ItemSeq->Value(rep)); items->SetValue(rep, repit); } int ap = aStepModel->InternalParameters.WriteSchema; NCollection_Sequence> aSeqBindRelation; if (ap == 3 && nbs > 1) { int j = 1; if (items->Value(j)->IsKind(STANDARD_TYPE(StepGeom_Axis2Placement3d))) { occ::handle>> axis = new NCollection_HArray1>(1, 1); axis->SetValue(1, items->Value(j++)); shapeRep->SetItems(axis); } for (; j <= items->Length(); j++) { occ::handle ShapeRepr1; if (items->Value(j)->IsKind(STANDARD_TYPE(StepShape_ManifoldSolidBrep))) ShapeRepr1 = new StepShape_AdvancedBrepShapeRepresentation; else if (items->Value(j)->IsKind(STANDARD_TYPE(StepShape_ShellBasedSurfaceModel))) ShapeRepr1 = new StepShape_ManifoldSurfaceShapeRepresentation; else if (items->Value(j)->IsKind(STANDARD_TYPE(StepShape_GeometricCurveSet))) ShapeRepr1 = new StepShape_GeometricallyBoundedWireframeShapeRepresentation; else if (items->Value(j)->IsKind(STANDARD_TYPE(StepShape_FacetedBrep))) ShapeRepr1 = new StepShape_FacetedBrepShapeRepresentation; else if (items->Value(j)->IsKind(STANDARD_TYPE(StepVisual_TessellatedItem))) ShapeRepr1 = new StepVisual_TessellatedShapeRepresentation; else ShapeRepr1 = new StepShape_ShapeRepresentation; occ::handle>> repr1 = new NCollection_HArray1>(1, 2); repr1->SetValue(1, myContext.GetDefaultAxis()); repr1->SetValue(2, items->Value(j)); ShapeRepr1->SetItems(repr1); STEPConstruct_UnitContext mk1; mk1.Init(Tol, aStepModel, theLocalFactors); ShapeRepr1->SetContextOfItems(mk1.Value()); // la tolerance, voir au debut ShapeRepr1->SetName(new TCollection_HAsciiString("")); occ::handle aShapeRel = new StepRepr_ShapeRepresentationRelationship; occ::handle aName = new TCollection_HAsciiString(""); occ::handle aDescr = new TCollection_HAsciiString(""); aShapeRel->SetName(aName); aShapeRel->SetDescription(aDescr); aShapeRel->SetRep2(shapeRep); aShapeRel->SetRep1(ShapeRepr1); aSeqBindRelation.Append(TransientResult(aShapeRel)); } } else { int nC = 0; for (int i = 1; i <= items->Length(); i++) { if (!items->Value(i)->IsKind(STANDARD_TYPE(StepVisual_TessellatedItem))) continue; ++nC; } if (nC > 0) { occ::handle>> itemsTess = new NCollection_HArray1>(1, nC); int i = 1; for (int j = 1; j <= items->Length(); j++) { if (!items->Value(j)->IsKind(STANDARD_TYPE(StepVisual_TessellatedItem))) continue; itemsTess->SetValue(i++, items->Value(j)); } occ::handle shapeTessRepr = new StepVisual_TessellatedShapeRepresentation; shapeTessRepr->SetItems(itemsTess); STEPConstruct_UnitContext mk1; mk1.Init(Tol, aStepModel, theLocalFactors); shapeTessRepr->SetContextOfItems(mk1.Value()); shapeTessRepr->SetName(new TCollection_HAsciiString("")); aSeqBindRelation.Append(TransientResult(shapeTessRepr)); } if (!useExistingNMSSR) shapeRep->SetItems(items); else { // Add new representation item to the NMSSR's existing collection (ssv; 13.11.2010) occ::handle>> oldItems = shapeRep->Items(); occ::handle>> newItems = new NCollection_HArray1>(1, oldItems->Length() + 1); int el = 1; for (int i = 1; i <= oldItems->Length(); i++) newItems->SetValue(el++, oldItems->Value(i)); newItems->SetValue(el, items->Value(items->Length())); shapeRep->SetItems(newItems); } } // init representation STEPConstruct_UnitContext mk; mk.Init(Tol, aStepModel, theLocalFactors); shapeRep->SetContextOfItems(mk.Value()); // la tolerance, voir au debut shapeRep->SetName(new TCollection_HAsciiString("")); // Create SDR (only once for non-manifold group) if (!useExistingNMSSR) { SDR0->SetUsedRepresentation(shapeRep); // create binder for SR and attach to it binder for RepItem (if exists) occ::handle resbind = TransientResult(shapeRep); binder = FP->Find(start); if (!binder.IsNull()) { resbind->AddResult(binder); FP->Rebind(start, resbind); // binder->AddResult ( resbind ); // resbind = binder; } for (int k = 1; k <= aSeqBindRelation.Length(); k++) resbind->AddResult(aSeqBindRelation.Value(k)); // Add SDR for non-manifold topology in group mode 0 (ssv; 18.11.2010) if (!aNMBinder.IsNull()) resbind->AddResult(aNMBinder); return resbind; } else return FP->Find(start); } //======================================================================= // function : TransferCompound // #### TRANSFER COMPOUND AS (SUB-)ASSEMBLY // purpose : //======================================================================= occ::handle STEPControl_ActorWrite::TransferCompound( const occ::handle& start, const occ::handle& SDR0, const occ::handle& FP, const StepData_Factors& theLocalFactors, const Message_ProgressRange& theProgress) { occ::handle mapper = occ::down_cast(start); occ::handle binder; if (mapper.IsNull()) return binder; TopoDS_Shape theShape = mapper->Value(); occ::handle aStepModel = occ::down_cast(FP->Model()); // Inspect non-manifold topology case (ssv; 10.11.2010) bool isNMMode = aStepModel->InternalParameters.WriteNonmanifold != 0; bool isManifold; if (isNMMode) isManifold = IsManifoldShape(theShape); else isManifold = true; // get a sequence of components (subshapes) occ::handle> RepItemSeq = new NCollection_HSequence(); // Prepare a collection for non-manifold group of shapes occ::handle> NonManifoldGroup = new NCollection_HSequence(); bool isSeparateVertices = (aStepModel->InternalParameters.WriteVertexMode == 0); // bug 23950 // PTV OCC725 17.09.2002 -- begin -- int nbFreeVrtx = 0; TopoDS_Compound aCompOfVrtx; BRep_Builder aB; aB.MakeCompound(aCompOfVrtx); #ifdef OCCT_DEBUG if (!isManifold) std::cout << "Exploding Solids to Shells if any..." << std::endl; #endif for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) { const TopoDS_Shape& aSubShape = iter.Value(); if (aSubShape.ShapeType() != TopAbs_VERTEX || !isSeparateVertices) { // Store non-manifold topology as shells (ssv; 10.11.2010) if (!isManifold && aSubShape.ShapeType() == TopAbs_SOLID) { for (TopoDS_Iterator aSubIter(aSubShape); aSubIter.More(); aSubIter.Next()) { TopoDS_Shell aSubShell = TopoDS::Shell(aSubIter.Value()); aSubShell.Closed(true); RepItemSeq->Append(aSubShell); NonManifoldGroup->Append(aSubShell); } } else if (!isManifold && (aSubShape.ShapeType() == TopAbs_SHELL || aSubShape.ShapeType() == TopAbs_FACE)) { RepItemSeq->Append(aSubShape); NonManifoldGroup->Append(aSubShape); } else RepItemSeq->Append(aSubShape); continue; } aB.Add(aCompOfVrtx, iter.Value()); nbFreeVrtx++; } if (nbFreeVrtx) RepItemSeq->Append(aCompOfVrtx); // PTV OCC725 17.09.2002 -- end -- // Constitution : liste d axes, le premier est l origine, les suivants : 1 // par sous-item occ::handle shapeRep = occ::down_cast(SDR0->UsedRepresentation()); if (shapeRep.IsNull()) { shapeRep = new StepShape_ShapeRepresentation; SDR0->SetUsedRepresentation(shapeRep); // to be used by MakeItem } // clang-format off binder = TransientResult(SDR0); // set SDR as first item in order to be found first (but not SDR of subshape!) // clang-format on binder->AddResult(TransientResult(shapeRep)); // translate components int i, nbs = RepItemSeq->Length(); occ::handle>> ItemSeq = new NCollection_HSequence>(); ItemSeq->Append(myContext.GetDefaultAxis()); myContext.NextLevel(); Message_ProgressScope aPS(theProgress, NULL, nbs); for (i = 1; i <= nbs && aPS.More(); i++) { occ::handle subs = TransferBRep::ShapeMapper(FP, RepItemSeq->Value(i)); occ::handle AX1; occ::handle bnd = TransferSubShape(subs, SDR0, AX1, FP, theLocalFactors, NonManifoldGroup, isManifold, aPS.Next()); if (!AX1.IsNull()) ItemSeq->Append(AX1); // copy binders so as to have all roots in upper binder, but do not conflict while (!bnd.IsNull()) { occ::handle bx = occ::down_cast(bnd); if (!bx.IsNull()) { binder->AddResult(TransientResult(bx->Result())); } bnd = bnd->NextResult(); } } myContext.PrevLevel(); int nsub = ItemSeq->Length(); occ::handle>> items = new NCollection_HArray1>(1, nsub); // initialize representation for (int rep = 1; rep <= nsub; rep++) items->SetValue(rep, GetCasted(StepRepr_RepresentationItem, ItemSeq->Value(rep))); shapeRep->SetItems(items); double Tol = UsedTolerance(aStepModel, mytoler, theShape); STEPConstruct_UnitContext mk; mk.Init(Tol, aStepModel, theLocalFactors); shapeRep->SetContextOfItems(mk.Value()); // la tolerance, voir au debut shapeRep->SetName(new TCollection_HAsciiString("")); // set it to SDR // SDR0->SetUsedRepresentation (shapeRep); return binder; } //================================================================================================= occ::handle STEPControl_ActorWrite::TransferSubShape( const occ::handle& start, const occ::handle& SDR0, occ::handle& AX1, const occ::handle& FP, const StepData_Factors& theLocalFactors, const occ::handle>& shapeGroup, const bool isManifold, const Message_ProgressRange& theProgress) { occ::handle mapper = occ::down_cast(start); if (mapper.IsNull()) return NullResult(); TopoDS_Shape shape = mapper->Value(); // SHAPE EN POSITION VENANT D UN ASSEMBLAGE // Il faut alors distinguer la transformation de la shape meme // laquelle est consideree a l origine, puis transferee // A part, un item decrivant une occurence en position est cree // SINON, la shape est prise et transferee telle quelle TopoDS_Shape sh0 = shape; gp_Trsf aLoc; bool isShapeLocated = false; if (GroupMode() > 0) { const TopLoc_Location& shloc = shape.Location(); isShapeLocated = !shloc.IsIdentity(); aLoc = shloc.Transformation(); TopLoc_Location shident; sh0.Location(shident); mapper = TransferBRep::ShapeMapper(FP, sh0); mapper->SameAttributes(start); } occ::handle resbind = FP->Find(mapper); occ::handle sdr; // occ::handle resultat; STEPConstruct_Part SDRTool; occ::handle aStepModel = occ::down_cast(FP->Model()); // Already SDR and SR available : take them as are bool iasdr = FP->GetTypedTransient(resbind, STANDARD_TYPE(StepShape_ShapeDefinitionRepresentation), sdr); if (iasdr) SDRTool.ReadSDR(sdr); else { SDRTool.MakeSDR(0, myContext.GetProductName(), myContext.GetAPD()->Application(), aStepModel); sdr = SDRTool.SDRValue(); } // resultat = GetCasted(StepShape_ShapeRepresentation,sdr->UsedRepresentation()); // if shape itself not yet translated, do it now //: abv 20.05.02: see comment in TransferShape(): added "! iasdr ||" occ::handle resprod = TransientResult(sdr); // KA - OCC7141(skl 10.11.2004) bool isJustTransferred = false; if (!iasdr || resbind.IsNull()) { occ::handle resbind1 = TransferShape(mapper, sdr, FP, theLocalFactors, shapeGroup, isManifold, theProgress); if (resbind1.IsNull() || sdr->UsedRepresentation().IsNull()) return occ::handle(); resbind = resbind1; occ::handle oldbind = FP->Find(mapper); if (!oldbind.IsNull() && !resbind.IsNull()) resbind->AddResult(oldbind); isJustTransferred = true; } // A new resbind may have been produced // DeclareAndCast(Transfer_SimpleBinderOfTransient,restrans,resbind); // if (restrans.IsNull()) return resbind; // FP->GetTypedTransient (resbind,STANDARD_TYPE(StepShape_ShapeRepresentation),resultat); // sdr->SetUsedRepresentation(resultat); // to be used by MakeItem // create assembly structures (CDSR, NAUO etc.) STEPConstruct_Assembly mkitem; // make location for assembly placement if (std::abs(aLoc.ScaleFactor() - 1.0) > Precision::Confusion()) { if (aStepModel->InternalParameters.WriteScalingTrsf) FP->AddWarning( start, "The shape has a scaling factor, exported as cartesian_transformation_operator"); else FP->AddWarning(start, "The shape has a scaling factor, skipped"); } if (std::abs(aLoc.ScaleFactor() - 1.0) < Precision::Confusion() || !aStepModel->InternalParameters.WriteScalingTrsf) { // create a new axis2placement3d GeomToStep_MakeAxis2Placement3d mkax(aLoc, theLocalFactors); mkitem.Init(sdr, SDR0, myContext.GetDefaultAxis(), mkax.Value()); AX1 = mkax.Value(); } else { // create a new cartesian transformation GeomToStep_MakeCartesianTransformationOperator aMaker(aLoc, theLocalFactors); if (!aMaker.IsDone()) { FP->AddFail(start, "The transformation relation creation failed"); } mkitem.Init(sdr, SDR0, aMaker.Value()); AX1 = aMaker.Value(); } mkitem.MakeRelationship(); occ::handle>> roots = myContext.GetRootsForAssemblyLink(mkitem); // add roots corresponding to assembly and product structures to binder // occ::handle resprod = resbind; //KA - OCC7141(skl 10.11.2004) // KA: we need only the current subshape in resprod, since the binder is copied // in Transfershape which calls Transfersubshape [ OCC7141(skl 10.11.2004) ] if (!iasdr) { resprod->AddResult(TransientResult(sdr)); if (resprod != resbind) resbind->AddResult(TransientResult(sdr)); // KA - OCC7141(skl 10.11.2004) roots->Append(myContext.GetRootsForPart(SDRTool)); } for (int i = 1; i <= roots->Length(); i++) { resprod->AddResult(TransientResult(roots->Value(i))); if (resprod != resbind) resbind->AddResult(TransientResult(roots->Value(i))); // KA - OCC7141(skl 10.11.2004) } if (isJustTransferred) { // We make CDSR of the current shape preceding CDSR of any subshapes, // therefore add resbind at the end. resprod->AddResult(resbind); FP->Bind(mapper, resprod); } myContext.NextIndex(); // abv 16.10.00: bind CDSR (et al) to located shape in order to be able to track instances if (mapper != start && isShapeLocated) { occ::handle bnd = FP->Find(start); for (int j = 1; j <= roots->Length(); j++) if (bnd.IsNull()) bnd = TransientResult(roots->Value(j)); else bnd->AddResult(TransientResult(roots->Value(j))); FP->Bind(start, bnd); } return resprod; }