1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-05 18:16:23 +03:00

0024890: Result of uniform scaling is invalid

Test case for issue CR24890
This commit is contained in:
ifv 2015-10-29 15:39:20 +03:00 committed by bugmaster
parent ec7ed71c18
commit 2651bfde07
10 changed files with 377 additions and 108 deletions

View File

@ -61,7 +61,138 @@ void BRepBuilderAPI_NurbsConvert::Perform(const TopoDS_Shape& S,
Handle(BRepTools_NurbsConvertModification) theModif =
Handle(BRepTools_NurbsConvertModification)::DownCast(myModification);
DoModif(S,myModification);
CorrectVertexTol();
}
//=======================================================================
//function : CorrectVertexTol
//purpose :
//=======================================================================
void BRepBuilderAPI_NurbsConvert::CorrectVertexTol()
{
TopTools_MapOfShape anInitVertices;
TopExp_Explorer anExp(myInitialShape, TopAbs_VERTEX);
for(; anExp.More(); anExp.Next())
{
anInitVertices.Add(anExp.Current());
}
//
Handle(BRepTools_NurbsConvertModification) aModif =
Handle(BRepTools_NurbsConvertModification)::DownCast(myModification);
BRep_Builder aBB;
myVtxToReplace.Clear();
TopTools_ListIteratorOfListOfShape anEIter(aModif->GetUpdatedEdges());
for(; anEIter.More(); anEIter.Next())
{
const TopoDS_Shape& anE = anEIter.Value();
//
Standard_Real anETol = BRep_Tool::Tolerance(TopoDS::Edge(anE));
TopoDS_Iterator anIter(anE);
for(; anIter.More(); anIter.Next())
{
const TopoDS_Vertex& aVtx = TopoDS::Vertex(anIter.Value());
if(anInitVertices.Contains(aVtx))
{
if(myVtxToReplace.IsBound(aVtx))
{
aBB.UpdateVertex(TopoDS::Vertex(myVtxToReplace(aVtx)), anETol + Epsilon(anETol));
}
else
{
Standard_Real aVTol = BRep_Tool::Tolerance(aVtx);
if(aVTol < anETol)
{
TopoDS_Vertex aNewVtx;
gp_Pnt aVPnt = BRep_Tool::Pnt(aVtx);
aBB.MakeVertex(aNewVtx, aVPnt,anETol + Epsilon(anETol));
aNewVtx.Orientation(aVtx.Orientation());
myVtxToReplace.Bind(aVtx, aNewVtx);
}
}
}
else
{
aBB.UpdateVertex(aVtx, anETol + Epsilon(anETol));
}
}
}
//
if(myVtxToReplace.IsEmpty())
{
return;
}
//
mySubs.Clear();
TopTools_DataMapIteratorOfDataMapOfShapeShape anIter(myVtxToReplace);
for(; anIter.More(); anIter.Next())
{
mySubs.Replace(anIter.Key(), anIter.Value());
}
mySubs.Apply( myShape );
myShape = mySubs.Value(myShape);
//
}
//=======================================================================
//function : ModifiedShape
//purpose :
//=======================================================================
TopoDS_Shape BRepBuilderAPI_NurbsConvert::ModifiedShape
(const TopoDS_Shape& S) const
{
if(S.ShapeType() == TopAbs_VERTEX)
{
if(myVtxToReplace.IsBound(S))
{
return myVtxToReplace(S);
}
}
if(myVtxToReplace.IsEmpty())
{
return myModifier.ModifiedShape(S);
}
else
{
const TopoDS_Shape& aNS = myModifier.ModifiedShape(S);
return mySubs.Value(aNS);
}
}
//=======================================================================
//function : Modified
//purpose :
//=======================================================================
const TopTools_ListOfShape& BRepBuilderAPI_NurbsConvert::Modified
(const TopoDS_Shape& F)
{
myGenerated.Clear();
if(F.ShapeType() == TopAbs_VERTEX)
{
if(myVtxToReplace.IsBound(F))
{
myGenerated.Append(myVtxToReplace(F));
}
else
{
myGenerated.Append(myModifier.ModifiedShape(F));
}
}
else
{
if(myVtxToReplace.IsEmpty())
{
myGenerated.Append(myModifier.ModifiedShape(F));
}
else
{
const TopoDS_Shape& aNS = myModifier.ModifiedShape(F);
myGenerated.Append(mySubs.Value(aNS));
}
}
return myGenerated;
}

