1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-09 18:50:54 +03:00

0031441: UnifySameDomain corrupts the shape

Local function TransformPCurves is modified to process correctly same-domain elementary surfaces with different local coordinate systems.
This commit is contained in:
jgv 2020-03-22 22:39:12 +03:00 committed by rnv
parent 1af716b9f3
commit b3f078f474
2 changed files with 70 additions and 96 deletions

View File

@ -86,6 +86,7 @@
#include <Extrema_ExtPS.hxx>
#include <BRepTools.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <ElCLib.hxx>
IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_UnifySameDomain,Standard_Transient)
@ -675,129 +676,79 @@ static void TransformPCurves(const TopoDS_Face& theRefFace,
const TopoDS_Face& theFace,
TopTools_MapOfShape& theMapEdgesWithTemporaryPCurves)
{
BRepAdaptor_Surface BAsurf(theFace, Standard_True); //with real bounds of face
Standard_Real Uperiod = 0., Vperiod = 0.;
Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theRefFace);
if (RefSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
RefSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(RefSurf))->BasisSurface();
if (RefSurf->IsUPeriodic())
Uperiod = RefSurf->UPeriod();
if (RefSurf->IsVPeriodic())
Vperiod = RefSurf->VPeriod();
GeomAdaptor_Surface RefGAsurf(RefSurf);
Handle(Geom_Surface) SurfFace = BRep_Tool::Surface(theFace);
if (SurfFace->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
SurfFace = (Handle(Geom_RectangularTrimmedSurface)::DownCast(SurfFace))->BasisSurface();
Standard_Real Ufirst = BAsurf.FirstUParameter(),
Ulast = BAsurf.LastUParameter(),
Vfirst = BAsurf.FirstVParameter(),
Vlast = BAsurf.LastVParameter();
Standard_Real u_mid = (Ufirst + Ulast)/2, v_mid = (Vfirst + Vlast)/2;
gp_Pnt MidPoint = BAsurf.Value(u_mid, v_mid);
Extrema_ExtPS ProjPS(MidPoint, RefGAsurf,
Precision::PConfusion(), Precision::PConfusion());
Standard_Integer indmin = 1;
for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++)
if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(indmin))
indmin = iext;
Standard_Boolean ToModify = Standard_False,
ToTranslate = Standard_False, Y_Reverse = Standard_False;
Standard_Real uu, vv;
ProjPS.Point(indmin).Parameter(uu,vv);
//Check uu and vv
if (Abs(u_mid + Uperiod - uu) <= Precision::PConfusion())
uu = u_mid;
if (Abs(u_mid - uu) <= Precision::PConfusion())
uu = u_mid;
if (Abs(v_mid + Vperiod - vv) <= Precision::PConfusion())
vv = v_mid;
if (Abs(v_mid - vv) <= Precision::PConfusion())
vv = v_mid;
gp_Vec2d Translation(uu - u_mid, vv - v_mid);
gp_Vec2d Translation(0.,0.);
Standard_Boolean X_Reverse = Standard_False, Y_Reverse = Standard_False;
Standard_Real u_dx, v_dx, u_dy, v_dy;
//Get axes of surface of face and of surface of RefFace
Handle(Geom_ElementarySurface) ElemSurfFace = Handle(Geom_ElementarySurface)::DownCast(SurfFace);
Handle(Geom_ElementarySurface) ElemRefSurf = Handle(Geom_ElementarySurface)::DownCast(RefSurf);
Standard_Real Delta = (Precision::IsInfinite(Ufirst) || Precision::IsInfinite(Ulast))?
1. : (Ulast - Ufirst)/4;
Standard_Real Offset = (Uperiod == 0.)? Delta : Min(Uperiod/8, Delta);
Standard_Real u1 = u_mid + Offset, v1 = v_mid;
gp_Pnt DX = BAsurf.Value(u1, v1);
ProjPS.Perform(DX);
indmin = 1;
for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++)
if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(indmin))
indmin = iext;
ProjPS.Point(indmin).Parameter(u_dx, v_dx);
if (Uperiod != 0. &&
Abs(uu - u_dx) > Uperiod/2)
if (!ElemSurfFace.IsNull() && !ElemRefSurf.IsNull())
{
if (uu < Uperiod/2 &&
u_dx > Uperiod/2)
X_Reverse = Standard_True;
}
else if (u_dx < uu)
X_Reverse = Standard_True;
Delta = (Precision::IsInfinite(Vfirst) || Precision::IsInfinite(Vlast))?
1. : (Vlast - Vfirst)/4;
Offset = (Vperiod == 0.)? Delta : Min(Vperiod/8, Delta);
Standard_Real u2 = u_mid, v2 = v_mid + Offset;
gp_Pnt DY = BAsurf.Value(u2, v2);
ProjPS.Perform(DY);
indmin = 1;
for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++)
if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(indmin))
indmin = iext;
gp_Ax3 AxisOfSurfFace = ElemSurfFace->Position();
gp_Ax3 AxisOfRefSurf = ElemRefSurf->Position();
ProjPS.Point(indmin).Parameter(u_dy, v_dy);
if (Vperiod != 0. &&
Abs(vv - v_dy) > Vperiod/2)
{
if (vv < Vperiod/2 &&
v_dy > Vperiod/2)
gp_Pnt OriginRefSurf = AxisOfRefSurf.Location();
Standard_Real aParam = ElCLib::LineParameter(AxisOfSurfFace.Axis(), OriginRefSurf);
if (Abs(aParam) > Precision::PConfusion())
Translation.SetY(-aParam);
gp_Dir VdirSurfFace = AxisOfSurfFace.Direction();
gp_Dir VdirRefSurf = AxisOfRefSurf.Direction();
gp_Dir XdirSurfFace = AxisOfSurfFace.XDirection();
gp_Dir XdirRefSurf = AxisOfRefSurf.XDirection();
Standard_Real anAngle = XdirRefSurf.AngleWithRef(XdirSurfFace, VdirRefSurf);
if (!AxisOfRefSurf.Direct())
anAngle *= -1;
if (Abs(anAngle) > Precision::PConfusion())
Translation.SetX(anAngle);
Standard_Real ScalProd = VdirSurfFace * VdirRefSurf;
if (ScalProd < 0.)
Y_Reverse = Standard_True;
}
else if (v_dy < vv)
Y_Reverse = Standard_True;
gp_Trsf2d aTrsf;
if (X_Reverse && Y_Reverse)
aTrsf.SetMirror(gp::Origin2d());
else if (X_Reverse)
aTrsf.SetMirror(gp::OY2d());
else if (Y_Reverse)
aTrsf.SetMirror(gp::OX2d());
aTrsf.SetTranslationPart(Translation);
ToTranslate = !(Translation.XY().IsEqual(gp_XY(0.,0.), Precision::PConfusion()));
ToModify = ToTranslate || Y_Reverse;
}
BRep_Builder BB;
TopExp_Explorer Explo(theFace, TopAbs_EDGE);
for (; Explo.More(); Explo.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
if (BRep_Tool::Degenerated(anEdge) &&
aTrsf.Form() != gp_Identity)
if (BRep_Tool::Degenerated(anEdge) && ToModify)
continue;
if (BRepTools::IsReallyClosed(anEdge, theFace))
continue;
Standard_Real fpar, lpar;
Handle(Geom2d_Curve) PCurveOnRef = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar);
if (!PCurveOnRef.IsNull())
if (!PCurveOnRef.IsNull() && !ToModify)
continue;
Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar);
Handle(Geom2d_Curve) aNewPCurve = Handle(Geom2d_Curve)::DownCast(aPCurve->Copy());
if (aTrsf.Form() != gp_Identity)
aNewPCurve->Transform(aTrsf);
if (ToTranslate)
aNewPCurve->Translate(Translation);
if (Y_Reverse)
aNewPCurve->Mirror(gp::OX2d());
Standard_Real tmp_first, tmp_last;
Handle(Geom2d_Curve) aPCurveOnRefFace = BRep_Tool::CurveOnSurface(anEdge, theRefFace,
tmp_first, tmp_last);
if (aPCurveOnRefFace.IsNull())
theMapEdgesWithTemporaryPCurves.Add(anEdge);
theMapEdgesWithTemporaryPCurves.Add(anEdge);
BB.UpdateEdge(anEdge, aNewPCurve, theRefFace, 0.);
BB.Range(anEdge, fpar, lpar);
@ -820,7 +771,8 @@ static void AddPCurves(const TopTools_SequenceOfShape& theFaces,
for (Standard_Integer i = 1; i <= theFaces.Length(); i++)
{
const TopoDS_Face& aFace = TopoDS::Face(theFaces(i));
TopoDS_Face aFace = TopoDS::Face(theFaces(i));
aFace.Orientation(TopAbs_FORWARD);
if (aFace.IsSame(theRefFace))
continue;
@ -2189,7 +2141,9 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
if (faces.Length() > 1) {
//Add correct pcurves for the reference surface to the edges of other faces
AddPCurves(faces, RefFace, MapEdgesWithTemporaryPCurves);
TopoDS_Face F_RefFace = RefFace;
F_RefFace.Orientation(TopAbs_FORWARD);
AddPCurves(faces, F_RefFace, MapEdgesWithTemporaryPCurves);
// fill in the connectivity map for selected faces
TopTools_IndexedDataMapOfShapeListOfShape aMapEF;

View File

@ -0,0 +1,20 @@
puts "============================================"
puts "OCC31441: UnifySameDomain corrupts the shape"
puts "============================================"
puts ""
brestore [locate_data_file bug31441.brep] a
unifysamedom result a
checkshape result
checknbshapes result -solid 1 -shell 2 -face 46 -wire 48 -edge 128 -vertex 84
set tolres [checkmaxtol result]
if { ${tolres} > 2.e-7} {
puts "Error: bad tolerance of result"
}
checkprops result -v 1.10788