1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0024249: Crash on ShapeFix_Shape

MAIN CHANGES:
FixAddNaturalBound: the boundaries of "natural bound addition" are restricted: a face, that does not contains an outer wire, should not have any infinite UV boundaries due to new face building (with using a surface) requires specified UV boundaries.
FixAddNaturalBound: myResult is updated in FixAddNaturalBound when the method creates a new face with natural boundary. myResult is required to be updated for next "fix small-area wires" algorithm
IsPeriodicConicalLoop: incorrect working BRepTools_WireExplorer was replaced on TopoDS_Iterator.
a natural bound is added to all the faces are constructed with UV-periodical surfaces (not only sphere and torus; e.g., closed b-splines)

other:
ShapeAnalysis: ReverceSeq renamed to ReverseSeq
BRep_Tool Pnt and Tolerance has the check for null TShape
Test cases for issue CR24249

required null checks were added
test cases were corrected according to their new behavior
Correction test case for issue CR24249
This commit is contained in:
ibs
2014-04-17 16:16:36 +04:00
committed by apn
parent e28d7e62f9
commit 46aed280cc
41 changed files with 204 additions and 111 deletions

View File

@@ -55,7 +55,6 @@
#include <BRep_Builder.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <BRepTools.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
@@ -109,6 +108,22 @@
#define DEBUG
#endif
static Standard_Boolean IsSurfaceUVInfinite(const Handle(Geom_Surface)& theSurf)
{
Standard_Real UMin,UMax,VMin,VMax;
theSurf->Bounds(UMin,UMax,VMin,VMax);
return (Precision::IsInfinite(UMin) ||
Precision::IsInfinite(UMax) ||
Precision::IsInfinite(VMin) ||
Precision::IsInfinite(VMax) );
}
static Standard_Boolean IsSurfaceUVPeriodic(const Handle(Geom_Surface)& theSurf)
{
return theSurf->IsUPeriodic() && theSurf->IsVPeriodic();
}
//=======================================================================
//function : ShapeFix_Face
//purpose :
@@ -419,7 +434,7 @@ Standard_Boolean ShapeFix_Face::Perform()
theAdvFixWire->SetPrecision(newpreci);
}
}
isfixReorder = Standard_False;
for ( TopoDS_Iterator iter(S,Standard_False); iter.More(); iter.Next()) {
if(iter.Value().ShapeType() != TopAbs_WIRE) {
@@ -497,7 +512,7 @@ Standard_Boolean ShapeFix_Face::Perform()
}
// cycle by all possible faces coming from FixMissingSeam
// each face is processed as if it was single
// each face is processed as if it was single
TopExp_Explorer exp(myResult,TopAbs_FACE);
for ( ; exp.More(); exp.Next() ) {
myFace = TopoDS::Face ( exp.Current() );
@@ -660,7 +675,7 @@ Standard_Boolean ShapeFix_Face::Perform()
//return the original preci
SetPrecision(aSavPreci);
theAdvFixWire->SetPrecision(aSavPreci);
theAdvFixWire->SetPrecision(aSavPreci);
// cycle by all possible faces coming from FixAddNaturalBound
// each face is processed as if it was single
@@ -807,11 +822,19 @@ Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
vs.Append(wi.Value());
}
// deal with case of empty face: just create a new one by standard tool
if ( ws.Length() <=0 ) {
BRepBuilderAPI_MakeFace mf (mySurf->Surface(), Precision::Confusion());
if ( ! Context().IsNull() ) Context()->Replace ( myFace, mf.Face() );
myFace = mf.Face();
// deal with the case of an empty face: just create a new face by a standard tool
if (ws.IsEmpty() && !IsSurfaceUVInfinite (mySurf->Surface()))
{
BRepBuilderAPI_MakeFace aFaceBuilder (mySurf->Surface(), Precision::Confusion());
TopoDS_Face aNewFace = aFaceBuilder.Face();
aNewFace.Orientation (myFace.Orientation());
if ( ! Context().IsNull() )
Context()->Replace (myFace, aNewFace);
// taking into account orientation
myFace = aNewFace;
//gka 11.01.99 file PRO7755.stp entity #2018 surface #1895: error BRepLib_MakeFace func IsDegenerated
Handle(ShapeFix_Edge) sfe = myFixWire->FixEdgeTool();
@@ -823,13 +846,12 @@ Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
// B.UpdateFace (myFace,myPrecision);
SendWarning ( myFace, Message_Msg ( "FixAdvFace.FixOrientation.MSG0" ) );// Face created with natural bounds
BRepTools::Update(myFace);
myResult = myFace;
return Standard_True;
}
// check that surface is double-closed and fix is needed
if ( ( mySurf->Adaptor3d()->GetType() != GeomAbs_Sphere &&
mySurf->Adaptor3d()->GetType() != GeomAbs_Torus ) ||
ShapeAnalysis::IsOuterBound (myFace) )
// check if surface is double-closed and fix is needed
if ( !IsSurfaceUVPeriodic (mySurf->Surface()) || ShapeAnalysis::IsOuterBound (myFace) )
return Standard_False;
// Collect informations on free intervals in U and V
@@ -1015,7 +1037,7 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
continue;
}
TopoDS_Iterator ei (wi.Value(),Standard_False);
TopoDS_Iterator ei (wi.Value(),Standard_False);
TopoDS_Edge anEdge;
Standard_Real length = RealLast();
if ( ei.More() ) {
@@ -1059,8 +1081,7 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
if ( nb <= 0) return Standard_False;
Standard_Integer nbInternal=0;
Standard_Boolean isAddNaturalBounds = (NeedFix (myFixAddNaturalBoundMode) &&
( mySurf->Adaptor3d()->GetType() == GeomAbs_Sphere ||
mySurf->Adaptor3d()->GetType() == GeomAbs_Torus ));
IsSurfaceUVPeriodic (mySurf->Surface()));
TColStd_SequenceOfInteger aSeqReversed;
// if wire is only one, check its orientation
if ( nb == 1 ) {
@@ -1070,10 +1091,10 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
TopoDS_Face af = TopoDS::Face ( dummy );
af.Orientation ( TopAbs_FORWARD );
B.Add (af,ws.Value(1));
if ( ( myFixAddNaturalBoundMode != Standard_True || //: abv 29.08.01: Spatial_firex_lofting.sat
( mySurf->Adaptor3d()->GetType() != GeomAbs_Sphere &&
mySurf->Adaptor3d()->GetType() != GeomAbs_Torus ) ) &&
! ShapeAnalysis::IsOuterBound (af)) {
if ((myFixAddNaturalBoundMode != Standard_True || //: abv 29.08.01: Spatial_firex_lofting.sat
!IsSurfaceUVPeriodic (mySurf->Surface()) ) &&
!ShapeAnalysis::IsOuterBound (af) )
{
Handle(ShapeExtend_WireData) sbdw =
new ShapeExtend_WireData (TopoDS::Wire(ws.Value(1)));
sbdw->Reverse ( myFace );
@@ -2300,10 +2321,10 @@ static Standard_Boolean IsPeriodicConicalLoop(const Handle(Geom_ConicalSurface)&
Standard_Real aMaxV = aMaxU;
// Iterate over the edges to check whether the wire is periodic on conical surface
BRepTools_WireExplorer aWireExp(theWire);
for ( ; aWireExp.More(); aWireExp.Next() )
TopoDS_Iterator aWireIter(theWire, Standard_False);
for ( ; aWireIter.More(); aWireIter.Next() )
{
const TopoDS_Edge& aCurrentEdge = aWireExp.Current();
const TopoDS_Edge& aCurrentEdge = TopoDS::Edge(aWireIter.Value());
Handle(Geom2d_Curve) aC2d;
Standard_Real aPFirst, aPLast;