View File

@ -23,6 +23,9 @@
#include <BRepBuilderAPI_ModifyShape.hxx>
#include <Standard_Boolean.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
#include <BRepTools_ReShape.hxx>
class TopoDS_Shape;
@ -66,6 +69,17 @@ public:
Standard_EXPORT void Perform (const TopoDS_Shape& S, const Standard_Boolean Copy = Standard_False);
//! Returns the list of shapes modified from the shape
//! <S>.
Standard_EXPORT virtual const TopTools_ListOfShape& Modified (const TopoDS_Shape& S);
//! Returns the modified shape corresponding to <S>.
//! S can correspond to the entire initial shape or to its subshape.
//! Exceptions
//! Standard_NoSuchObject if S is not the initial shape or
//! a subshape of the initial shape to which the
//! transformation has been applied.
Standard_EXPORT virtual TopoDS_Shape ModifiedShape (const TopoDS_Shape& S) const;
protected:
@ -76,9 +90,10 @@ protected:
private:
Standard_EXPORT void CorrectVertexTol();
TopTools_DataMapOfShapeShape myVtxToReplace;
BRepTools_ReShape mySubs;
};

View File

@ -200,7 +200,7 @@ const TopTools_ListOfShape& BRepOffsetAPI_DraftAngle::ModifiedFaces() const
}
//=======================================================================
//function : ModifiedFaces
//function : Generated
//purpose :
//=======================================================================
@ -216,15 +216,21 @@ const TopTools_ListOfShape& BRepOffsetAPI_DraftAngle::Generated(const TopoDS_Sha
Standard_Real Tol;
Standard_Boolean RW,RF;
if (DMod->NewSurface(TopoDS::Face(S), Surf, L, Tol, RW, RF)) {
myGenerated.Append(ModifiedShape (S));
if(myVtxToReplace.IsEmpty())
{
myGenerated.Append(ModifiedShape (S));
}
else
{
myGenerated.Append(mySubs.Value(ModifiedShape (S)));
}
}
}
return myGenerated;
}
//=======================================================================
//function : ModifiedFaces
//function : Modified
//purpose :
//=======================================================================
@ -242,9 +248,16 @@ const TopTools_ListOfShape& BRepOffsetAPI_DraftAngle::Modified(const TopoDS_Shap
if (!DMod->NewSurface(TopoDS::Face(S), Surf, L, Tol, RW, RF)) {
// Ce n est pas une generation => peut etre une modif
myGenerated.Append(ModifiedShape (S));
if(myVtxToReplace.IsEmpty())
{
myGenerated.Append(ModifiedShape (S));
}
else
{
myGenerated.Append(mySubs.Value(ModifiedShape (S)));
}
if (myGenerated.Extent() == 1 && myGenerated.First().IsSame(S)) {
myGenerated.Clear();
myGenerated.Clear();
}
}
}
@ -266,7 +279,15 @@ TopoDS_Shape BRepOffsetAPI_DraftAngle::ModifiedShape
return myVtxToReplace(S);
}
}
return myModifier.ModifiedShape(S);
if(myVtxToReplace.IsEmpty())
{
return myModifier.ModifiedShape(S);
}
else
{
const TopoDS_Shape& aNS = myModifier.ModifiedShape(S);
return mySubs.Value(aNS);
}
}
//=======================================================================
@ -943,6 +964,7 @@ void BRepOffsetAPI_DraftAngle::CorrectVertexTol()
TopoDS_Vertex aNewVtx;
gp_Pnt aVPnt = BRep_Tool::Pnt(aVtx);
aBB.MakeVertex(aNewVtx, aVPnt,anETol + Epsilon(anETol));
aNewVtx.Orientation(aVtx.Orientation());
myVtxToReplace.Bind(aVtx, aNewVtx);
}
}
@ -959,20 +981,13 @@ void BRepOffsetAPI_DraftAngle::CorrectVertexTol()
return;
}
//
BRepTools_Substitution aSub;
mySubs.Clear();
TopTools_DataMapIteratorOfDataMapOfShapeShape anIter(myVtxToReplace);
for(; anIter.More(); anIter.Next())
{
TopTools_ListOfShape aSubVtx;
aSubVtx.Append(anIter.Value());
aSub.Substitute(anIter.Key(), aSubVtx);
}
aSub.Build( myShape );
if (aSub.IsCopied( myShape ))
{
const TopTools_ListOfShape& listSh = aSub.Copy( myShape );
if (! listSh.IsEmpty())
myShape = listSh.First();
mySubs.Replace(anIter.Key(), anIter.Value());
}
mySubs.Apply( myShape );
myShape = mySubs.Value(myShape);
//
}

