1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0026656: ShapeFix_Face introduces extremely high vertex tolerance in the input shape

Added set of methods CopyVertex in BRepTools_ReShape. Usage of this non-modifying methods added in ShapeFix_Wire, ShapeFix_Edge.
Test case for issue 26656.
Test cases updated to the new behavior.

Correction of test cases for issue CR26656

Changed access by value to access by reference in method CopyVertex.
This commit is contained in:
aml
2015-09-24 15:01:44 +03:00
committed by bugmaster
parent 10a4116e31
commit ed5ca017c7
64 changed files with 308 additions and 121 deletions

View File

@@ -59,6 +59,7 @@
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Vertex.hxx>
#include <ShapeBuild_ReShape.hxx>
//=======================================================================
//function : ShapeFix_Edge
@@ -575,22 +576,36 @@ Standard_Boolean ShapeFix_Edge::FixAddPCurve (const TopoDS_Edge& edge,
//purpose :
//=======================================================================
Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge,
Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge,
const TopoDS_Face& face)
{
myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
TopoDS_Edge anEdgeCopy = edge;
ShapeAnalysis_Edge sae;
if (!Context().IsNull())
{
anEdgeCopy = TopoDS::Edge(Context()->Apply(edge));
}
Standard_Real toler1, toler2;
if (!sae.CheckVertexTolerance (edge, face, toler1, toler2)) return Standard_False;
if (!sae.CheckVertexTolerance (anEdgeCopy, face, toler1, toler2)) return Standard_False;
if (sae.Status (ShapeExtend_DONE1))
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
if (sae.Status (ShapeExtend_DONE2))
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
BRep_Builder B;
TopoDS_Vertex V1 = sae.FirstVertex(edge);
TopoDS_Vertex V2 = sae.LastVertex(edge);
B.UpdateVertex (V1, toler1);
B.UpdateVertex (V2, toler2);
TopoDS_Vertex V1 = sae.FirstVertex(anEdgeCopy);
TopoDS_Vertex V2 = sae.LastVertex(anEdgeCopy);
if (! Context().IsNull())
{
Context()->CopyVertex(V1,toler1);
Context()->CopyVertex(V2,toler2);
}
else
{
B.UpdateVertex (V1, toler1);
B.UpdateVertex (V2, toler2);
}
return Standard_True;
}
@@ -602,18 +617,31 @@ Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge,
Standard_Boolean ShapeFix_Edge::FixVertexTolerance(const TopoDS_Edge& edge)
{
myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
TopoDS_Edge anEdgeCopy = edge;
ShapeAnalysis_Edge sae;
if (!Context().IsNull())
{
anEdgeCopy = TopoDS::Edge(Context()->Apply(edge));
}
Standard_Real toler1, toler2;
if (!sae.CheckVertexTolerance (edge, toler1, toler2)) return Standard_False;
if (!sae.CheckVertexTolerance (anEdgeCopy, toler1, toler2)) return Standard_False;
if (sae.Status (ShapeExtend_DONE1))
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
if (sae.Status (ShapeExtend_DONE2))
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
BRep_Builder B;
TopoDS_Vertex V1 = sae.FirstVertex(edge);
TopoDS_Vertex V2 = sae.LastVertex(edge);
B.UpdateVertex (V1, toler1);
B.UpdateVertex (V2, toler2);
TopoDS_Vertex V1 = sae.FirstVertex(anEdgeCopy);
TopoDS_Vertex V2 = sae.LastVertex(anEdgeCopy);
if (! Context().IsNull())
{
Context()->CopyVertex(V1,toler1);
Context()->CopyVertex(V2,toler2);
}
else
{
B.UpdateVertex (V1, toler1);
B.UpdateVertex (V2, toler2);
}
return Standard_True;
}
@@ -678,17 +706,19 @@ Standard_Boolean ShapeFix_Edge::FixReversed2d (const TopoDS_Edge& edge,
//=======================================================================
Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
const Standard_Real tolerance)
const Standard_Real tolerance)
{
myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
if ( BRep_Tool::Degenerated ( edge ) ) {
if ( BRep_Tool::Degenerated ( edge ) )
{
BRep_Builder B;
if ( ! BRep_Tool::SameRange (edge) )
TempSameRange ( edge, Precision::PConfusion() );
B.SameParameter ( edge, Standard_True );
return Standard_False;
}
ShapeFix_ShapeTolerance SFST;
ShapeAnalysis_Edge sae;
BRep_Builder B;
@@ -699,18 +729,20 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
Standard_Real TolFV = ( V1.IsNull() ? 0. : BRep_Tool::Tolerance ( V1 ) );
Standard_Real TolLV = ( V2.IsNull() ? 0. : BRep_Tool::Tolerance ( V2 ) );
Standard_Real tol = BRep_Tool::Tolerance (edge);
Standard_Boolean wasSP = BRep_Tool::SameParameter ( edge ), SP = Standard_False;
{
try {
try
{
OCC_CATCH_SIGNALS
if ( ! BRep_Tool::SameRange (edge) )
TempSameRange ( edge, Precision::PConfusion() );
if ( ! BRep_Tool::SameRange (edge) )
TempSameRange ( edge, Precision::PConfusion() );
//#81 rln 15.03.99 S4135: for not SP edge choose the best result (either BRepLib or deviation only)
if ( ! wasSP ) {
//create copyedge as copy of edge with the same vertices and copy of pcurves on the same surface(s)
copyedge = ShapeBuild_Edge().Copy ( edge, Standard_False );
B.SameParameter ( copyedge, Standard_False );
if ( ! wasSP )
{
//create copyedge as copy of edge with the same vertices and copy of pcurves on the same surface(s)
copyedge = ShapeBuild_Edge().Copy ( edge, Standard_False );
B.SameParameter ( copyedge, Standard_False );
// ShapeBuild_Edge::Copy() may change 3D curve range (if it's outside of its period).
// In this case pcurves in BRepLib::SameParameter() will be changed as well
// and later ShapeBuild_Edge::CopyPCurves() will copy pcurves keeping original range.
@@ -718,13 +750,13 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
Standard_Real aF, aL;
BRep_Tool::Range (edge, aF, aL);
B.Range (copyedge, aF, aL, Standard_True); // only 3D
BRepLib::SameParameter ( copyedge, ( tolerance >= Precision::Confusion() ?
tolerance : tol ) );
SP = BRep_Tool::SameParameter ( copyedge );
if ( ! SP ) myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
BRepLib::SameParameter ( copyedge, ( tolerance >= Precision::Confusion() ? tolerance : tol ) );
SP = BRep_Tool::SameParameter ( copyedge );
if ( ! SP ) myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
}
}
catch(Standard_Failure) {
catch(Standard_Failure)
{
#ifdef OCCT_DEBUG
cout << "\nWarning: ShapeFix_Edge: Exception in SameParameter: ";
Standard_Failure::Caught()->Print(cout); cout << endl;
@@ -732,25 +764,27 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL2 );
}
}
// compute deviation on the original pcurves
Standard_Real maxdev;
B.SameParameter ( edge, Standard_True );
sae.CheckSameParameter ( edge, maxdev );
if ( sae.Status ( ShapeExtend_FAIL2 ) )
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
// if BRepLib was OK, compare and select the best variant
if ( SP ) {
if ( SP )
{
Standard_Real BRLTol = BRep_Tool::Tolerance ( copyedge ), BRLDev;
sae.CheckSameParameter ( copyedge, BRLDev );
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
if ( BRLTol < BRLDev ) BRLTol = BRLDev;
//chose the best result
if ( BRLTol < maxdev ) {
if ( BRLTol < maxdev )
{
if ( sae.Status ( ShapeExtend_FAIL2 ) )
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL1 );
//copy pcurves and tolerances from copyedge
ShapeBuild_Edge().CopyPCurves ( edge, copyedge );
maxdev = BRLTol;
@@ -758,11 +792,13 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE5 );
}
}
//restore tolerances because they could be modified by BRepLib
if ( ! V1.IsNull() ) SFST.SetTolerance ( V1, Max (maxdev, TolFV), TopAbs_VERTEX);
if ( ! V2.IsNull() ) SFST.SetTolerance ( V2, Max (maxdev, TolLV), TopAbs_VERTEX);
if ( maxdev > tol ) {
if ( maxdev > tol )
{
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
B.UpdateEdge ( edge, maxdev );
FixVertexTolerance(edge);
@@ -781,3 +817,23 @@ Standard_Boolean ShapeFix_Edge::FixSameParameter(const TopoDS_Edge& edge,
{
return ShapeExtend::DecodeStatus (myStatus, status);
}
//=======================================================================
//function : Context
//purpose :
//=======================================================================
inline Handle(ShapeBuild_ReShape) ShapeFix_Edge::Context() const
{
return myContext;
}
//=======================================================================
//function : SetContext
//purpose :
//=======================================================================
void ShapeFix_Edge::SetContext (const Handle(ShapeBuild_ReShape)& context)
{
myContext = context;
}

View File

@@ -31,7 +31,7 @@ class TopoDS_Face;
class Geom_Surface;
class TopLoc_Location;
class ShapeAnalysis_Surface;
class ShapeBuild_ReShape;
class ShapeFix_Edge;
DEFINE_STANDARD_HANDLE(ShapeFix_Edge, MMgt_TShared)
@@ -177,14 +177,17 @@ public:
//! Returns the status (in the form of True/False) of last Fix
Standard_EXPORT Standard_Boolean Status (const ShapeExtend_Status status) const;
//! Sets context
Standard_EXPORT void SetContext (const Handle(ShapeBuild_ReShape)& context);
//! Returns context
Handle(ShapeBuild_ReShape) Context() const;
DEFINE_STANDARD_RTTI(ShapeFix_Edge,MMgt_TShared)
protected:
Handle(ShapeBuild_ReShape) myContext;
Standard_Integer myStatus;
Handle(ShapeConstruct_ProjectCurveOnSurface) myProjector;

View File

@@ -837,7 +837,7 @@ Standard_Boolean ShapeFix_IntersectionTool::FixSelfIntersectWire
//Standard_Real area2d = ShapeAnalysis::TotCross2D(sewd,face);
//if(area2d<Precision::PConfusion()*Precision::PConfusion()) return Standard_False; //gka 06.09.04 BUG 6555
TopoDS_Shape SF = face;
TopoDS_Shape SF = Context()->Apply(face);
Standard_Real MaxTolVert=0.0;
for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) {
Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));

View File

@@ -227,6 +227,7 @@ Standard_Boolean ShapeFix_Shape::Perform(const Handle(Message_ProgressIndicator)
}
case TopAbs_EDGE: {
Handle(ShapeFix_Edge) sfe = FixEdgeTool();
sfe->SetContext(Context());
if(sfe->FixVertexTolerance(TopoDS::Edge(S)))
myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
break;
@@ -238,9 +239,8 @@ Standard_Boolean ShapeFix_Shape::Perform(const Handle(Message_ProgressIndicator)
// Switch to the second progress indication scope if it exists
aPSentry.Next();
myResult = Context()->Apply(S);
myResult = Context()->Apply(S);
if ( NeedFix(myFixSameParameterMode) )
{
SameParameter(myResult, Standard_False, theProgress);
@@ -262,9 +262,9 @@ Standard_Boolean ShapeFix_Shape::Perform(const Handle(Message_ProgressIndicator)
TopExp_Explorer anExpE (myResult, TopAbs_EDGE);
for ( ; anExpE.More(); anExpE.Next())
sfe->FixVertexTolerance( TopoDS::Edge (anExpE.Current()));
}
}
myResult = Context()->Apply(myResult);
if ( !fft.IsNull() )
fft->FixSmallAreaWireMode() = savFixSmallAreaWireMode;

View File

@@ -337,7 +337,9 @@ Standard_Boolean ShapeFix_Wire::Perform()
{
ClearStatuses();
if ( ! IsLoaded() ) return Standard_False;
if ( !Context().IsNull() )
myFixEdge->SetContext( Context() );
Standard_Integer Fixed = Standard_False;
@@ -415,7 +417,12 @@ Standard_Boolean ShapeFix_Wire::Perform()
Handle(ShapeExtend_WireData) sbwd = WireData();
for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++)
if ( myFixEdge->FixVertexTolerance (sbwd->Edge (iedge)) )
{
Fixed = Standard_True;
}
if ( !Context().IsNull() )
UpdateWire();
return Fixed;
}
@@ -776,7 +783,7 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
}
// fix same parameter
if ( isReady && NeedFix ( myFixSameParameterMode ) ) {
if ( isReady && NeedFix ( myFixSameParameterMode ) ){
for ( i=1; i <= nb; i++ ) {
// skl 28.10.2004 for OCC6366 - check SameRange
ShapeAnalysis_Edge sae;
@@ -800,19 +807,24 @@ Standard_Boolean ShapeFix_Wire::FixEdgeCurves()
myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
}
}
//:abv 10.06.02: porting C40 -> dev (CC670-12608.stp): moved from Perform()
// Update with face is needed for plane surfaces (w/o stored pcurves)
if ( NeedFix ( myFixVertexToleranceMode ) ) {
for ( i=1; i <= nb; i++) {
if ( NeedFix ( myFixVertexToleranceMode ) )
{
for ( i=1; i <= nb; i++)
{
myFixEdge->FixVertexTolerance (sbwd->Edge (i), face);
if ( myFixEdge->Status ( ShapeExtend_DONE ) )
myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE8 );
if ( myFixEdge->Status ( ShapeExtend_FAIL ) )
myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
myStatusEdgeCurves |= ShapeExtend::EncodeStatus ( ShapeExtend_FAIL8 );
}
if (!Context().IsNull() )
UpdateWire();
}
return StatusEdgeCurves ( ShapeExtend_DONE );
}
@@ -934,7 +946,7 @@ Standard_Boolean ShapeFix_Wire::FixSelfIntersection()
}
}
}
//pdn 17.03.99 S4135 to avoid regression fixing not adjacent intersection
if ( NeedFix ( myFixNonAdjacentIntersectingEdgesMode ) ) {
@@ -2386,7 +2398,7 @@ Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num
Standard_Real a1, b1, a2, b2;
BRep_Tool::Range ( E1, Face(), a1, b1 );
BRep_Tool::Range ( E2, Face(), a2, b2 );
ShapeAnalysis_Edge sae;
TopoDS_Vertex Vp = sae.FirstVertex ( E1 );
TopoDS_Vertex V1 = sae.LastVertex ( E1 );
@@ -2401,7 +2413,7 @@ Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num
Standard_Boolean IsCutLine = Standard_False;
BRep_Builder B;
Standard_Integer nb = points3d.Length();
for ( Standard_Integer i=1; i <= nb; i++ ) {
const IntRes2d_IntersectionPoint &IP = points2d.Value(i);
@@ -2422,18 +2434,58 @@ Standard_Boolean ShapeFix_Wire::FixIntersectingEdges (const Standard_Integer num
Standard_Boolean locMayEdit = myTopoMode;
// Always try to modify the tolerance firstly as a better solution
if ( /*! myTopoMode &&*/ newtol > tol ) {
if ( /*! myTopoMode &&*/ newtol > tol )
{
Standard_Real te1 = rad + ComputeLocalDeviation (E1, pint, pnt,
param1, ( isForward1 ? b1 : a1 ), Face() );
Standard_Real te2 = rad + ComputeLocalDeviation (E2, pint, pnt,
( isForward2 ? a2 : b2 ), param2, Face() );
Standard_Real maxte = Max ( te1, te2 );
if ( maxte < MaxTolerance() && maxte < newtol ) {
if ( BRep_Tool::Tolerance(E1) < te1 || BRep_Tool::Tolerance(E2) < te2 ) {
if ( maxte < MaxTolerance() && maxte < newtol )
{
if ( BRep_Tool::Tolerance(E1) < te1 || BRep_Tool::Tolerance(E2) < te2 )
{
#ifdef OCCT_DEBUG
cout << "Warning: ShapeFix_Wire::FixIE: edges tolerance increased: (" <<
te1 << ", " << te2 << ") / " << newtol << endl;
#endif
// Make copy of edges.
if (!Context().IsNull())
{
// Intersection point of two base edges.
ShapeBuild_Edge aSBE;
TopoDS_Vertex VV1 = Context()->CopyVertex(V1);
TopoDS_Vertex VVp = Vp;
TopoDS_Vertex VVn = Vn;
if (Vp.IsSame(Vn))
{
// Should modify only one vertex.
VVp = Context()->CopyVertex(Vp);
VVn = VVp;
}
else
{
VVp = Context()->CopyVertex(Vp);
VVn = Context()->CopyVertex(Vn);
}
TopoDS_Edge EE1 = aSBE.CopyReplaceVertices(E1, VVp, VV1);
TopoDS_Edge EE2 = aSBE.CopyReplaceVertices(E2, VV1, VVn);
Context()->Replace(E1, EE1);
Context()->Replace(E2, EE2);
UpdateWire();
E1 = sbwd->Edge(n1);
E2 = sbwd->Edge(n2);
Vp = sae.FirstVertex ( E1 );
V1 = sae.LastVertex ( E1 );
V2 = sae.FirstVertex ( E2 );
Vn = sae.LastVertex ( E2 );
}
B.UpdateEdge ( E1, 1.000001 * te1 );
B.UpdateVertex ( sae.FirstVertex ( E1 ), 1.000001 * te1 );
B.UpdateVertex ( sae.LastVertex ( E1 ), 1.000001 * te1 );