mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-14 13:30:48 +03:00
0028414: Data Exchange, STEP - Face on a closed surface with single inner wire and without natural bound not correctly read
Problem: From the point of view of the STEP format (and others), it is allowed to describe a face on a surface with natural boundaries (torus, sphere) without specifying these boundaries. Thus, a face on a closed surface and containing an inner wire (or several) is correctly defined and describes a face with a cutout defined by this wire. At the same time, there is a function (ShapeFix_Face::FixOrientation) in the ShapeHealing procedure that corrects the orientation of the wires, and it starts before the function of adding natural boundaries (ShapeFix_Face::FixAddNaturalBound). There are many shapes that have incorrectly oriented wires and this procedure successfully heals them, but on a correctly specified face with single inner wire on closed surface, we do not get the entire surface with a cutout, but a part of the surface defined by the wire. This fix is intended to resolve this ambiguity. Change: 1. Added function isNeedAddNaturalBound that returns TRUE if face needs to add natural bounds. 2. Corrected condition in FixOrientation to ignoring faces that needs to add natural bounds. 3. For tests in which one wire was incorrectly oriented on a closed surface, flag AddNaturalBound was disabled. 5. Test with cutout from torus was created: bugs step bug28414. Result: By default, it is correct to add natural boundaries, because this case is correct from the point of view of the STEP format and others.
This commit is contained in:
@@ -647,11 +647,10 @@ Standard_Boolean ShapeFix_Face::Perform()
|
||||
|
||||
// fix natural bounds
|
||||
Standard_Boolean NeedSplit = Standard_True;
|
||||
if ( NeedFix ( myFixAddNaturalBoundMode ) ) {
|
||||
if ( FixAddNaturalBound() ) {
|
||||
NeedSplit = Standard_False;
|
||||
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
|
||||
}
|
||||
if (FixAddNaturalBound())
|
||||
{
|
||||
NeedSplit = Standard_False;
|
||||
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
|
||||
}
|
||||
|
||||
// split face
|
||||
@@ -840,9 +839,11 @@ Standard_Boolean ShapeFix_Face::FixAddNaturalBound()
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
// check if surface is double-closed and fix is needed
|
||||
if ( !IsSurfaceUVPeriodic (mySurf->Adaptor3d()) || ShapeAnalysis::IsOuterBound (myFace) )
|
||||
// check if surface doesn't need natural bounds
|
||||
if (!isNeedAddNaturalBound(ws))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// Collect information on free intervals in U and V
|
||||
TColgp_SequenceOfPnt2d intU, intV, centers;
|
||||
@@ -1002,6 +1003,50 @@ Standard_Boolean ShapeFix_Face::FixOrientation()
|
||||
return FixOrientation(MapWires);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : isNeedAddNaturalBound
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean ShapeFix_Face::isNeedAddNaturalBound(const TopTools_SequenceOfShape& theOrientedWires)
|
||||
{
|
||||
// if fix is not needed
|
||||
if (!NeedFix (myFixAddNaturalBoundMode))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
// if surface is not double-closed
|
||||
if (!IsSurfaceUVPeriodic (mySurf->Adaptor3d()))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
// if face has an OUTER bound
|
||||
if (ShapeAnalysis::IsOuterBound (myFace))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
// check that not any wire has a seam edge and not any edge is degenerated.
|
||||
// because the presence of a seam or degenerated edge indicates that this wire should be an external one,
|
||||
// and in case of its incorrect orientation, this will be corrected.
|
||||
Standard_Integer aNbOriented = theOrientedWires.Length();
|
||||
for (Standard_Integer i = 1; i <= aNbOriented; i++)
|
||||
{
|
||||
TopoDS_Wire aWire = TopoDS::Wire(theOrientedWires.Value(i));
|
||||
for (TopoDS_Iterator anEdgeIt(aWire); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
TopoDS_Edge anEdge = TopoDS::Edge(anEdgeIt.Value());
|
||||
if (BRep_Tool::Degenerated(anEdge))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
if (BRep_Tool::IsClosed(anEdge, myFace))
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : FixOrientation
|
||||
@@ -1071,9 +1116,8 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
|
||||
|
||||
// if no wires, just do nothing
|
||||
if ( nb <= 0) return Standard_False;
|
||||
Standard_Integer nbInternal=0;
|
||||
|
||||
Standard_Boolean isAddNaturalBounds = (NeedFix (myFixAddNaturalBoundMode) && IsSurfaceUVPeriodic(mySurf->Adaptor3d()));
|
||||
Standard_Boolean isAddNaturalBounds = isNeedAddNaturalBound(ws);
|
||||
TColStd_SequenceOfInteger aSeqReversed;
|
||||
// if wire is only one, check its orientation
|
||||
if ( nb == 1 ) {
|
||||
@@ -1084,9 +1128,7 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
|
||||
af.Orientation ( TopAbs_FORWARD );
|
||||
B.Add (af,ws.Value(1));
|
||||
|
||||
if ((myFixAddNaturalBoundMode != 1 ||
|
||||
!IsSurfaceUVPeriodic(mySurf->Adaptor3d())) &&
|
||||
!ShapeAnalysis::IsOuterBound(af))
|
||||
if (!isAddNaturalBounds && !ShapeAnalysis::IsOuterBound(af))
|
||||
{
|
||||
Handle(ShapeExtend_WireData) sbdw =
|
||||
new ShapeExtend_WireData(TopoDS::Wire(ws.Value(1)));
|
||||
@@ -1244,7 +1286,7 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
|
||||
if(!(stb==ste)) {
|
||||
sta = TopAbs_UNKNOWN;
|
||||
SI.Bind(aw,0);
|
||||
j=nb;
|
||||
j=nbAll;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1363,11 +1405,9 @@ Standard_Boolean ShapeFix_Face::FixOrientation(TopTools_DataMapOfShapeListOfShap
|
||||
|
||||
}
|
||||
|
||||
//done = (done && (nb ==1 || (isAddNaturalBounds || (!isAddNaturalBounds && nbInternal <nb))));
|
||||
if(isAddNaturalBounds && nb == aSeqReversed.Length())
|
||||
done = Standard_False;
|
||||
else
|
||||
done = (done && (nb ==1 || (isAddNaturalBounds || (!isAddNaturalBounds && nbInternal <nb))));
|
||||
|
||||
// Faut-il reconstruire ? si myRebil est mis
|
||||
if ( done ) {
|
||||
TopoDS_Shape S = myFace.EmptyCopied();
|
||||
|
Reference in New Issue
Block a user