View File

@ -27,6 +27,8 @@
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <Draft_ErrorStatus.hxx>
#include <BRepTools_ReShape.hxx>
class StdFail_NotDone;
class Standard_NullObject;
class Standard_NoSuchObject;
@ -208,7 +210,7 @@ private:
Standard_EXPORT void CorrectVertexTol();
TopTools_DataMapOfShapeShape myVtxToReplace;
BRepTools_ReShape mySubs;
};

View File

@ -62,7 +62,7 @@
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopTools_SequenceOfShape.hxx>
#include <GeomLib_CheckCurveOnSurface.hxx>
#include <errno.h>
//=======================================================================
//function : UVBounds
@ -948,5 +948,92 @@ Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
return nbocc == 2;
}
//=======================================================================
//function : EvalAndUpdateTol
//purpose :
//=======================================================================
Standard_Real BRepTools::EvalAndUpdateTol(const TopoDS_Edge& theE,
const Handle(Geom_Curve)& C3d,
const Handle(Geom2d_Curve) C2d,
const Handle(Geom_Surface)& S,
const Standard_Real f,
const Standard_Real l)
{
Standard_Real newtol = 0.;
Standard_Real first = f, last = l;
//Set first, last to avoid ErrosStatus = 2 because of
//too strong checking of limits in class CheckCurveOnSurface
//
if(!C3d->IsPeriodic())
{
first = Max(first, C3d->FirstParameter());
last = Min(last, C3d->LastParameter());
}
if(!C2d->IsPeriodic())
{
first = Max(first, C2d->FirstParameter());
last = Min(last, C2d->LastParameter());
}
GeomLib_CheckCurveOnSurface CT(C3d, S, first, last);
CT.Perform(C2d);
if(CT.IsDone())
{
newtol = CT.MaxDistance();
}
else
{
if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 &&
(C3d->IsPeriodic() || C2d->IsPeriodic())))
{
//Try to estimate by sample points
Standard_Integer nbint = 22;
Standard_Real dt = (last - first) / nbint;
dt = Max(dt, Precision::Confusion());
Standard_Real d, dmax = 0.;
gp_Pnt2d aP2d;
gp_Pnt aPC, aPS;
Standard_Integer cnt = 0;
Standard_Real t = first;
for(; t <= last; t += dt)
{
cnt++;
C2d->D0(t, aP2d);
C3d->D0(t, aPC);
S->D0(aP2d.X(), aP2d.Y(), aPS);
d = aPS.SquareDistance(aPC);
if(d > dmax)
{
dmax = d;
}
}
if(cnt < nbint + 1)
{
t = last;
C2d->D0(t, aP2d);
C3d->D0(t, aPC);
S->D0(aP2d.X(), aP2d.Y(), aPS);
d = aPS.SquareDistance(aPC);
if(d > dmax)
{
dmax = d;
}
}
newtol = 1.2 * Sqrt(dmax);
}
}
Standard_Real Tol = BRep_Tool::Tolerance(theE);
if(newtol > Tol)
{
Tol = newtol;
BRep_Builder B;
B.UpdateEdge(theE, Tol);
}
return Tol;
}

