diff --git a/src/RWStepShape/RWStepShape_RWEdgeCurve.cxx b/src/RWStepShape/RWStepShape_RWEdgeCurve.cxx index d6c8f9fd04..d5614afd03 100644 --- a/src/RWStepShape/RWStepShape_RWEdgeCurve.cxx +++ b/src/RWStepShape/RWStepShape_RWEdgeCurve.cxx @@ -11,11 +11,11 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +#include #include #include #include -#include #include #include #include @@ -27,271 +27,228 @@ #include #include -RWStepShape_RWEdgeCurve::RWStepShape_RWEdgeCurve () {} - -void RWStepShape_RWEdgeCurve::ReadStep - (const Handle(StepData_StepReaderData)& data, - const Standard_Integer num, - Handle(Interface_Check)& ach, - const Handle(StepShape_EdgeCurve)& ent) const +namespace { + // ================================================================ + // Function : GetSharing + // Purpose : Returns a step entity of a type StepShapeType that is + // sharing theStepEntity. If no sharing entity of + // required type is found, returns nullptr. + // ================================================================ + template + Handle (StepShapeType) GetSharing (const Handle (Standard_Transient)& theStepEntity, + const Interface_ShareTool& theShareTool) + { + Interface_EntityIterator aSharedEntitiesIt = theShareTool.Sharings (theStepEntity); + aSharedEntitiesIt.SelectType (STANDARD_TYPE (StepShapeType), Standard_True); + return aSharedEntitiesIt.NbEntities() == 0 + ? Handle (StepShapeType){} + : Handle (StepShapeType)::DownCast (aSharedEntitiesIt.Value()); + } + // ================================================================ + // Function : GetFaceBoundOrientation + // Purpose : Returns an orientation of face bound sharing + // theOrientedEdge. If face bound cannot be found, + // returns true (to preserve pre-refactoring behavior). + // ================================================================ + Standard_Boolean GetFaceBoundOrientation (const Handle (StepShape_OrientedEdge)& theOrientedEdge, + const Interface_ShareTool& theShareTool) + { + if (!theShareTool.IsShared (theOrientedEdge)) + { + return Standard_True; + } - // --- Number of Parameter Control --- - - if (!data->CheckNbParams(num,5,ach,"edge_curve")) return; - - // --- inherited field : name --- - - Handle(TCollection_HAsciiString) aName; - data->ReadString (num,1,"name",ach,aName); - - // --- inherited field : edgeStart --- - - Handle(StepShape_Vertex) aEdgeStart; - data->ReadEntity(num, 2,"edge_start", ach, STANDARD_TYPE(StepShape_Vertex), aEdgeStart); - - // --- inherited field : edgeEnd --- - - Handle(StepShape_Vertex) aEdgeEnd; - data->ReadEntity(num, 3,"edge_end", ach, STANDARD_TYPE(StepShape_Vertex), aEdgeEnd); - - // --- own field : edgeGeometry --- - - Handle(StepGeom_Curve) aEdgeGeometry; - data->ReadEntity(num, 4,"edge_geometry", ach, STANDARD_TYPE(StepGeom_Curve), aEdgeGeometry); - - // --- own field : sameSense --- + const Handle (StepShape_EdgeLoop) anEdgeLoop = GetSharing (theOrientedEdge, + theShareTool); + if (!theShareTool.IsShared (anEdgeLoop)) + { + return Standard_True; + } - Standard_Boolean aSameSense; - data->ReadBoolean (num,5,"same_sense",ach,aSameSense); + const Handle (StepShape_FaceBound) aFaceBound = GetSharing (anEdgeLoop, + theShareTool); + return aFaceBound.IsNull() ? Standard_True : aFaceBound->Orientation(); + } - //--- Initialisation of the read entity --- + // ================================================================ + // Function : GetFaceBoundOrientation + // Purpose : Returns true if start and end points of theEdgeCurve + // are valid points of the different vertices and are + // equal to each other within Precision::Confusion(). + // ================================================================ + Standard_Boolean AreEndsMatch (const Handle (StepShape_EdgeCurve)& theEdgeCurve) + { + Handle (StepShape_VertexPoint) aStartVertex = Handle (StepShape_VertexPoint)::DownCast ( + theEdgeCurve->EdgeStart()); + Handle (StepShape_VertexPoint) anEndVertex = Handle (StepShape_VertexPoint)::DownCast ( + theEdgeCurve->EdgeEnd()); + if (aStartVertex == anEndVertex) + { + return Standard_False; + } + Handle (StepGeom_CartesianPoint) aStartPoint = Handle (StepGeom_CartesianPoint)::DownCast ( + aStartVertex->VertexGeometry()); + Handle (StepGeom_CartesianPoint) anEndPoint = Handle (StepGeom_CartesianPoint)::DownCast ( + anEndVertex->VertexGeometry()); + if (aStartPoint.IsNull() || anEndPoint.IsNull()) + { + return Standard_False; + } - ent->Init(aName, aEdgeStart, aEdgeEnd, aEdgeGeometry, aSameSense); + const Standard_Real aDistance = Sqrt ( + (aStartPoint->CoordinatesValue (1) - anEndPoint->CoordinatesValue (1)) + * (aStartPoint->CoordinatesValue (1) - anEndPoint->CoordinatesValue (1)) + + (aStartPoint->CoordinatesValue (2) - anEndPoint->CoordinatesValue (2)) + * (aStartPoint->CoordinatesValue (2) - anEndPoint->CoordinatesValue (2)) + + (aStartPoint->CoordinatesValue (3) - anEndPoint->CoordinatesValue (3)) + * (aStartPoint->CoordinatesValue (3) - anEndPoint->CoordinatesValue (3))); + return aDistance < Precision::Confusion(); + } } - -void RWStepShape_RWEdgeCurve::WriteStep - (StepData_StepWriter& SW, - const Handle(StepShape_EdgeCurve)& ent) const +// ================================================================ +// Function : ReadStep +// Purpose : +// ================================================================ +void RWStepShape_RWEdgeCurve::ReadStep (const Handle (StepData_StepReaderData)& theStepData, + const Standard_Integer theRecordID, + Handle (Interface_Check)& theMessageTool, + const Handle (StepShape_EdgeCurve)& theEdgeCurve) const { + // --- Number of Parameter Control --- + if (!theStepData->CheckNbParams (theRecordID, 5, theMessageTool, "edge_curve")) + { + return; + } - // --- inherited field name --- - - SW.Send(ent->Name()); - - // --- inherited field edgeStart --- - - SW.Send(ent->EdgeStart()); - - // --- inherited field edgeEnd --- + // --- inherited field : name --- + Handle (TCollection_HAsciiString) aName; + theStepData->ReadString (theRecordID, 1, "name", theMessageTool, aName); + + // --- inherited field : edgeStart --- + Handle (StepShape_Vertex) anEdgeStart; + theStepData->ReadEntity (theRecordID, + 2, + "edge_start", + theMessageTool, + STANDARD_TYPE (StepShape_Vertex), + anEdgeStart); + + // --- inherited field : edgeEnd --- + Handle (StepShape_Vertex) anEdgeEnd; + theStepData->ReadEntity (theRecordID, + 3, + "edge_end", + theMessageTool, + STANDARD_TYPE (StepShape_Vertex), + anEdgeEnd); + + // --- own field : edgeGeometry --- + Handle (StepGeom_Curve) anEdgeGeometry; + theStepData->ReadEntity (theRecordID, + 4, + "edge_geometry", + theMessageTool, + STANDARD_TYPE (StepGeom_Curve), + anEdgeGeometry); + + // --- own field : sameSense --- + Standard_Boolean aSameSense; + theStepData->ReadBoolean (theRecordID, 5, "same_sense", theMessageTool, aSameSense); + + //--- Initialisation of the read entity --- + theEdgeCurve->Init (aName, anEdgeStart, anEdgeEnd, anEdgeGeometry, aSameSense); +} - SW.Send(ent->EdgeEnd()); +// ================================================================ +// Function : WriteStep +// Purpose : +// ================================================================ +void RWStepShape_RWEdgeCurve::WriteStep (StepData_StepWriter& theStepWriter, + const Handle (StepShape_EdgeCurve)& theEdgeCurve) const +{ + // --- inherited field name --- + theStepWriter.Send (theEdgeCurve->Name()); - // --- own field : edgeGeometry --- + // --- inherited field edgeStart --- + theStepWriter.Send (theEdgeCurve->EdgeStart()); - SW.Send(ent->EdgeGeometry()); + // --- inherited field edgeEnd --- + theStepWriter.Send (theEdgeCurve->EdgeEnd()); - // --- own field : sameSense --- + // --- own field : edgeGeometry --- + theStepWriter.Send (theEdgeCurve->EdgeGeometry()); - SW.SendBoolean(ent->SameSense()); + // --- own field : sameSense --- + theStepWriter.SendBoolean (theEdgeCurve->SameSense()); } - -void RWStepShape_RWEdgeCurve::Share(const Handle(StepShape_EdgeCurve)& ent, Interface_EntityIterator& iter) const +// ================================================================ +// Function : Share +// Purpose : +// ================================================================ +void RWStepShape_RWEdgeCurve::Share (const Handle (StepShape_EdgeCurve)& theEdgeCurve, + Interface_EntityIterator& theSharedEntitiesIt) const { + theSharedEntitiesIt.GetOneItem (theEdgeCurve->EdgeStart()); - iter.GetOneItem(ent->EdgeStart()); - + theSharedEntitiesIt.GetOneItem (theEdgeCurve->EdgeEnd()); - iter.GetOneItem(ent->EdgeEnd()); - - - iter.GetOneItem(ent->EdgeGeometry()); + theSharedEntitiesIt.GetOneItem (theEdgeCurve->EdgeGeometry()); } - - -void RWStepShape_RWEdgeCurve::Check - (const Handle(StepShape_EdgeCurve)& ent, - const Interface_ShareTool& aShto, - Handle(Interface_Check)& ach) const +// ================================================================ +// Function : Check +// Purpose : +// ================================================================ +void RWStepShape_RWEdgeCurve::Check (const Handle (StepShape_EdgeCurve)& theEdgeCurve, + const Interface_ShareTool& theShareTool, + Handle (Interface_Check)& theMessageTool) const { -// std::cout << "------ calling CheckEdgeCurve ------" << std::endl; - - Handle(StepShape_OrientedEdge) theOE1, theOE2; - Handle(StepShape_FaceBound) theFOB1, theFOB2; - //Handle(StepShape_FaceSurface) theFS1, theFS2; - - Standard_Boolean theOEOri1 = Standard_True; - Standard_Boolean theOEOri2 = Standard_True; - Standard_Boolean theFBOri1 = Standard_True; - Standard_Boolean theFBOri2 = Standard_True; - //Standard_Boolean theFSOri1 = Standard_True; - //Standard_Boolean theFSOri2 = Standard_True; - Standard_Boolean Cumulated1, Cumulated2; - // 1- First Vertex != LastVertex but First VertexPoint == Last VertexPoint - // Remark : time consuming process but useful ! - // If this append, we can drop one of the two vertices and replace it - // everywhere it is referenced. Side effect : tolerance problem !!! - - Handle(StepShape_VertexPoint) StartVertex = - Handle(StepShape_VertexPoint)::DownCast(ent->EdgeStart()); - Handle(StepShape_VertexPoint) EndVertex = - Handle(StepShape_VertexPoint)::DownCast(ent->EdgeEnd()); - - if (StartVertex != EndVertex) { - - Handle(StepGeom_CartesianPoint) StartPoint = - Handle(StepGeom_CartesianPoint)::DownCast(StartVertex->VertexGeometry()); - Handle(StepGeom_CartesianPoint) EndPoint = - Handle(StepGeom_CartesianPoint)::DownCast(EndVertex->VertexGeometry()); - - // it can also be a degenerated pcurve + // Remark: time consuming process but useful. + // If this append, we can drop one of the two vertices and replace it + // everywhere it is referenced. Side effect: tolerance problem. + if (AreEndsMatch (theEdgeCurve)) + { + theMessageTool->AddWarning ( + "Two instances of Vertex have equal (within uncertainty) coordinates"); + } - if (!StartPoint.IsNull() && !EndPoint.IsNull()) { - Standard_Real Dist = Sqrt - ((StartPoint->CoordinatesValue(1) - EndPoint->CoordinatesValue(1)) * - (StartPoint->CoordinatesValue(1) - EndPoint->CoordinatesValue(1)) + - (StartPoint->CoordinatesValue(2) - EndPoint->CoordinatesValue(2)) * - (StartPoint->CoordinatesValue(2) - EndPoint->CoordinatesValue(2)) + - (StartPoint->CoordinatesValue(3) - EndPoint->CoordinatesValue(3)) * - (StartPoint->CoordinatesValue(3) - EndPoint->CoordinatesValue(3))); - if (Dist < Precision::Confusion() ) { - ach->AddWarning("Two instances of Vertex have equal (within uncertainty) coordinates"); - } - } + if (!theShareTool.IsShared (theEdgeCurve)) + { + theMessageTool->AddFail ("ERROR: EdgeCurve not referenced"); + return; } - - // 2- Two-Manifold Topology - Standard_Boolean sharEC = aShto.IsShared(ent); - Standard_Integer nbRef; - if(!sharEC){ - ach->AddFail("ERROR: EdgeCurve not referenced"); + // 2- Two-Manifold Topology + Interface_EntityIterator aSharedEntitiesIt = theShareTool.Sharings (theEdgeCurve); + aSharedEntitiesIt.SelectType (STANDARD_TYPE (StepShape_OrientedEdge), Standard_True); + if (aSharedEntitiesIt.NbEntities() != 2) + { + return; } - else { - Interface_EntityIterator myShRef = aShto.Sharings(ent); - myShRef.SelectType (STANDARD_TYPE(StepShape_OrientedEdge),Standard_True); - nbRef = myShRef.NbEntities(); - if (nbRef ==2) { - theOE1 = Handle(StepShape_OrientedEdge)::DownCast(myShRef.Value()); - theOEOri1 = theOE1->Orientation(); - myShRef.Next(); - theOE2 = Handle(StepShape_OrientedEdge)::DownCast(myShRef.Value()); - theOEOri2 = theOE2->Orientation(); - - // get the FaceBound orientation for theOE1 - - Standard_Boolean sharOE1 = aShto.IsShared(theOE1); - if(!sharOE1){ -#ifdef OCCT_DEBUG - std::cout << "OrientedEdge1 not shared" <Orientation(); - } - else { -#ifdef OCCT_DEBUG - std::cout << "EdgeLoop not referenced by FaceBound" << std::endl; -#endif - } - } - } - else { - if (nbRef == 0) { -#ifdef OCCT_DEBUG - std::cout << "OrientedEdge not referenced" << std::endl; -#endif - } - else { - if (aShto.NbTypedSharings(theOE1, - STANDARD_TYPE(StepShape_EdgeLoop)) > 1) { -#ifdef OCCT_DEBUG - std::cout << "OrientedEdge referenced more than once" << std::endl; -#endif - } - } - } - } - // get the FaceBound orientation for theOE2 + const Handle (StepShape_OrientedEdge) anOrientedEdge1 = + Handle (StepShape_OrientedEdge)::DownCast (aSharedEntitiesIt.Value()); + const Standard_Boolean aFaceBoundOrientation1 = GetFaceBoundOrientation (anOrientedEdge1, + theShareTool); + const Standard_Boolean anIsCumulated1 = aFaceBoundOrientation1 != anOrientedEdge1->Orientation(); - Standard_Boolean sharOE2 = aShto.IsShared(theOE2); - if(!sharOE2){ -#ifdef OCCT_DEBUG - std::cout << "OrientedEdge2 not shared" <Orientation(); - } - else { -#ifdef OCCT_DEBUG - std::cout << "EdgeLoop not referenced by FaceBound" << std::endl; -#endif - } - } - } - - // "cumulate" the FaceBound and the OrientedEdge orientation - - Cumulated1 = theFBOri1 ^ theOEOri1; - Cumulated2 = theFBOri2 ^ theOEOri2; - - // the orientation of the OrientedEdges must be opposite - - if (Cumulated1 == Cumulated2) { - ach->AddFail("ERROR: non 2-manifold topology"); - } - } + aSharedEntitiesIt.Next(); + + const Handle (StepShape_OrientedEdge) anOrientedEdge2 = + Handle (StepShape_OrientedEdge)::DownCast (aSharedEntitiesIt.Value()); + const Standard_Boolean aFaceBoundOrientation2 = GetFaceBoundOrientation (anOrientedEdge2, + theShareTool); + const Standard_Boolean anIsCumulated2 = aFaceBoundOrientation2 != anOrientedEdge2->Orientation(); + + // the orientation of the OrientedEdges must be opposite + if (anIsCumulated1 == anIsCumulated2) + { + theMessageTool->AddFail ("ERROR: non 2-manifold topology"); } } - diff --git a/src/RWStepShape/RWStepShape_RWEdgeCurve.hxx b/src/RWStepShape/RWStepShape_RWEdgeCurve.hxx index 69e767325f..6cd8e32430 100644 --- a/src/RWStepShape/RWStepShape_RWEdgeCurve.hxx +++ b/src/RWStepShape/RWStepShape_RWEdgeCurve.hxx @@ -20,8 +20,8 @@ #include #include #include - #include + class StepData_StepReaderData; class Interface_Check; class StepShape_EdgeCurve; @@ -29,47 +29,30 @@ class StepData_StepWriter; class Interface_EntityIterator; class Interface_ShareTool; - //! Read & Write Module for EdgeCurve //! Check added by CKY , 7-OCT-1996 -class RWStepShape_RWEdgeCurve +class RWStepShape_RWEdgeCurve { public: - DEFINE_STANDARD_ALLOC - - Standard_EXPORT RWStepShape_RWEdgeCurve(); - - Standard_EXPORT void ReadStep (const Handle(StepData_StepReaderData)& data, const Standard_Integer num, Handle(Interface_Check)& ach, const Handle(StepShape_EdgeCurve)& ent) const; - - Standard_EXPORT void WriteStep (StepData_StepWriter& SW, const Handle(StepShape_EdgeCurve)& ent) const; - - Standard_EXPORT void Share (const Handle(StepShape_EdgeCurve)& ent, Interface_EntityIterator& iter) const; - - Standard_EXPORT void Check (const Handle(StepShape_EdgeCurve)& ent, const Interface_ShareTool& shares, Handle(Interface_Check)& ach) const; - - - - -protected: - - - - - -private: - +public: + RWStepShape_RWEdgeCurve() = default; + Standard_EXPORT void ReadStep (const Handle (StepData_StepReaderData)& theStepData, + const Standard_Integer theRecordID, + Handle (Interface_Check)& theMessageTool, + const Handle (StepShape_EdgeCurve)& theEdgeCurve) const; + Standard_EXPORT void WriteStep (StepData_StepWriter& theStepWriter, + const Handle (StepShape_EdgeCurve)& theEdgeCurve) const; + Standard_EXPORT void Share (const Handle (StepShape_EdgeCurve)& theEdgeCurve, + Interface_EntityIterator& theSharedEntitiesIt) const; + Standard_EXPORT void Check (const Handle (StepShape_EdgeCurve)& theEdgeCurve, + const Interface_ShareTool& theShareTool, + Handle (Interface_Check)& theMessageTool) const; }; - - - - - - #endif // _RWStepShape_RWEdgeCurve_HeaderFile diff --git a/src/StepToTopoDS/StepToTopoDS_TranslateFace.cxx b/src/StepToTopoDS/StepToTopoDS_TranslateFace.cxx index c33ac4a3bd..1141cc3ce1 100644 --- a/src/StepToTopoDS/StepToTopoDS_TranslateFace.cxx +++ b/src/StepToTopoDS/StepToTopoDS_TranslateFace.cxx @@ -433,264 +433,283 @@ StepToTopoDS_TranslateFace::StepToTopoDS_TranslateFace(const Handle(StepVisual_T // ============================================================================ static inline Standard_Boolean isReversed(const Handle(StepGeom_Surface)& theStepSurf) { - Handle(StepGeom_ToroidalSurface) aStepTorSur; if(theStepSurf->IsKind(STANDARD_TYPE(StepGeom_RectangularTrimmedSurface))) + { return isReversed(Handle(StepGeom_RectangularTrimmedSurface)::DownCast(theStepSurf)->BasisSurface()); - + } else - aStepTorSur = Handle(StepGeom_ToroidalSurface)::DownCast(theStepSurf); - - return (!aStepTorSur.IsNull() && aStepTorSur->MajorRadius() < 0 ? Standard_True : Standard_False); + { + Handle(StepGeom_ToroidalSurface) aStepTorSur = + Handle(StepGeom_ToroidalSurface)::DownCast(theStepSurf); + return !aStepTorSur.IsNull() && aStepTorSur->MajorRadius() < 0.; + } } // ============================================================================ // Method : Init // Purpose : Init with a FaceSurface and a Tool // ============================================================================ -void StepToTopoDS_TranslateFace::Init(const Handle(StepShape_FaceSurface)& FS, - StepToTopoDS_Tool& aTool, - StepToTopoDS_NMTool& NMTool, - const StepData_Factors& theLocalFactors) +void StepToTopoDS_TranslateFace::Init (const Handle (StepShape_FaceSurface)& theFaceSurface, + StepToTopoDS_Tool& theTopoDSTool, + StepToTopoDS_NMTool& theTopoDSToolNM, + const StepData_Factors& theLocalFactors) { done = Standard_True; - if (aTool.IsBound(FS)) { - myResult = TopoDS::Face(aTool.Find(FS)); - myError = StepToTopoDS_TranslateFaceDone; - done = Standard_True; + if (theTopoDSTool.IsBound (theFaceSurface)) + { + myResult = TopoDS::Face (theTopoDSTool.Find (theFaceSurface)); + myError = StepToTopoDS_TranslateFaceDone; + done = Standard_True; return; } - - Handle(Transfer_TransientProcess) TP = aTool.TransientProcess(); - + + // Within a context of this method this object is used for message handling only. + Handle (Transfer_TransientProcess) aMessageHandler = theTopoDSTool.TransientProcess(); + // ---------------------------------------------- // Map the Face Geometry and create a TopoDS_Face // ---------------------------------------------- - Handle(StepGeom_Surface) StepSurf = FS->FaceGeometry(); - - // sln 01.10.2001 BUC61003. If corresponding entity was read with error StepSurface may be NULL. In this case we exit from function - if ( StepSurf.IsNull() ) { - TP->AddFail(StepSurf," Surface has not been created"); + Handle (StepGeom_Surface) aStepGeomSurface = theFaceSurface->FaceGeometry(); + // sln 01.10.2001 BUC61003. If corresponding entity was read with error StepSurface may be NULL. + // In this case we exit from function + if (aStepGeomSurface.IsNull()) + { + aMessageHandler->AddFail (aStepGeomSurface, " Surface has not been created"); myError = StepToTopoDS_TranslateFaceOther; - done = Standard_False; + done = Standard_False; return; } // [BEGIN] Added to process non-manifold topology (ssv; 14.11.2010) - if ( NMTool.IsActive() && NMTool.IsBound(StepSurf) ) { - TopoDS_Shape existingShape = NMTool.Find(StepSurf); + if (theTopoDSToolNM.IsActive() && theTopoDSToolNM.IsBound (aStepGeomSurface)) + { + TopoDS_Shape anExistingShape = theTopoDSToolNM.Find (aStepGeomSurface); // Reverse shape's orientation for the next shell - existingShape.Reverse(); - myResult = existingShape; + anExistingShape.Reverse(); + myResult = anExistingShape; myError = StepToTopoDS_TranslateFaceDone; - done = Standard_True; + done = Standard_True; return; } // [END] Added to process non-manifold topology (ssv; 14.11.2010) - if (StepSurf->IsKind(STANDARD_TYPE(StepGeom_OffsetSurface))) //:d4 abv 12 Mar 98 - TP->AddWarning(StepSurf," Type OffsetSurface is out of scope of AP 214"); - Handle(Geom_Surface) GeomSurf = StepToGeom::MakeSurface (StepSurf, theLocalFactors); - if (GeomSurf.IsNull()) + if (aStepGeomSurface->IsKind (STANDARD_TYPE (StepGeom_OffsetSurface))) //: d4 abv 12 Mar 98 + { + aMessageHandler->AddWarning (aStepGeomSurface, " Type OffsetSurface is out of scope of AP 214"); + } + + Handle (Geom_Surface) aGeomSurface = StepToGeom::MakeSurface (aStepGeomSurface, theLocalFactors); + if (aGeomSurface.IsNull()) { - TP->AddFail(StepSurf," Surface has not been created"); + aMessageHandler->AddFail (aStepGeomSurface, " Surface has not been created"); myError = StepToTopoDS_TranslateFaceOther; - done = Standard_False; + done = Standard_False; return; } + // pdn to force bsplsurf to be periodic - Handle(StepGeom_BSplineSurface) sgbss = Handle(StepGeom_BSplineSurface)::DownCast(StepSurf); - if (!sgbss.IsNull()) { - Handle(Geom_Surface) periodicSurf = ShapeAlgo::AlgoContainer()->ConvertToPeriodic(GeomSurf); - if (!periodicSurf.IsNull()) { - TP->AddWarning(StepSurf, "Surface forced to be periodic"); - GeomSurf = periodicSurf; + if (!Handle (StepGeom_BSplineSurface)::DownCast (aStepGeomSurface).IsNull()) + { + Handle (Geom_Surface) periodicSurf = ShapeAlgo::AlgoContainer()->ConvertToPeriodic ( + aGeomSurface); + if (!periodicSurf.IsNull()) + { + aMessageHandler->AddWarning (aStepGeomSurface, "Surface forced to be periodic"); + aGeomSurface = periodicSurf; } } - - Standard_Boolean sameSenseFace = FS->SameSense(); - //fix for bug 0026376 Solid Works wrote face based on toroidal surface having negative major radius - //seems that such case is interpreted by "Solid Works" and "ProE" as face having reversed orientation. - Standard_Boolean sameSense = (isReversed(StepSurf) ? !sameSenseFace : sameSenseFace); - + // fix for bug 0026376 Solid Works wrote face based on toroidal surface having negative major radius + // seems that such case is interpreted by "Solid Works" and "ProE" as face having reversed orientation. + const Standard_Boolean aSameSense = isReversed (aStepGeomSurface) ? !theFaceSurface->SameSense() + : theFaceSurface->SameSense(); + // -- Statistics -- - aTool.AddContinuity (GeomSurf); - - TopoDS_Face F; - BRep_Builder B; - B.MakeFace ( F, GeomSurf, Precision::Confusion() ); - + theTopoDSTool.AddContinuity (aGeomSurface); + + TopoDS_Face aResultFace; + BRep_Builder aFaceBuilder; + aFaceBuilder.MakeFace (aResultFace, aGeomSurface, Precision::Confusion()); + // ---------------------------------- // Iterate on each FaceBounds (Wires) // ---------------------------------- - Handle(StepShape_FaceBound) FaceBound; - Handle(StepShape_Loop) Loop; - - StepToTopoDS_TranslateVertexLoop myTranVL; - StepToTopoDS_TranslatePolyLoop myTranPL; - StepToTopoDS_TranslateEdgeLoop myTranEdgeLoop; - - Standard_Integer NbBnd = FS->NbBounds(); - - // -- Critere de couture simple (CKY, JAN97) - // surface periodique (typiquement un cylindre) - // 2 face bounds, chacun avec un edge loop d une seule edge - // cette edge est fermee, c-a-d vtx-deb = vtx-fin (pour les deux edges) - // est-ce suffisant (verifier que ce sont deux outer-bounds ... ?? comment ?) - // Alors on peut dire : face a deux bords dont la couture manque - // La couture est entre les deux vertex - - for (Standard_Integer i = 1; i <= NbBnd; i ++) { - -#ifdef OCCT_DEBUG - std::cout << " Processing Wire : " << i << std::endl; -#endif - FaceBound = FS->BoundsValue(i); - Loop = FaceBound->Bound(); - if (Loop.IsNull()) + // - Simple sewing criterion (CKY, Jan97) + // Periodic surface (typically a cylinder) + // 2 face bounds, each with an edge loop from a single edge. + // This edge is closed, c-a-d vertex-begin = vertex-end (for the two edges) + // Is it sufficient (check that these are two outer-bounds... ?? How?) + // Then we can say: face with two edges whose seam is missing + // The seam is between the two vertex + for (Standard_Integer aBoundIndex = 1; aBoundIndex <= theFaceSurface->NbBounds(); ++aBoundIndex) + { + Handle (StepShape_FaceBound) aFaceBound = theFaceSurface->BoundsValue (aBoundIndex); + if (aFaceBound.IsNull()) { continue; } + Handle (StepShape_Loop) aFaceLoop = aFaceBound->Bound(); + if (aFaceLoop.IsNull()) + { + continue; + } + // ------------------------ // The Loop is a VertexLoop // ------------------------ - - if (Loop->IsKind(STANDARD_TYPE(StepShape_VertexLoop))) { -//:S4136 STF.Closed() = Standard_False; -// PROBLEME si SPHERE ou TORE -// Il faudra faire un wire complet, a condition que le point porte sur la face -// En attendant, on ne fait rien - Handle(StepShape_VertexLoop) VL = Handle(StepShape_VertexLoop)::DownCast(Loop); + if (aFaceLoop->IsKind (STANDARD_TYPE (StepShape_VertexLoop))) + { + //: S4136 STF.Closed() = Standard_False; + // PROBLEM if SPHERE or TORE + // It will be necessary to make a complete wire, provided that the point carries on the face + // In the meantime, we do nothing // abv 10.07.00 pr1sy.stp: vertex_loop can be wrong; so just make natural bounds - if (GeomSurf->IsKind (STANDARD_TYPE(Geom_SphericalSurface)) || - GeomSurf->IsKind (STANDARD_TYPE(Geom_BSplineSurface)) || - GeomSurf->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) + if ((aGeomSurface->IsKind (STANDARD_TYPE (Geom_SphericalSurface)) + || aGeomSurface->IsKind (STANDARD_TYPE (Geom_BSplineSurface)) + || aGeomSurface->IsKind (STANDARD_TYPE (Geom_SurfaceOfRevolution))) + && (theFaceSurface->NbBounds() == 1)) { - - // Modification to create natural bounds for face based on the spherical and Bspline surface and having only one bound represented by Vertex loop was made. - // According to the specification of ISO - 10303 part 42: - // "If the face has only one bound and this is of type vertex_loop, then the interior of the face is the domain of the face_surface.face_geometry. - // In such a case the underlying surface shall be closed (e.g. a spherical_surface.)" - // - natural bounds are applied only in case if VertexLoop is only the one defined face bound. - if (NbBnd == 1) + // Modification to create natural bounds for face based on the spherical and Bspline + // surface and having only one bound represented by Vertex loop was made. + // According to the specification of ISO - 10303 part 42: + // "If the face has only one bound and this is of type vertex_loop, then the interior of + // the face is the domain of the face_surface.face_geometry. In such a case the underlying + // surface shall be closed (e.g. a spherical_surface.)" + // - natural bounds are applied only in case if VertexLoop is only the one defined face bound. + BRepBuilderAPI_MakeFace anAuxiliaryFaceBuilder (aGeomSurface, Precision()); + for (TopoDS_Iterator aFaceIt (anAuxiliaryFaceBuilder); aFaceIt.More(); aFaceIt.Next()) { - BRepBuilderAPI_MakeFace mf(GeomSurf, Precision()); - for (TopoDS_Iterator it(mf); it.More(); it.Next()) - { - B.Add(F, it.Value()); - } - continue; + aFaceBuilder.Add (aResultFace, aFaceIt.Value()); } + continue; } - if (GeomSurf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) { - continue; - } - if (GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane))) { - TP->AddWarning(VL, "VertexLoop on plane is ignored"); - continue; //smh : BUC60809 - } - myTranVL.SetPrecision(Precision());//gka - myTranVL.SetMaxTol(MaxTol()); - myTranVL.Init(VL, aTool, NMTool, theLocalFactors); - if (myTranVL.IsDone()) { - B.Add(F, myTranVL.Value()); - } - else { - TP->AddWarning(VL, " a VertexLoop not mapped to TopoDS"); + if (aGeomSurface->IsKind (STANDARD_TYPE (Geom_ToroidalSurface))) + { + continue; + } + + Handle (StepShape_VertexLoop) aVertexLoop = Handle (StepShape_VertexLoop)::DownCast ( + aFaceLoop); + if (aGeomSurface->IsKind (STANDARD_TYPE (Geom_Plane))) + { + aMessageHandler->AddWarning (aVertexLoop, "VertexLoop on plane is ignored"); + continue; // smh : BUC60809 + } + + StepToTopoDS_TranslateVertexLoop aVertexLoopTranslator; + aVertexLoopTranslator.SetPrecision (Precision()); // gka + aVertexLoopTranslator.SetMaxTol (MaxTol()); + aVertexLoopTranslator.Init (aVertexLoop, theTopoDSTool, theTopoDSToolNM, theLocalFactors); + if (aVertexLoopTranslator.IsDone()) + { + aFaceBuilder.Add (aResultFace, aVertexLoopTranslator.Value()); + } + else + { + aMessageHandler->AddWarning (aVertexLoop, " a VertexLoop not mapped to TopoDS"); + } } - } - - // ---------------------- - // The Loop is a PolyLoop - // ---------------------- - else if (Loop->IsKind(STANDARD_TYPE(StepShape_PolyLoop))) { -//:S4136 STF.Closed() = Standard_False; - Handle(StepShape_PolyLoop) PL = Handle(StepShape_PolyLoop)::DownCast(Loop); - F.Orientation ( FS->SameSense() ? TopAbs_FORWARD : TopAbs_REVERSED); - myTranPL.SetPrecision(Precision()); //gka - myTranPL.SetMaxTol(MaxTol()); - myTranPL.Init(PL, aTool, GeomSurf, F, theLocalFactors); - if (myTranPL.IsDone()) { - TopoDS_Wire W = TopoDS::Wire(myTranPL.Value()); - W.Orientation(FaceBound->Orientation() ? TopAbs_FORWARD : TopAbs_REVERSED); - B.Add(F, W); + // ---------------------- + // The Loop is a PolyLoop + // ---------------------- + else if (aFaceLoop->IsKind (STANDARD_TYPE (StepShape_PolyLoop))) + { + Handle (StepShape_PolyLoop) aPolyLoop = Handle (StepShape_PolyLoop)::DownCast (aFaceLoop); + aResultFace.Orientation (theFaceSurface->SameSense() ? TopAbs_FORWARD : TopAbs_REVERSED); + StepToTopoDS_TranslatePolyLoop aPolyLoopTranslator; + aPolyLoopTranslator.SetPrecision (Precision()); // gka + aPolyLoopTranslator.SetMaxTol (MaxTol()); + aPolyLoopTranslator.Init (aPolyLoop, + theTopoDSTool, + aGeomSurface, + aResultFace, + theLocalFactors); + if (aPolyLoopTranslator.IsDone()) + { + TopoDS_Wire aPolyLoopWire = TopoDS::Wire (aPolyLoopTranslator.Value()); + aPolyLoopWire.Orientation (aFaceBound->Orientation() ? TopAbs_FORWARD : TopAbs_REVERSED); + aFaceBuilder.Add (aResultFace, aPolyLoopWire); } - else { - TP->AddWarning(PL, " a PolyLoop not mapped to TopoDS"); + else + { + aMessageHandler->AddWarning (aPolyLoop, " a PolyLoop not mapped to TopoDS"); } } - // ----------------------- // The Loop is an EdgeLoop // ----------------------- - else if (Loop->IsKind(STANDARD_TYPE(StepShape_EdgeLoop))) { - //:S4136 if (STF.Closed()) { - //:S4136 Handle(StepShape_EdgeLoop) EL = - //:S4136 Handle(StepShape_EdgeLoop)::DownCast(FaceBound->Bound()); - //:S4136 if (EL->NbEdgeList() != 1) STF.Closed() = Standard_False; - //:S4136 } - - TopoDS_Wire W; - myTranEdgeLoop.SetPrecision(Precision()); //gka - myTranEdgeLoop.SetMaxTol(MaxTol()); - myTranEdgeLoop.Init(FaceBound, F, GeomSurf, StepSurf, sameSense, aTool, NMTool, theLocalFactors); - - if (myTranEdgeLoop.IsDone()) { - W = TopoDS::Wire(myTranEdgeLoop.Value()); - - // STEP Face_Surface orientation : - // if the topological orientation is opposite to the geometric - // orientation of the surface => the underlying topological - // orientation are not implicitly reversed - // this is the case in CAS.CADE => If the face_surface is reversed, - // the wire orientation has to be explicitly reversed - if (FaceBound->Orientation()) { - // *DTH* if (sameSense || GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane))) - W.Orientation(sameSense ? TopAbs_FORWARD : TopAbs_REVERSED); - } - else { - // *DTH* if (sameSense || GeomSurf->IsKind(STANDARD_TYPE(Geom_Plane))) - W.Orientation(sameSense ? TopAbs_REVERSED : TopAbs_FORWARD); + else if (aFaceLoop->IsKind (STANDARD_TYPE (StepShape_EdgeLoop))) + { + StepToTopoDS_TranslateEdgeLoop anEdgeLoopTranslator; + anEdgeLoopTranslator.SetPrecision (Precision()); // gka + anEdgeLoopTranslator.SetMaxTol (MaxTol()); + anEdgeLoopTranslator.Init (aFaceBound, + aResultFace, + aGeomSurface, + aStepGeomSurface, + aSameSense, + theTopoDSTool, + theTopoDSToolNM, + theLocalFactors); + + if (anEdgeLoopTranslator.IsDone()) + { + TopoDS_Wire anEdgeLoopWire = TopoDS::Wire (anEdgeLoopTranslator.Value()); + + // STEP Face_Surface orientation : + // if the topological orientation is opposite to the geometric + // orientation of the surface => the underlying topological + // orientation are not implicitly reversed + // this is the case in CAS.CADE => If the face_surface is reversed, + // the wire orientation has to be explicitly reversed + if (aFaceBound->Orientation()) + { + anEdgeLoopWire.Orientation (aSameSense ? TopAbs_FORWARD : TopAbs_REVERSED); + } + else + { + anEdgeLoopWire.Orientation (aSameSense ? TopAbs_REVERSED : TopAbs_FORWARD); + } + // ----------------------------- + // The Wire is added to the Face + // ----------------------------- + aFaceBuilder.Add (aResultFace, anEdgeLoopWire); } - // ----------------------------- - // The Wire is added to the Face - // ----------------------------- - B.Add(F, W); - } - else { - // Il y a eu un probleme dans le mapping : On perd la Face - // (facon de parler ...) Pas de moyen aujourd hui de recuperer - // au moins toutes les geometries (Points, Courbes 3D, Surface) - TP->AddFail(Loop, " EdgeLoop not mapped to TopoDS"); - - // CKY JAN-97 : un Wire manque, eh bien on continue quand meme !! - // sauf si OuterBound : la c est quand meme pas bien normal ... - if (FaceBound->IsKind(STANDARD_TYPE(StepShape_FaceOuterBound))) { - TP->AddWarning(FS, "No Outer Bound : Face not done"); + else + { + // There was a problem in the mapping: We lost Face (so to speak...). + // No way today to recover at least all the geometries (Points, 3D Curves, Surface). + aMessageHandler->AddFail (aFaceLoop, " EdgeLoop not mapped to TopoDS"); + + // CKY JAN-97: a Wire is missing, well we continue anyway + // unless OuterBound: that's still not quite normal... + if (aFaceBound->IsKind (STANDARD_TYPE (StepShape_FaceOuterBound))) + { + aMessageHandler->AddWarning (theFaceSurface, "No Outer Bound : Face not done"); + } + continue; } - continue; } - } - else { + else + { // Type not yet implemented or non sens - TP->AddFail(Loop," Type of loop not yet implemented"); -#ifdef OCCT_DEBUG - std::cout << Loop->DynamicType() << std::endl; -#endif + aMessageHandler->AddFail (aFaceLoop, " Type of loop not yet implemented"); continue; } } - F.Orientation ( FS->SameSense() ? TopAbs_FORWARD : TopAbs_REVERSED); - aTool.Bind(FS,F); + aResultFace.Orientation (theFaceSurface->SameSense() ? TopAbs_FORWARD : TopAbs_REVERSED); + theTopoDSTool.Bind (theFaceSurface, aResultFace); // Register face in NM tool (ssv; 14.11.2010) - if ( NMTool.IsActive() ) - NMTool.Bind(StepSurf, F); + if (theTopoDSToolNM.IsActive()) + { + theTopoDSToolNM.Bind (aStepGeomSurface, aResultFace); + } - myResult = F; + myResult = aResultFace; myError = StepToTopoDS_TranslateFaceDone; done = Standard_True; } diff --git a/src/StepToTopoDS/StepToTopoDS_TranslateFace.hxx b/src/StepToTopoDS/StepToTopoDS_TranslateFace.hxx index c58b56745d..af78de0c45 100644 --- a/src/StepToTopoDS/StepToTopoDS_TranslateFace.hxx +++ b/src/StepToTopoDS/StepToTopoDS_TranslateFace.hxx @@ -60,9 +60,9 @@ public: StepToTopoDS_NMTool& theNMTool, const StepData_Factors& theLocalFactors = StepData_Factors()); - Standard_EXPORT void Init (const Handle(StepShape_FaceSurface)& FS, - StepToTopoDS_Tool& T, - StepToTopoDS_NMTool& NMTool, + Standard_EXPORT void Init (const Handle(StepShape_FaceSurface)& theFaceSurface, + StepToTopoDS_Tool& theTopoDSTool, + StepToTopoDS_NMTool& theTopoDSToolNM, const StepData_Factors& theLocalFactors = StepData_Factors()); Standard_EXPORT void Init (const Handle(StepVisual_TessellatedFace)& theTF, diff --git a/tests/bugs/step/bug33665 b/tests/bugs/step/bug33665 new file mode 100644 index 0000000000..b1b20e724d --- /dev/null +++ b/tests/bugs/step/bug33665 @@ -0,0 +1,12 @@ +puts "# =====================================================================" +puts "# 0033665: Data Exchange, Step Import - TransferRoots crashes for" +puts "# invalid STEP files." +puts "# =====================================================================" + +# Step entity #18 is intentionally removed from test file, +# but it is still referenced by other step entities. +# Parsing and root transfer should not cause crash for such invalid file. + +set aFilePath [locate_data_file bug33665.step] +testreadstep "$aFilePath" aShape +checkshape aShape