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

0031736: ShapeUpgrade_UnifySameDomain algorithm does not unify all possible faces

1. Correct processing faces that can be converted into planar ones.
2. Correct processing faces based on V-closed surfaces.
This commit is contained in:
jgv 2020-09-01 23:55:52 +03:00 committed by bugmaster
parent ed753e10df
commit c3e0e1de43
5 changed files with 194 additions and 151 deletions

View File

@ -495,8 +495,9 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
const TopoDS_Face& theFrefFace, const TopoDS_Face& theFrefFace,
const TopoDS_Vertex& theCurVertex, const TopoDS_Vertex& theCurVertex,
const gp_Pnt2d& theCurPoint, const gp_Pnt2d& theCurPoint,
const Standard_Real theUperiod, const Standard_Real thePeriod,
const Standard_Real theFaceUmin, const Standard_Real theFaceCoordMin,
const Standard_Boolean theIsU,
const Standard_Real theCoordTol, const Standard_Real theCoordTol,
TopoDS_Edge& theNextEdge, TopoDS_Edge& theNextEdge,
TopoDS_Wire& theNewWire, TopoDS_Wire& theNewWire,
@ -507,16 +508,24 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
{ {
Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theFrefFace); Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theFrefFace);
GeomAbs_Shape aContinuity = (RefSurf->IsUPeriodic())? GeomAbs_CN : GeomAbs_C0; GeomAbs_Shape aContinuity;
if (theIsU)
aContinuity = (RefSurf->IsUPeriodic())? GeomAbs_CN : GeomAbs_C0;
else
aContinuity = (RefSurf->IsVPeriodic())? GeomAbs_CN : GeomAbs_C0;
Standard_Integer IndCoord = theIsU? 1 : 2;
Standard_Real Ydir = 1.; //up Standard_Real SeamDir = 1.; //up or right
if (Abs(theCurPoint.X() - theFaceUmin) <= theCoordTol) if (theIsU && Abs(theCurPoint.Coord(IndCoord) - theFaceCoordMin) <= theCoordTol)
Ydir = -1.; //down SeamDir = -1.; //down
else if (!theIsU && Abs(theCurPoint.Coord(IndCoord) - theFaceCoordMin) > theCoordTol)
SeamDir = -1.; //left
//Consider as the candidate to be next edge: //Consider as the candidate to be next edge:
//only the edge that has first point with X-coordinate close to X-coordinate of theCurPoint //only the edge that has first point with X(or Y)-coordinate close to X(or Y)-coordinate of theCurPoint
//Choose from candidates the edge that is closest to theCurPoint in the defined direction Ydir //Choose from candidates the edge that is closest to theCurPoint in the defined direction SeamDir
Standard_Real MinDeltaY = RealLast(); Standard_Real MinDeltaSeamCoord = RealLast();
for (Standard_Integer ind = 1; ind <= theEdges.Length(); ind++) for (Standard_Integer ind = 1; ind <= theEdges.Length(); ind++)
{ {
const TopoDS_Edge& aCandidate = TopoDS::Edge(theEdges(ind)); const TopoDS_Edge& aCandidate = TopoDS::Edge(theEdges(ind));
@ -526,17 +535,17 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
Standard_Real CandParam = (aCandidate.Orientation() == TopAbs_FORWARD)? Standard_Real CandParam = (aCandidate.Orientation() == TopAbs_FORWARD)?
BAcurve2d.FirstParameter() : BAcurve2d.LastParameter(); BAcurve2d.FirstParameter() : BAcurve2d.LastParameter();
gp_Pnt2d CandPoint = BAcurve2d.Value(CandParam); gp_Pnt2d CandPoint = BAcurve2d.Value(CandParam);
Standard_Real DeltaX = Abs(CandPoint.X() - theCurPoint.X()); Standard_Real DeltaCoord = Abs(CandPoint.Coord(IndCoord) - theCurPoint.Coord(IndCoord));
if (DeltaX > theCoordTol) if (DeltaCoord > theCoordTol)
continue; continue;
Standard_Real DeltaY = CandPoint.Y() - theCurPoint.Y(); Standard_Real DeltaSeamCoord = CandPoint.Coord(3-IndCoord) - theCurPoint.Coord(3-IndCoord);
DeltaY *= Ydir; DeltaSeamCoord *= SeamDir;
if (DeltaY < 0.) //on the other side from CurPoint if (DeltaSeamCoord < 0.) //on the other side from CurPoint
continue; continue;
if (DeltaY < MinDeltaY) if (DeltaSeamCoord < MinDeltaSeamCoord)
{ {
MinDeltaY = DeltaY; MinDeltaSeamCoord = DeltaSeamCoord;
theNextEdge = aCandidate; theNextEdge = aCandidate;
theStartOfNextEdge = CandPoint; theStartOfNextEdge = CandPoint;
} }
@ -545,58 +554,68 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
//Build missed seam edge //Build missed seam edge
theLastVertexOfSeam = TopExp::FirstVertex(theNextEdge, Standard_True); //with orientation theLastVertexOfSeam = TopExp::FirstVertex(theNextEdge, Standard_True); //with orientation
TopoDS_Vertex V1, V2; TopoDS_Vertex V1, V2;
Standard_Real Param1, Param2, anU = 0.; Standard_Real Param1, Param2, aCoord = 0.;
Handle(Geom_Curve) Uiso; Handle(Geom_Curve) Iso;
TopoDS_Edge aRemovedEdge; //try to find it in <RemovedEdges> TopoDS_Edge aRemovedEdge; //try to find it in <RemovedEdges>
for (Standard_Integer i = 1; i <= theRemovedEdges.Length(); i++) for (Standard_Integer i = 1; i <= theRemovedEdges.Length(); i++)
{ {
const TopoDS_Edge& anEdge = TopoDS::Edge(theRemovedEdges(i)); const TopoDS_Edge& anEdge = TopoDS::Edge(theRemovedEdges(i));
Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(anEdge, theFrefFace, Param1, Param2);
if (aPC.IsNull())
continue;
GeomAbs_Shape aContOnRefFace = BRep_Tool::Continuity(anEdge, theFrefFace, theFrefFace);
if (aContOnRefFace > aContinuity)
aContinuity = aContOnRefFace;
TopoDS_Vertex aV1, aV2; TopoDS_Vertex aV1, aV2;
TopExp::Vertices(anEdge, aV1, aV2); TopExp::Vertices(anEdge, aV1, aV2);
if ((aV1.IsSame(theCurVertex) && aV2.IsSame(theLastVertexOfSeam)) || if ((aV1.IsSame(theCurVertex) && aV2.IsSame(theLastVertexOfSeam)) ||
(aV1.IsSame(theLastVertexOfSeam) && aV2.IsSame(theCurVertex))) (aV1.IsSame(theLastVertexOfSeam) && aV2.IsSame(theCurVertex)))
{ {
Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(anEdge, theFrefFace, Param1, Param2); aRemovedEdge = anEdge;
if (!aPC.IsNull()) break;
{
aRemovedEdge = anEdge;
break;
}
} }
} }
if (aRemovedEdge.IsNull()) if (aRemovedEdge.IsNull())
{ {
Standard_Real CurTol = BRep_Tool::Tolerance(theCurVertex); Standard_Real CurTol = BRep_Tool::Tolerance(theCurVertex);
Standard_Real LastTol = BRep_Tool::Tolerance(theLastVertexOfSeam); Standard_Real LastTol = BRep_Tool::Tolerance(theLastVertexOfSeam);
anU = (CurTol < LastTol)? theCurPoint.X() : theStartOfNextEdge.X(); aCoord = (CurTol < LastTol)? theCurPoint.Coord(IndCoord) : theStartOfNextEdge.Coord(IndCoord);
Uiso = RefSurf->UIso(anU); Iso = (theIsU)? RefSurf->UIso(aCoord) : RefSurf->VIso(aCoord);
if (Ydir > 0) if (SeamDir > 0)
{ {
V1 = theCurVertex; V2 = theLastVertexOfSeam; V1 = theCurVertex; V2 = theLastVertexOfSeam;
Param1 = theCurPoint.Y(); Param2 = theStartOfNextEdge.Y(); Param1 = theCurPoint.Coord(3-IndCoord); Param2 = theStartOfNextEdge.Coord(3-IndCoord);
} }
else else
{ {
V1 = theLastVertexOfSeam; V2 = theCurVertex; V1 = theLastVertexOfSeam; V2 = theCurVertex;
Param1 = theStartOfNextEdge.Y(); Param2 = theCurPoint.Y(); Param1 = theStartOfNextEdge.Coord(3-IndCoord); Param2 = theCurPoint.Coord(3-IndCoord);
} }
} }
else else
{ {
TopExp::Vertices(aRemovedEdge, V1, V2); TopExp::Vertices(aRemovedEdge, V1, V2);
Uiso = BRep_Tool::Curve(aRemovedEdge, Param1, Param2); Iso = BRep_Tool::Curve(aRemovedEdge, Param1, Param2);
} }
TopoDS_Edge MissedSeam = BRepLib_MakeEdge(Uiso, V1, V2, Param1, Param2); TopoDS_Edge MissedSeam = BRepLib_MakeEdge(Iso, V1, V2, Param1, Param2);
BRep_Builder BB; BRep_Builder BB;
gp_Vec2d Offset(theUperiod, 0.); //gp_Vec2d Offset(theUperiod, 0.);
gp_Vec2d Offset;
if (theIsU)
Offset.SetCoord(thePeriod, 0.);
else
Offset.SetCoord(0., thePeriod);
if (aRemovedEdge.IsNull()) if (aRemovedEdge.IsNull())
{ {
Standard_Real Vorigin = 0.; Standard_Real SeamCoordOrigin = 0.;
//Correct Param1 and Param2 if needed: //Correct Param1 and Param2 if needed:
//when Uiso-curve is periodic and Param1 and Param2 do not fit into V-range of surface, //when iso-curve is periodic and Param1 and Param2 do not fit into SeamCoord-range of surface,
//(for example, V-range of sphere)
//BRepLib_MakeEdge may shift Param1 and Param2 //BRepLib_MakeEdge may shift Param1 and Param2
Standard_Real InitialParam1 = Param1, InitialParam2 = Param2; Standard_Real InitialParam1 = Param1, InitialParam2 = Param2;
Handle(Geom_Curve) MissedCurve = BRep_Tool::Curve(MissedSeam, Param1, Param2); Handle(Geom_Curve) MissedCurve = BRep_Tool::Curve(MissedSeam, Param1, Param2);
@ -604,21 +623,29 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
MissedCurve->IsPeriodic()) MissedCurve->IsPeriodic())
{ {
//Vorigin = -(MissedCurve->Period()); //Vorigin = -(MissedCurve->Period());
Vorigin = -(Param1 - InitialParam1); SeamCoordOrigin = -(Param1 - InitialParam1);
} }
///////////////////////////////////// /////////////////////////////////////
Handle(Geom2d_Line) PC1 = new Geom2d_Line(gp_Pnt2d(anU, Vorigin), gp_Dir2d(0., 1.)); //Handle(Geom2d_Line) PC1 = new Geom2d_Line(gp_Pnt2d(anU, Vorigin), gp_Dir2d(0., 1.));
Handle(Geom2d_Line) PC1;
if (theIsU)
PC1 = new Geom2d_Line(gp_Pnt2d(aCoord, SeamCoordOrigin), gp_Dir2d(0., 1.));
else
PC1 = new Geom2d_Line(gp_Pnt2d(SeamCoordOrigin, aCoord), gp_Dir2d(1., 0.));
Handle(Geom2d_Curve) PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy()); Handle(Geom2d_Curve) PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy());
if (Ydir > 0) if (theIsU && SeamDir > 0)
Offset *= -1;
else if (!theIsU && SeamDir < 0)
Offset *= -1; Offset *= -1;
PC2->Translate(Offset); PC2->Translate(Offset);
if (Ydir > 0) if (SeamDir > 0)
BB.UpdateEdge(MissedSeam, PC1, PC2, theFrefFace, 0.); BB.UpdateEdge(MissedSeam, PC1, PC2, theFrefFace, 0.);
else else
BB.UpdateEdge(MissedSeam, PC2, PC1, theFrefFace, 0.); BB.UpdateEdge(MissedSeam, PC2, PC1, theFrefFace, 0.);
if (Ydir < 0) if (SeamDir < 0)
MissedSeam.Reverse(); MissedSeam.Reverse();
} }
else else
@ -631,19 +658,19 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
Standard_Boolean IsSeam = (PC1 != PC2); Standard_Boolean IsSeam = (PC1 != PC2);
if (!IsSeam) //it was not a seam if (!IsSeam) //it was not a seam
{ {
anU = theCurPoint.X(); aCoord = theCurPoint.Coord(IndCoord);
gp_Pnt2d PointOnRemovedEdge = PC1->Value(Param1); gp_Pnt2d PointOnRemovedEdge = PC1->Value(Param1);
Standard_Real Uremovededge = PointOnRemovedEdge.X(); Standard_Real CoordOfRemovededge = PointOnRemovedEdge.Coord(IndCoord);
if (Abs(anU - Uremovededge) > theUperiod/2) if (Abs(aCoord - CoordOfRemovededge) > thePeriod/2)
{ {
Standard_Real Sign = (anU > Uremovededge)? 1 : -1; Standard_Real Sign = (aCoord > CoordOfRemovededge)? 1 : -1;
Offset *= Sign; Offset *= Sign;
PC1 = Handle(Geom2d_Curve)::DownCast(PC2->Copy()); PC1 = Handle(Geom2d_Curve)::DownCast(PC2->Copy());
PC1->Translate(Offset); PC1->Translate(Offset);
} }
else else
{ {
if (Ydir > 0) if (SeamDir > 0)
Offset *= -1; Offset *= -1;
PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy()); PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy());
PC2->Translate(Offset); PC2->Translate(Offset);
@ -673,6 +700,7 @@ static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges,
BAcurve2d.LastParameter() : BAcurve2d.FirstParameter(); BAcurve2d.LastParameter() : BAcurve2d.FirstParameter();
theNextPoint = BAcurve2d.Value(ParamOfNextPoint); theNextPoint = BAcurve2d.Value(ParamOfNextPoint);
} }
//======================================================================= //=======================================================================
//function : SameSurf //function : SameSurf
//purpose : auxilary //purpose : auxilary
@ -1109,90 +1137,6 @@ static Standard_Boolean GetNormalToSurface(const TopoDS_Face& theFace,
return Standard_True; return Standard_True;
} }
//=======================================================================
//function : IsInSide
//purpose :
//=======================================================================
static Standard_Boolean IsInSide(const gp_Pln& theRefPln,
const Handle(Geom_Surface)& theRefSurf,
const Handle(Geom_Surface)& theCheckedSurf, const Standard_Real theLinTol)
{
//
Standard_Real uf, ul, vf, vl;
theRefSurf->Bounds(uf, ul, vf, vl);
if (Precision::IsInfinite(uf) && Precision::IsInfinite(ul) &&
Precision::IsInfinite(vf) && Precision::IsInfinite(vl))
{
return Standard_True;
}
else if (Precision::IsInfinite(uf) || Precision::IsInfinite(ul) ||
Precision::IsInfinite(vf) || Precision::IsInfinite(vl))
{
//To avoid calculation of "infinite" isoline
return Standard_False;
}
//
Handle(Geom_Curve) anIsolines[4];
anIsolines[0] = theRefSurf->VIso(vf);
anIsolines[1] = theRefSurf->UIso(ul);
anIsolines[2] = theRefSurf->VIso(vl)->Reversed();
anIsolines[3] = theRefSurf->UIso(uf)->Reversed();
BRepBuilderAPI_MakeWire aMkWire;
TopoDS_Edge E;
Standard_Integer i;
for (i = 0; i < 4; ++i)
{
GeomAdaptor_Curve aGAC(anIsolines[i]);
Standard_Real length = GCPnts_AbscissaPoint::Length(aGAC);
if (length > Precision::Confusion())
{
E = BRepBuilderAPI_MakeEdge(anIsolines[i]);
aMkWire.Add(E);
}
}
TopoDS_Face aRefFace;
TopoDS_Wire aW;
if (aMkWire.IsDone())
{
aW = aMkWire.Wire();
}
else
{
return Standard_False;
}
//
BRepBuilderAPI_MakeFace aMkFace(theRefPln, aW);
if (aMkFace.IsDone())
{
aRefFace = aMkFace.Face();
}
else
{
return Standard_False;
}
//
Standard_Real up, vp;
BRepTopAdaptor_FClass2d aFClass(aRefFace, theLinTol);
theCheckedSurf->Bounds(uf, ul, vf, vl);
const gp_Ax3& aPos = theRefPln.Position();
//
gp_Pnt2d aP2d[4] = { gp_Pnt2d(uf, vf), gp_Pnt2d(ul, vf), gp_Pnt2d(ul, vl), gp_Pnt2d(uf, vl) };
for (i = 0; i < 4; ++i)
{
gp_Pnt aP = theCheckedSurf->Value(aP2d[i].X(), aP2d[i].Y());
ElSLib::PlaneParameters(aPos, aP, up, vp);
gp_Pnt2d aP2(up, vp);
TopAbs_State aSt = aFClass.Perform(aP2);
if (aSt == TopAbs_OUT || aSt == TopAbs_UNKNOWN)
{
return Standard_False;
}
}
//
return Standard_True;
}
//======================================================================= //=======================================================================
//function : IsSameDomain //function : IsSameDomain
//purpose : //purpose :
@ -1200,7 +1144,8 @@ static Standard_Boolean IsInSide(const gp_Pln& theRefPln,
static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
const TopoDS_Face& aCheckedFace, const TopoDS_Face& aCheckedFace,
const Standard_Real theLinTol, const Standard_Real theLinTol,
const Standard_Real theAngTol) const Standard_Real theAngTol,
ShapeUpgrade_UnifySameDomain::DataMapOfFacePlane& theFacePlaneMap)
{ {
//checking the same handles //checking the same handles
TopLoc_Location L1, L2; TopLoc_Location L1, L2;
@ -1234,11 +1179,20 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace,
gp_Pln aPln2 = aPlanarityChecker2.Plan(); gp_Pln aPln2 = aPlanarityChecker2.Plan();
if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), theAngTol) && if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), theAngTol) &&
aPln1.Distance(aPln2) < theLinTol) { aPln1.Distance(aPln2) < theLinTol)
Standard_Real uf, ul, vf, vl; {
BRepTools::UVBounds(aCheckedFace, uf, ul, vf, vl); Handle(Geom_Plane) aPlaneOfFaces;
S2 = new Geom_RectangularTrimmedSurface(S2, uf, ul, vf, vl); if (theFacePlaneMap.IsBound(aFace))
return IsInSide(aPln1, S1, S2, theLinTol); aPlaneOfFaces = theFacePlaneMap(aFace);
else if (theFacePlaneMap.IsBound(aCheckedFace))
aPlaneOfFaces = theFacePlaneMap(aCheckedFace);
else
aPlaneOfFaces = new Geom_Plane(aPln1);
theFacePlaneMap.Bind(aFace, aPlaneOfFaces);
theFacePlaneMap.Bind(aCheckedFace, aPlaneOfFaces);
return Standard_True;
} }
} }
} }
@ -2167,6 +2121,7 @@ void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
myContext->Clear(); myContext->Clear();
myKeepShapes.Clear(); myKeepShapes.Clear();
myFacePlaneMap.Clear();
myHistory->Clear(); myHistory->Clear();
} }
@ -2314,6 +2269,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
//these edges may be updated by temporary pcurves //these edges may be updated by temporary pcurves
Standard_Real Uperiod = (aBaseSurface->IsUPeriodic())? aBaseSurface->UPeriod() : 0.; Standard_Real Uperiod = (aBaseSurface->IsUPeriodic())? aBaseSurface->UPeriod() : 0.;
Standard_Real Vperiod = (aBaseSurface->IsVPeriodic())? aBaseSurface->VPeriod() : 0.;
// find adjacent faces to union // find adjacent faces to union
Standard_Integer i; Standard_Integer i;
@ -2373,7 +2329,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
} }
} }
// //
if (IsSameDomain(aFace,aCheckedFace, myLinTol, myAngTol)) { if (IsSameDomain(aFace,aCheckedFace, myLinTol, myAngTol, myFacePlaneMap)) {
if (AddOrdinaryEdges(edges, aCheckedFace, dummy, RemovedEdges)) { if (AddOrdinaryEdges(edges, aCheckedFace, dummy, RemovedEdges)) {
// sequence edges is modified // sequence edges is modified
@ -2388,6 +2344,12 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
} }
if (faces.Length() > 1) { if (faces.Length() > 1) {
if (myFacePlaneMap.IsBound(faces(1)))
{
const Handle(Geom_Plane)& aPlane = myFacePlaneMap(faces(1));
TopLoc_Location aLoc;
BB.UpdateFace(RefFace, aPlane, aLoc, Precision::Confusion());
}
//Add correct pcurves for the reference surface to the edges of other faces //Add correct pcurves for the reference surface to the edges of other faces
TopoDS_Face F_RefFace = RefFace; TopoDS_Face F_RefFace = RefFace;
F_RefFace.Orientation(TopAbs_FORWARD); F_RefFace.Orientation(TopAbs_FORWARD);
@ -2528,6 +2490,10 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
if (faces.Length() > 1) if (faces.Length() > 1)
{ {
Standard_Real CoordTol = Precision::Confusion(); Standard_Real CoordTol = Precision::Confusion();
TopTools_MapOfShape edgesMap;
CoordTol = ComputeMinEdgeSize(edges, F_RefFace, edgesMap);
CoordTol /= 10.;
CoordTol = Max(CoordTol, Precision::Confusion());
TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopTools_IndexedDataMapOfShapeListOfShape VEmap;
for (Standard_Integer ind = 1; ind <= edges.Length(); ind++) for (Standard_Integer ind = 1; ind <= edges.Length(); ind++)
@ -2537,11 +2503,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
//Define boundaries in 2d space of RefFace //Define boundaries in 2d space of RefFace
if (Uperiod != 0.) if (Uperiod != 0.)
{ {
TopTools_MapOfShape edgesMap;
CoordTol = ComputeMinEdgeSize(edges, F_RefFace, edgesMap);
CoordTol /= 10.;
CoordTol = Max(CoordTol, Precision::Confusion());
//try to find a real seam edge - if it exists, do nothing //try to find a real seam edge - if it exists, do nothing
Standard_Boolean SeamFound = Standard_False; Standard_Boolean SeamFound = Standard_False;
for (Standard_Integer ii = 1; ii <= faces.Length(); ii++) for (Standard_Integer ii = 1; ii <= faces.Length(); ii++)
@ -2643,32 +2604,41 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
TopTools_SequenceOfShape NewFaces, NewWires; TopTools_SequenceOfShape NewFaces, NewWires;
if (Uperiod == 0) if (Uperiod == 0 || Vperiod == 0)
{ {
//Set the "period" for closed non-periodic surface //Set the "periods" for closed non-periodic surface
TopLoc_Location aLoc; TopLoc_Location aLoc;
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc); Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc);
if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
aSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf))->BasisSurface(); aSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf))->BasisSurface();
Standard_Real Ufirst, Ulast, Vfirst, Vlast; Standard_Real Ufirst, Ulast, Vfirst, Vlast;
aSurf->Bounds(Ufirst, Ulast, Vfirst, Vlast); aSurf->Bounds(Ufirst, Ulast, Vfirst, Vlast);
if (aSurf->IsUClosed()) if (Uperiod == 0 && aSurf->IsUClosed())
Uperiod = Ulast - Ufirst; Uperiod = Ulast - Ufirst;
if (Vperiod == 0 && aSurf->IsVClosed())
Vperiod = Vlast - Vfirst;
} }
TopTools_MapOfShape UsedEdges; TopTools_MapOfShape UsedEdges;
Standard_Real FaceUmin = RealLast(); Standard_Real FaceUmin = RealLast();
Standard_Real FaceVmin = RealLast();
for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) for (Standard_Integer ii = 1; ii <= edges.Length(); ii++)
{ {
const TopoDS_Edge& anEdge = TopoDS::Edge(edges(ii)); const TopoDS_Edge& anEdge = TopoDS::Edge(edges(ii));
BRepAdaptor_Curve2d aBAcurve(anEdge, F_RefFace); BRepAdaptor_Curve2d aBAcurve(anEdge, F_RefFace);
gp_Pnt2d aFirstPoint = aBAcurve.Value(aBAcurve.FirstParameter()); gp_Pnt2d aFirstPoint = aBAcurve.Value(aBAcurve.FirstParameter());
gp_Pnt2d aLastPoint = aBAcurve.Value(aBAcurve.LastParameter()); gp_Pnt2d aLastPoint = aBAcurve.Value(aBAcurve.LastParameter());
if (aFirstPoint.X() < FaceUmin) if (aFirstPoint.X() < FaceUmin)
FaceUmin = aFirstPoint.X(); FaceUmin = aFirstPoint.X();
if (aLastPoint.X() < FaceUmin) if (aLastPoint.X() < FaceUmin)
FaceUmin = aLastPoint.X(); FaceUmin = aLastPoint.X();
if (aFirstPoint.Y() < FaceVmin)
FaceVmin = aFirstPoint.Y();
if (aLastPoint.Y() < FaceVmin)
FaceVmin = aLastPoint.Y();
} }
//Building new wires from <edges> //Building new wires from <edges>
@ -2726,7 +2696,18 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
gp_Pnt2d StartOfNextEdge; gp_Pnt2d StartOfNextEdge;
TopoDS_Vertex LastVertexOfSeam; TopoDS_Vertex LastVertexOfSeam;
ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex, ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
CurPoint, Uperiod, FaceUmin, CoordTol, CurPoint, Uperiod, FaceUmin, Standard_True, CoordTol,
NextEdge, aNewWire, NextPoint,
StartOfNextEdge, LastVertexOfSeam, VEmap);
}
else if (Vperiod != 0. &&
Abs(StartPoint.Y() - CurPoint.Y()) > Vperiod/2) //end of parametric space
{
//<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
gp_Pnt2d StartOfNextEdge;
TopoDS_Vertex LastVertexOfSeam;
ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
CurPoint, Vperiod, FaceVmin, Standard_False, CoordTol,
NextEdge, aNewWire, NextPoint, NextEdge, aNewWire, NextPoint,
StartOfNextEdge, LastVertexOfSeam, VEmap); StartOfNextEdge, LastVertexOfSeam, VEmap);
} }
@ -2754,7 +2735,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
TmpElist.Append(anEdge); TmpElist.Append(anEdge);
} }
if (TmpElist.Extent() <= 1 || if (TmpElist.Extent() <= 1 ||
Uperiod != 0.) (Uperiod != 0. || Vperiod != 0))
TrueElist.Assign(TmpElist); TrueElist.Assign(TmpElist);
else else
{ {
@ -2797,20 +2778,25 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar); Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar);
Standard_Real aParam = (anEdge.Orientation() == TopAbs_FORWARD)? fpar : lpar; Standard_Real aParam = (anEdge.Orientation() == TopAbs_FORWARD)? fpar : lpar;
gp_Pnt2d aPoint = aPCurve->Value(aParam); gp_Pnt2d aPoint = aPCurve->Value(aParam);
Standard_Real Diff = Abs(aPoint.X() - CurPoint.X()); Standard_Real DiffU = Abs(aPoint.X() - CurPoint.X());
Standard_Real DiffV = Abs(aPoint.Y() - CurPoint.Y());
if (Uperiod != 0. && if (Uperiod != 0. &&
Diff > CoordTol && DiffU > CoordTol &&
Abs(Diff - Uperiod) > CoordTol) //may be is is a deg.vertex Abs(DiffU - Uperiod) > CoordTol) //may be is is a deg.vertex
continue;
if (Vperiod != 0. &&
DiffV > CoordTol &&
Abs(DiffV - Vperiod) > CoordTol) //may be is is a deg.vertex
continue; continue;
//Check: may be <CurPoint> and <aPoint> are on Period from each other //Check: may be <CurPoint> and <aPoint> are on Period from each other
if (Uperiod != 0. && Diff > Uperiod/2) //end of parametric space if (Uperiod != 0. && DiffU > Uperiod/2) //end of parametric space
{ {
//<edges> do not contain seams => we must reconstruct the seam up to <NextEdge> //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
gp_Pnt2d StartOfNextEdge; gp_Pnt2d StartOfNextEdge;
TopoDS_Vertex LastVertexOfSeam; TopoDS_Vertex LastVertexOfSeam;
ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex, ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
CurPoint, Uperiod, FaceUmin, CoordTol, CurPoint, Uperiod, FaceUmin, Standard_True, CoordTol,
NextEdge, aNewWire, NextPoint, NextEdge, aNewWire, NextPoint,
StartOfNextEdge, LastVertexOfSeam, VEmap); StartOfNextEdge, LastVertexOfSeam, VEmap);
@ -2821,6 +2807,23 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
break; break;
} //if (Uperiod != 0. && Abs(aPoint.X() - CurPoint.X()) > Uperiod/2) } //if (Uperiod != 0. && Abs(aPoint.X() - CurPoint.X()) > Uperiod/2)
else if (Vperiod != 0. && DiffV > Vperiod/2) //end of parametric space
{
//<edges> do not contain seams => we must reconstruct the seam up to <NextEdge>
gp_Pnt2d StartOfNextEdge;
TopoDS_Vertex LastVertexOfSeam;
ReconstructMissedSeam(edges, RemovedEdges, UsedEdges, F_RefFace, CurVertex,
CurPoint, Vperiod, FaceVmin, Standard_False, CoordTol,
NextEdge, aNewWire, NextPoint,
StartOfNextEdge, LastVertexOfSeam, VEmap);
//Check: may be it is the end
if (LastVertexOfSeam.IsSame(StartVertex) &&
Abs(StartPoint.Y() - StartOfNextEdge.Y()) < Vperiod/2)
EndOfWire = Standard_True;
break;
}
else else
{ {
NextEdge = anEdge; NextEdge = anEdge;

View File

@ -27,6 +27,8 @@
#include <TopTools_DataMapOfShapeShape.hxx> #include <TopTools_DataMapOfShapeShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_MapOfShape.hxx> #include <TopTools_MapOfShape.hxx>
#include <Geom_Plane.hxx>
#include <Precision.hxx>
class ShapeBuild_ReShape; class ShapeBuild_ReShape;
class TopoDS_Shape; class TopoDS_Shape;
@ -66,6 +68,9 @@ class ShapeUpgrade_UnifySameDomain : public Standard_Transient
{ {
public: public:
typedef NCollection_DataMap<TopoDS_Shape, Handle(Geom_Plane), TopTools_ShapeMapHasher> DataMapOfFacePlane;
//! Empty constructor //! Empty constructor
Standard_EXPORT ShapeUpgrade_UnifySameDomain(); Standard_EXPORT ShapeUpgrade_UnifySameDomain();
@ -177,6 +182,7 @@ private:
TopoDS_Shape myShape; TopoDS_Shape myShape;
Handle(ShapeBuild_ReShape) myContext; Handle(ShapeBuild_ReShape) myContext;
TopTools_MapOfShape myKeepShapes; TopTools_MapOfShape myKeepShapes;
DataMapOfFacePlane myFacePlaneMap;
Handle(BRepTools_History) myHistory; //!< The history. Handle(BRepTools_History) myHistory; //!< The history.
}; };

View File

@ -7,7 +7,7 @@ restore [locate_data_file bug30185.brep] s
unifysamedom r s +b unifysamedom r s +b
checkshape r checkshape r
checknbshapes r -vertex 54 -edge 78 -face 24 checknbshapes r -vertex 50 -edge 71 -face 21
checkmaxtol r -min_tol 2.49130e-03 checkmaxtol r -min_tol 2.49130e-03
checkmaxtol s -min_tol 2.49130e-03 checkmaxtol s -min_tol 2.49130e-03

View File

@ -0,0 +1,17 @@
puts "=================================================================================="
puts "OCC31736: ShapeUpgrade_UnifySameDomain algorithm does not unify all possible faces"
puts "=================================================================================="
puts ""
restore [locate_data_file bug31736_1.brep] a
unifysamedom result a
checkshape result
checknbshapes result -vertex 18 -edge 26 -wire 9 -face 9 -shell 1 -solid 1
set tolres [checkmaxtol result]
if { ${tolres} > 0.5} {
puts "Error: bad tolerance of result"
}

View File

@ -0,0 +1,17 @@
puts "=================================================================================="
puts "OCC31736: ShapeUpgrade_UnifySameDomain algorithm does not unify all possible faces"
puts "=================================================================================="
puts ""
restore [locate_data_file bug31736_2.brep] a
unifysamedom result a
checkshape result
checknbshapes result -vertex 17 -edge 24 -wire 9 -face 9 -shell 1 -solid 1
set tolres [checkmaxtol result]
if { ${tolres} > 0.5} {
puts "Error: bad tolerance of result"
}