View File

@ -52,6 +52,9 @@ class BRepTools_Substitution;
class BRepTools_Quilt;
class BRepTools_ShapeSet;
class BRepTools_ReShape;
class Geom_Curve;
class Geom2d_Curve;
class Geom_Surface;
//! The BRepTools package provides utilities for BRep
@ -201,6 +204,18 @@ public:
//! <B> is used to build the shape.
Standard_EXPORT static Standard_Boolean Read (TopoDS_Shape& Sh, const Standard_CString File, const BRep_Builder& B, const Handle(Message_ProgressIndicator)& PR = NULL);
//! Evals real tolerance of edge <theE>.
//! <theC3d>, <theC2d>, <theS>, <theF>, <theL> are
//! correspondently 3d curve of edge, 2d curve on surface <theS> and
//! rang of edge
//! If calculated tolerance is more then current edge tolerance, edge is updated.
//! Method returns actual tolerance of edge
Standard_EXPORT static Standard_Real EvalAndUpdateTol(const TopoDS_Edge& theE,
const Handle(Geom_Curve)& theC3d,
const Handle(Geom2d_Curve) theC2d,
const Handle(Geom_Surface)& theS,
const Standard_Real theF,
const Standard_Real theL);

View File

@ -67,7 +67,8 @@
#include <TopoDS_Face.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <BRep_Builder.hxx>
//
static void GeomLib_ChangeUBounds(Handle(Geom_BSplineSurface)& aSurface,
const Standard_Real newU1,
const Standard_Real newU2)
@ -415,6 +416,12 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
(st == STANDARD_TYPE(Geom2d_BezierCurve))) {
if(isConvert2d) {
Curve2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
return Standard_False;
@ -457,9 +464,21 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
ProjLib_ComputeApprox ProjOnCurve(G3dAHC,GAHS,Tol);
if(ProjOnCurve.BSpline().IsNull()) {
Curve2d = Geom2dConvert::CurveToBSplineCurve(ProjOnCurve.Bezier());
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
Curve2d = ProjOnCurve.BSpline();
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
GeomAdaptor_Surface GAS(S,Uinf-u,Usup+u,Vinf-v,Vsup+v);
@ -470,10 +489,22 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
if(ProjOnCurve.IsDone()) {
Curve2d = ProjOnCurve.BSpline();
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
else {
Curve2d = Geom2dConvert::CurveToBSplineCurve(C2d);
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
}
@ -506,6 +537,19 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
if(C3d.IsNull()) {
if(isConvert2d) {
Curve2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
Handle(Geom_Surface) S;
if(newF.IsNull())
S = BRep_Tool::Surface(F);
else
S = BRep_Tool::Surface(newF);
//
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
return Standard_False;
@ -525,6 +569,12 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
(st == STANDARD_TYPE(Geom2d_BezierCurve))) {
if(isConvert2d) {
Curve2d = Handle(Geom2d_Curve)::DownCast(C2d->Copy());
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
return Standard_False;
@ -566,10 +616,22 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewCurve2d
if(ProjOnCurve.IsDone()) {
Curve2d = ProjOnCurve.BSpline();
mylcu.Append(ProjOnCurve.Curve2d());
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
return Standard_True;
}
else {
Curve2d = Geom2dConvert::CurveToBSplineCurve(C2d);
Standard_Real newTol = BRepTools::EvalAndUpdateTol(newE, C3d, Curve2d, S, f3d, l3d);
if(newTol > Tol)
{
Tol = newTol;
myUpdatedEdges.Append(newE);
}
mylcu.Append(C2dBis);
return Standard_True;
}
@ -643,3 +705,12 @@ GeomAbs_Shape BRepTools_NurbsConvertModification::Continuity
}
//=======================================================================
//function : GetUpdatedEdges
//purpose :
//=======================================================================
const TopTools_ListOfShape&
BRepTools_NurbsConvertModification::GetUpdatedEdges() const
{
return myUpdatedEdges;
}

View File

@ -102,6 +102,7 @@ public:
//! (resp. <F2>).
Standard_EXPORT GeomAbs_Shape Continuity (const TopoDS_Edge& E, const TopoDS_Face& F1, const TopoDS_Face& F2, const TopoDS_Edge& NewE, const TopoDS_Face& NewF1, const TopoDS_Face& NewF2);
Standard_EXPORT const TopTools_ListOfShape& GetUpdatedEdges() const;
@ -118,6 +119,7 @@ private:
TopTools_ListOfShape myled;
TColStd_ListOfTransient mylcu;
TColStd_IndexedDataMapOfTransientTransient myMap;
TopTools_ListOfShape myUpdatedEdges;
};

View File

@ -54,84 +54,6 @@
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <GeomLib_CheckCurveOnSurface.hxx>
#include <BRepLib.hxx>
//
static Standard_Real EvalTol(const Handle(Geom_Curve)& C3d,
const Handle(Geom2d_Curve) C2d,
const Handle(Geom_Surface)& S,
const Standard_Real f,
const Standard_Real l)
{
Standard_Real first = f, last = l;
//Set first, last to avoid ErrosStatus = 2 because of
//too strong checking of limits in class CheckCurveOnSurface
//
if(!C3d->IsPeriodic())
{
first = Max(first, C3d->FirstParameter());
last = Min(last, C3d->LastParameter());
}
if(!C2d->IsPeriodic())
{
first = Max(first, C2d->FirstParameter());
last = Min(last, C2d->LastParameter());
}
GeomLib_CheckCurveOnSurface CT(C3d, S, first, last);
CT.Perform(C2d);
if(CT.IsDone())
{
return CT.MaxDistance();
}
else
{
if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 &&
(C3d->IsPeriodic() || C2d->IsPeriodic())))
{
//Try to estimate by sample points
Standard_Integer nbint = 22;
Standard_Real dt = (last - first) / nbint;
dt = Max(dt, Precision::Confusion());
Standard_Real d, dmax = 0.;
gp_Pnt2d aP2d;
gp_Pnt aPC, aPS;
Standard_Integer cnt = 0;
Standard_Real t = first;
for(; t <= last; t += dt)
{
cnt++;
C2d->D0(t, aP2d);
C3d->D0(t, aPC);
S->D0(aP2d.X(), aP2d.Y(), aPS);
d = aPS.SquareDistance(aPC);
if(d > dmax)
{
dmax = d;
}
}
if(cnt < nbint + 1)
{
t = last;
C2d->D0(t, aP2d);
C3d->D0(t, aPC);
S->D0(aP2d.X(), aP2d.Y(), aPS);
d = aPS.SquareDistance(aPC);
if(d > dmax)
{
dmax = d;
}
}
dmax = 1.2 * Sqrt(dmax);
return dmax;
}
else
{
return 0.;
}
}
}
//=======================================================================
//function : Draft_Modification
@ -539,13 +461,7 @@ Standard_Boolean Draft_Modification::NewCurve2d(const TopoDS_Edge& E,
}
//
Handle(Geom_Curve) aC3d = BRep_Tool::Curve(NewE, Fp, Lp);
Standard_Real newtol = EvalTol(aC3d, C, SB, Fp, Lp);
if(newtol > Tol)
{
Tol = newtol;
BRep_Builder B;
B.UpdateEdge(NewE, newtol);
}
Tol = BRepTools::EvalAndUpdateTol(NewE,aC3d, C, SB, Fp, Lp);
return Standard_True;
}

15
tests/bugs/modalg_6/bug24890 Executable file
View File

@ -0,0 +1,15 @@
puts "============"
puts "OCC24890"
puts "============"
puts ""
##############################################################
## Result of uniform scaling is invalid
##############################################################
restore [locate_data_file bug24890_f0.brep] f0
nurbsconvert result f0
checkshape result
set 3dviewer 1