1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-06 18:26:22 +03:00

0026440: Invalid shape as a result of solid construction in BRepOffset_MakeOffset

Fixed degeneration in wall building in thicksolid mode.

Minor correction.

Test cases for issue CR26440
This commit is contained in:
aml 2015-09-03 14:40:03 +03:00 committed by bugmaster
parent d18c1ac06e
commit a8704c363d
5 changed files with 509 additions and 348 deletions

View File

@ -109,6 +109,8 @@
#include <TopTools_MapIteratorOfMapOfShape.hxx> #include <TopTools_MapIteratorOfMapOfShape.hxx>
#include <TopTools_MapOfShape.hxx> #include <TopTools_MapOfShape.hxx>
#include <TopTools_SequenceOfShape.hxx> #include <TopTools_SequenceOfShape.hxx>
#include <BRepBuilderAPI_Sewing.hxx>
#include <Geom_Line.hxx>
#include <stdio.h> #include <stdio.h>
// POP for NT // POP for NT
@ -524,6 +526,7 @@ void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape& S,
myJoin = Join; myJoin = Join;
myThickening = Thickening; myThickening = Thickening;
myDone = Standard_False; myDone = Standard_False;
myIsPerformSewing = Standard_False;
Clear(); Clear();
} }
@ -659,6 +662,7 @@ static void EvalMax(const TopoDS_Shape& S, Standard_Real& Tol)
} }
} }
//======================================================================= //=======================================================================
//function : MakeOffsetShape //function : MakeOffsetShape
//purpose : //purpose :
@ -778,6 +782,21 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
CorrectConicalFaces(); CorrectConicalFaces();
// Result solid should be computed in MakeOffset scope.
if (myThickening &&
myIsPerformSewing)
{
BRepBuilderAPI_Sewing aSew(myTol);
aSew.Add(myOffsetShape);
aSew.Perform();
myOffsetShape = aSew.SewedShape();
// Rebuild solid.
// Offset shape expected to be really closed after sewing.
myOffsetShape.Closed(Standard_True);
MakeSolid();
}
myDone = Standard_True; myDone = Standard_True;
} }
@ -2491,7 +2510,6 @@ static void UpdateInitOffset (BRepAlgo_Image& myInitOffset,
//function : MakeMissingWalls //function : MakeMissingWalls
//purpose : //purpose :
//======================================================================= //=======================================================================
void BRepOffset_MakeOffset::MakeMissingWalls () void BRepOffset_MakeOffset::MakeMissingWalls ()
{ {
TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary) TopTools_DataMapOfShapeListOfShape Contours; //Start vertex + list of connected edges (free boundary)
@ -2502,361 +2520,416 @@ void BRepOffset_MakeOffset::MakeMissingWalls ()
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours); TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter(Contours);
for (; iter.More(); iter.Next()) for (; iter.More(); iter.Next())
{
TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key());
TopoDS_Edge StartEdge;
const TopTools_ListOfShape& aContour = iter.Value();
TopTools_ListIteratorOfListOfShape itl(aContour);
Standard_Boolean FirstStep = Standard_True;
TopoDS_Edge PrevEdge;
TopoDS_Vertex PrevVertex = StartVertex;
Standard_Boolean isBuildFromScratch = Standard_False; // Problems with edges.
for (; itl.More(); itl.Next())
{ {
TopoDS_Vertex StartVertex = TopoDS::Vertex(iter.Key()); TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
TopoDS_Edge StartEdge;
const TopTools_ListOfShape& aContour = iter.Value(); // Check for offset existence.
TopTools_ListIteratorOfListOfShape itl(aContour); if (!myInitOffsetEdge.HasImage(anEdge))
Standard_Boolean FirstStep = Standard_True; continue;
TopoDS_Edge PrevEdge;
TopoDS_Vertex PrevVertex = StartVertex; // Check for existence of two different vertices.
for (; itl.More(); itl.Next()) TopTools_ListOfShape LOE, LOE2;
{ myInitOffsetEdge.LastImage( anEdge, LOE );
TopoDS_Edge anEdge = TopoDS::Edge(itl.Value()); myImageOffset.LastImage( LOE.Last(), LOE2 );
if (!myInitOffsetEdge.HasImage(anEdge)) TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() );
continue; TopoDS_Vertex V1, V2, V3, V4;
//if (BRep_Tool::Degenerated(anEdge)) TopExp::Vertices(OE, V4, V3);
//continue; TopExp::Vertices(anEdge, V1, V2);
TopoDS_Face aFace = TopoDS::Face(MapEF(anEdge)); Standard_Real aF, aL;
//TopoDS_Edge OE = TopoDS::Edge(myInitOffsetEdge.Image(anEdge).First()); const Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aF, aL);
TopTools_ListOfShape LOE, LOE2; if (!aC.IsNull() &&
myInitOffsetEdge.LastImage( anEdge, LOE ); (!aC->IsClosed() && !aC->IsPeriodic()))
myImageOffset.LastImage( LOE.Last(), LOE2 ); {
TopoDS_Edge OE = TopoDS::Edge( LOE2.Last() ); gp_Pnt aPntF = BRep_Tool::Pnt(V1);
//////////////////////////////////////////////////////////////////////// gp_Pnt aPntL = BRep_Tool::Pnt(V2);
TopoDS_Vertex V1, V2, V3, V4; Standard_Real aDistE = aPntF.SquareDistance(aPntL);
TopExp::Vertices(anEdge, V1, V2/*, Standard_True*/); if ( aDistE < Precision::SquareConfusion())
TopExp::Vertices(OE, V4, V3/*, Standard_True*/); {
Standard_Boolean ToReverse = Standard_False; // Bad case: non closed, but vertexes mapped to same 3d point.
if (!V1.IsSame(PrevVertex)) continue;
{ }
TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
aVtx = V3; V3 = V4; V4 = aVtx; Standard_Real anEdgeTol = BRep_Tool::Tolerance(anEdge);
ToReverse = Standard_True; if (aDistE < anEdgeTol)
} {
//Temporary // Potential problems not detected via checkshape.
//anEdge.Reverse(); gp_Pnt aPntOF = BRep_Tool::Pnt(V4);
OE.Orientation(TopAbs::Reverse(anEdge.Orientation())); gp_Pnt aPntOL = BRep_Tool::Pnt(V3);
TopoDS_Edge E3, E4; if (aPntOF.SquareDistance(aPntOL) > gp::Resolution())
if (FirstStep)
{
E4 = BRepLib_MakeEdge( V1, V4 );
StartEdge = E4;
}
else
E4 = PrevEdge;
Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
if (V2.IsSame(StartVertex) && !ArcOnV2)
E3 = StartEdge;
else
E3 = BRepLib_MakeEdge( V2, V3 );
E4.Reverse();
TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
BRep_Builder BB;
TopoDS_Wire theWire;
BB.MakeWire(theWire);
if (ToReverse)
{
BB.Add(theWire, anEdge.Reversed());
BB.Add(theWire, E3.Reversed());
BB.Add(theWire, OE.Reversed());
BB.Add(theWire, E4.Reversed());
}
else
{
BB.Add(theWire, anEdge);
BB.Add(theWire, E3);
BB.Add(theWire, OE);
BB.Add(theWire, E4);
}
BRepLib::BuildCurves3d( theWire, myTol );
theWire.Closed(Standard_True);
TopoDS_Face NewFace;
Handle(Geom_Surface) theSurf;
BRepAdaptor_Curve BAcurve(anEdge);
BRepAdaptor_Curve BAcurveOE(OE);
Standard_Real fpar = BAcurve.FirstParameter();
Standard_Real lpar = BAcurve.LastParameter();
gp_Pnt PonE = BAcurve.Value(fpar);
gp_Pnt PonOE = BAcurveOE.Value(fpar);
gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
Standard_Boolean IsPlanar = Standard_False;
if (BAcurve.GetType() == GeomAbs_Circle &&
BAcurveOE.GetType() == GeomAbs_Circle)
{ {
gp_Circ aCirc = BAcurve.Circle(); // To avoid computation of complex analytical continuation of Sin / ArcSin.
gp_Circ aCircOE = BAcurveOE.Circle(); Standard_Real aSinValue = Min(2 * anEdgeTol / aPntOF.Distance(aPntOL), 1.0);
gp_Lin anAxisLine(aCirc.Axis()); Standard_Real aMaxAngle = Min(Abs(ASin(aSinValue)), M_PI_4); // Maximal angle.
gp_Dir CircAxisDir = aCirc.Axis().Direction(); Standard_Real aCurrentAngle = gp_Vec(aPntF, aPntL).Angle(gp_Vec(aPntOF, aPntOL));
if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) && if (aC->IsKind(STANDARD_TYPE(Geom_Line)) &&
anAxisLine.Contains(aCircOE.Location(), Precision::Confusion())) Abs (aCurrentAngle) > aMaxAngle)
{ //cylinder, plane or cone {
if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder // anEdge not collinear to offset edge.
theSurf = GC_MakeCylindricalSurface(aCirc).Value(); isBuildFromScratch = Standard_True;
else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane myIsPerformSewing = Standard_True;
IsPlanar = Standard_True; continue;
}
}
}
}
Standard_Boolean ToReverse = Standard_False;
if (!V1.IsSame(PrevVertex))
{
TopoDS_Vertex aVtx = V1; V1 = V2; V2 = aVtx;
aVtx = V3; V3 = V4; V4 = aVtx;
ToReverse = Standard_True;
}
OE.Orientation(TopAbs::Reverse(anEdge.Orientation()));
TopoDS_Edge E3, E4;
Standard_Boolean ArcOnV2 = ((myJoin == GeomAbs_Arc) && (myInitOffsetEdge.HasImage(V2)));
if (FirstStep || isBuildFromScratch)
{
E4 = BRepLib_MakeEdge( V1, V4 );
if (FirstStep)
StartEdge = E4;
}
else
E4 = PrevEdge;
if (V2.IsSame(StartVertex) && !ArcOnV2)
E3 = StartEdge;
else
E3 = BRepLib_MakeEdge( V2, V3 );
E4.Reverse();
if (isBuildFromScratch)
{
E3.Reverse();
E4.Reverse();
}
TopoDS_Shape localAnEdge = anEdge.Oriented(TopAbs_FORWARD);
const TopoDS_Edge& anEdgeFWD = TopoDS::Edge(localAnEdge);
Standard_Real ParV1 = BRep_Tool::Parameter(V1, anEdgeFWD);
Standard_Real ParV2 = BRep_Tool::Parameter(V2, anEdgeFWD);
BRep_Builder BB;
TopoDS_Wire theWire;
BB.MakeWire(theWire);
if (ToReverse)
{
BB.Add(theWire, anEdge.Reversed());
BB.Add(theWire, E3.Reversed());
BB.Add(theWire, OE.Reversed());
BB.Add(theWire, E4.Reversed());
}
else
{
BB.Add(theWire, anEdge);
BB.Add(theWire, E3);
BB.Add(theWire, OE);
BB.Add(theWire, E4);
}
BRepLib::BuildCurves3d( theWire, myTol );
theWire.Closed(Standard_True);
TopoDS_Face NewFace;
Handle(Geom_Surface) theSurf;
BRepAdaptor_Curve BAcurve(anEdge);
BRepAdaptor_Curve BAcurveOE(OE);
Standard_Real fpar = BAcurve.FirstParameter();
Standard_Real lpar = BAcurve.LastParameter();
gp_Pnt PonE = BAcurve.Value(fpar);
gp_Pnt PonOE = BAcurveOE.Value(fpar);
gp_Dir OffsetDir = gce_MakeDir( PonE, PonOE );
Handle(Geom2d_Line) EdgeLine2d, OELine2d, aLine2d, aLine2d2;
Standard_Boolean IsPlanar = Standard_False;
if (BAcurve.GetType() == GeomAbs_Circle &&
BAcurveOE.GetType() == GeomAbs_Circle)
{
gp_Circ aCirc = BAcurve.Circle();
gp_Circ aCircOE = BAcurveOE.Circle();
gp_Lin anAxisLine(aCirc.Axis());
gp_Dir CircAxisDir = aCirc.Axis().Direction();
if (aCirc.Axis().IsParallel(aCircOE.Axis(), Precision::Confusion()) &&
anAxisLine.Contains(aCircOE.Location(), Precision::Confusion()))
{ //cylinder, plane or cone
if (Abs(aCirc.Radius() - aCircOE.Radius()) <= Precision::Confusion()) //case of cylinder
theSurf = GC_MakeCylindricalSurface(aCirc).Value();
else if (aCirc.Location().Distance(aCircOE.Location()) <= Precision::Confusion()) {//case of plane
IsPlanar = Standard_True;
//
gp_Pnt PonEL = BAcurve.Value(lpar);
if (PonEL.Distance(PonE) <= Precision::PConfusion()) {
Standard_Boolean bIsHole;
TopoDS_Edge aE1, aE2;
TopoDS_Wire aW1, aW2;
Handle(Geom_Plane) aPL;
IntTools_FClass2d aClsf;
//
if (aCirc.Radius()>aCircOE.Radius()) {
aE1 = anEdge;
aE2 = OE;
} else {
aE1 = OE;
aE2 = anEdge;
}
//
BB.MakeWire(aW1);
BB.Add(aW1, aE1);
BB.MakeWire(aW2);
BB.Add(aW2, aE2);
//
aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
for (Standard_Integer i = 0; i < 2; ++i) {
TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
// //
gp_Pnt PonEL = BAcurve.Value(lpar); TopoDS_Face aFace;
if (PonEL.Distance(PonE) <= Precision::PConfusion()) { BB.MakeFace(aFace, aPL, Precision::Confusion());
Standard_Boolean bIsHole; BB.Add (aFace, aW);
TopoDS_Edge aE1, aE2; aClsf.Init(aFace, Precision::Confusion());
TopoDS_Wire aW1, aW2; bIsHole=aClsf.IsHole();
Handle(Geom_Plane) aPL; if ((bIsHole && !i) || (!bIsHole && i)) {
IntTools_FClass2d aClsf; aW.Nullify();
// BB.MakeWire(aW);
if (aCirc.Radius()>aCircOE.Radius()) { BB.Add(aW, aE.Reversed());
aE1 = anEdge;
aE2 = OE;
} else {
aE1 = OE;
aE2 = anEdge;
}
//
BB.MakeWire(aW1);
BB.Add(aW1, aE1);
BB.MakeWire(aW2);
BB.Add(aW2, aE2);
//
aPL = new Geom_Plane(aCirc.Location(), CircAxisDir);
for (Standard_Integer i = 0; i < 2; ++i) {
TopoDS_Wire& aW = (i==0) ? aW1 : aW2;
TopoDS_Edge& aE = (i==0) ? aE1 : aE2;
//
TopoDS_Face aFace;
BB.MakeFace(aFace, aPL, Precision::Confusion());
BB.Add (aFace, aW);
aClsf.Init(aFace, Precision::Confusion());
bIsHole=aClsf.IsHole();
if ((bIsHole && !i) || (!bIsHole && i)) {
aW.Nullify();
BB.MakeWire(aW);
BB.Add(aW, aE.Reversed());
}
}
//
BB.MakeFace(NewFace, aPL, Precision::Confusion());
BB.Add(NewFace, aW1);
BB.Add(NewFace, aW2);
} }
} }
else //case of cone //
BB.MakeFace(NewFace, aPL, Precision::Confusion());
BB.Add(NewFace, aW1);
BB.Add(NewFace, aW2);
}
}
else //case of cone
{
gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(),
aCirc.Radius(), aCircOE.Radius());
gp_Ax3 theAx3(aCirc.Position());
if (CircAxisDir * theCone.Axis().Direction() < 0.)
{
theAx3.ZReverse();
CircAxisDir.Reverse();
}
theCone.SetPosition(theAx3);
theSurf = new Geom_ConicalSurface(theCone);
}
if (!IsPlanar) {
TopLoc_Location Loc;
EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.));
BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.;
OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.));
BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
aLine2d = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff));
aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff));
if (E3.IsSame(E4))
{
if (Coeff > 0.)
BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
else
{ {
gp_Cone theCone = gce_MakeCone(aCirc.Location(), aCircOE.Location(), BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion());
aCirc.Radius(), aCircOE.Radius()); theWire.Nullify();
gp_Ax3 theAx3(aCirc.Position()); BB.MakeWire(theWire);
if (CircAxisDir * theCone.Axis().Direction() < 0.) BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED));
{ BB.Add(theWire, E4);
theAx3.ZReverse(); BB.Add(theWire, OE.Oriented(TopAbs_FORWARD));
CircAxisDir.Reverse(); BB.Add(theWire, E3);
} theWire.Closed(Standard_True);
theCone.SetPosition(theAx3);
theSurf = new Geom_ConicalSurface(theCone);
} }
if (!IsPlanar) { }
TopLoc_Location Loc; else
EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., 0.), gp_Dir2d(1., 0.)); {
BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion()); BB.SameParameter(E3, Standard_False);
Standard_Real Coeff = (OffsetDir * CircAxisDir > 0.)? 1. : -1.; BB.SameRange(E3, Standard_False);
OELine2d = new Geom2d_Line(gp_Pnt2d(0., OffsetVal*Coeff), gp_Dir2d(1., 0.)); BB.SameParameter(E4, Standard_False);
BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion()); BB.SameRange(E4, Standard_False);
aLine2d = new Geom2d_Line(gp_Pnt2d(ParV2, 0.), gp_Dir2d(0., Coeff)); BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
aLine2d2 = new Geom2d_Line(gp_Pnt2d(ParV1, 0.), gp_Dir2d(0., Coeff)); BB.Range(E3, theSurf, Loc, 0., OffsetVal);
if (E3.IsSame(E4)) BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
{ BB.Range(E4, theSurf, Loc, 0., OffsetVal);
if (Coeff > 0.) }
BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion()); NewFace = BRepLib_MakeFace(theSurf, theWire);
else }
{ } //cylinder or cone
BB.UpdateEdge(E3, aLine2d2, aLine2d, theSurf, Loc, Precision::Confusion()); } //if both edges are arcs of circles
theWire.Nullify(); if (NewFace.IsNull())
BB.MakeWire(theWire); {
BB.Add(theWire, anEdge.Oriented(TopAbs_REVERSED)); BRepLib_MakeFace MF(theWire, Standard_True); //Only plane
BB.Add(theWire, E4); if (MF.Error() == BRepLib_FaceDone)
BB.Add(theWire, OE.Oriented(TopAbs_FORWARD)); {
BB.Add(theWire, E3); NewFace = MF.Face();
theWire.Closed(Standard_True); IsPlanar = Standard_True;
} }
} else //Extrusion (by thrusections)
else {
{ Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
BB.SameParameter(E3, Standard_False); Handle(Geom_TrimmedCurve) TrEdgeCurve =
BB.SameRange(E3, Standard_False); new Geom_TrimmedCurve( EdgeCurve, fpar, lpar );
BB.SameParameter(E4, Standard_False); Standard_Real fparOE, lparOE;
BB.SameRange(E4, Standard_False); Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE);
BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion()); Handle(Geom_TrimmedCurve) TrOffsetCurve =
BB.Range(E3, theSurf, Loc, 0., OffsetVal); new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE );
BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion()); GeomFill_Generator ThrusecGenerator;
BB.Range(E4, theSurf, Loc, 0., OffsetVal); ThrusecGenerator.AddCurve( TrEdgeCurve );
} ThrusecGenerator.AddCurve( TrOffsetCurve );
NewFace = BRepLib_MakeFace(theSurf, theWire); ThrusecGenerator.Perform( Precision::PConfusion() );
} theSurf = ThrusecGenerator.Surface();
} //cylinder or cone //theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir );
} //if both edges are arcs of circles Standard_Real Uf, Ul, Vf, Vl;
if (NewFace.IsNull()) theSurf->Bounds(Uf, Ul, Vf, Vl);
{ TopLoc_Location Loc;
BRepLib_MakeFace MF(theWire, Standard_True); //Only plane EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.));
if (MF.Error() == BRepLib_FaceDone) BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion());
{ OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.));
NewFace = MF.Face(); BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion());
IsPlanar = Standard_True; Standard_Real UonV1 = (ToReverse)? Ul : Uf;
} Standard_Real UonV2 = (ToReverse)? Uf : Ul;
else //Extrusion (by thrusections) aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.));
{ aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.));
Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(anEdge, fpar, lpar); if (E3.IsSame(E4))
Handle(Geom_TrimmedCurve) TrEdgeCurve = {
new Geom_TrimmedCurve( EdgeCurve, fpar, lpar ); BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion());
Standard_Real fparOE, lparOE; Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf );
Handle(Geom_Curve) OffsetCurve = BRep_Tool::Curve(OE, fparOE, lparOE); BB.UpdateEdge(E3, BSplC34, Precision::Confusion());
Handle(Geom_TrimmedCurve) TrOffsetCurve = BB.Range(E3, Vf, Vl);
new Geom_TrimmedCurve( OffsetCurve, fparOE, lparOE ); }
GeomFill_Generator ThrusecGenerator; else
ThrusecGenerator.AddCurve( TrEdgeCurve ); {
ThrusecGenerator.AddCurve( TrOffsetCurve ); BB.SameParameter(E3, Standard_False);
ThrusecGenerator.Perform( Precision::PConfusion() ); BB.SameRange(E3, Standard_False);
theSurf = ThrusecGenerator.Surface(); BB.SameParameter(E4, Standard_False);
//theSurf = new Geom_SurfaceOfLinearExtrusion( TrOffsetCurve, OffsetDir ); BB.SameRange(E4, Standard_False);
Standard_Real Uf, Ul, Vf, Vl; BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion());
theSurf->Bounds(Uf, Ul, Vf, Vl); BB.Range(E3, theSurf, Loc, Vf, Vl);
TopLoc_Location Loc; BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion());
EdgeLine2d = new Geom2d_Line(gp_Pnt2d(0., Vf), gp_Dir2d(1., 0.)); BB.Range(E4, theSurf, Loc, Vf, Vl);
BB.UpdateEdge(anEdge, EdgeLine2d, theSurf, Loc, Precision::Confusion()); Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 );
OELine2d = new Geom2d_Line(gp_Pnt2d(0., Vl), gp_Dir2d(1., 0.)); BB.UpdateEdge(E3, BSplC3, Precision::Confusion());
BB.UpdateEdge(OE, OELine2d, theSurf, Loc, Precision::Confusion()); BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve
Standard_Real UonV1 = (ToReverse)? Ul : Uf; Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 );
Standard_Real UonV2 = (ToReverse)? Uf : Ul; BB.UpdateEdge(E4, BSplC4, Precision::Confusion());
aLine2d = new Geom2d_Line(gp_Pnt2d(UonV2, 0.), gp_Dir2d(0., 1.)); BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve
aLine2d2 = new Geom2d_Line(gp_Pnt2d(UonV1, 0.), gp_Dir2d(0., 1.)); }
if (E3.IsSame(E4)) NewFace = BRepLib_MakeFace(theSurf, theWire);
{ }
BB.UpdateEdge(E3, aLine2d, aLine2d2, theSurf, Loc, Precision::Confusion()); }
Handle(Geom_Curve) BSplC34 = theSurf->UIso( Uf ); if (!IsPlanar)
BB.UpdateEdge(E3, BSplC34, Precision::Confusion()); {
BB.Range(E3, Vf, Vl); Standard_Real fparOE = BAcurveOE.FirstParameter();
} Standard_Real lparOE = BAcurveOE.LastParameter();
else TopLoc_Location Loc;
{ if (Abs(fpar - fparOE) > Precision::Confusion())
BB.SameParameter(E3, Standard_False); {
BB.SameRange(E3, Standard_False); const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4;
BB.SameParameter(E4, Standard_False); gp_Pnt2d fp2d = EdgeLine2d->Value(fpar);
BB.SameRange(E4, Standard_False); gp_Pnt2d fp2dOE = OELine2d->Value(fparOE);
BB.UpdateEdge(E3, aLine2d, theSurf, Loc, Precision::Confusion()); aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value();
BB.Range(E3, theSurf, Loc, Vf, Vl); Handle(Geom_Curve) aCurve;
BB.UpdateEdge(E4, aLine2d2, theSurf, Loc, Precision::Confusion()); Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE);
BB.Range(E4, theSurf, Loc, Vf, Vl); Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar );
Handle(Geom_Curve) BSplC3 = theSurf->UIso( UonV2 ); GeomAdaptor_Surface GAsurf( theSurf );
BB.UpdateEdge(E3, BSplC3, Precision::Confusion()); Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d );
BB.Range(E3, Vf, Vl, Standard_True); //only for 3d curve Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
Handle(Geom_Curve) BSplC4 = theSurf->UIso( UonV1 ); Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
BB.UpdateEdge(E4, BSplC4, Precision::Confusion()); Standard_Real max_deviation = 0., average_deviation;
BB.Range(E4, Vf, Vl, Standard_True); //only for 3d curve GeomLib::BuildCurve3d(Precision::Confusion(),
} ConS, FirstPar, LastPar,
NewFace = BRepLib_MakeFace(theSurf, theWire); aCurve, max_deviation, average_deviation);
} BB.UpdateEdge( anE4, aCurve, max_deviation );
} BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation );
if (!IsPlanar) BB.Range( anE4, FirstPar, LastPar );
{ }
Standard_Real fparOE = BAcurveOE.FirstParameter(); if (Abs(lpar - lparOE) > Precision::Confusion())
Standard_Real lparOE = BAcurveOE.LastParameter(); {
TopLoc_Location Loc; const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3;
if (Abs(fpar - fparOE) > Precision::Confusion()) gp_Pnt2d lp2d = EdgeLine2d->Value(lpar);
{ gp_Pnt2d lp2dOE = OELine2d->Value(lparOE);
const TopoDS_Edge& anE4 = (ToReverse)? E3 : E4; aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value();
gp_Pnt2d fp2d = EdgeLine2d->Value(fpar); Handle(Geom_Curve) aCurve;
gp_Pnt2d fp2dOE = OELine2d->Value(fparOE); Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE);
aLine2d2 = GCE2d_MakeLine( fp2d, fp2dOE ).Value(); Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar );
Handle(Geom_Curve) aCurve; GeomAdaptor_Surface GAsurf( theSurf );
Standard_Real FirstPar = 0., LastPar = fp2d.Distance(fp2dOE); Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d );
Geom2dAdaptor_Curve AC2d( aLine2d2, FirstPar, LastPar ); Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
GeomAdaptor_Surface GAsurf( theSurf ); Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d ); Standard_Real max_deviation = 0., average_deviation;
Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf ); GeomLib::BuildCurve3d(Precision::Confusion(),
Adaptor3d_CurveOnSurface ConS( HC2d, HSurf ); ConS, FirstPar, LastPar,
Standard_Real max_deviation = 0., average_deviation; aCurve, max_deviation, average_deviation);
GeomLib::BuildCurve3d(Precision::Confusion(), BB.UpdateEdge( anE3, aCurve, max_deviation );
ConS, FirstPar, LastPar, BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation );
aCurve, max_deviation, average_deviation); BB.Range( anE3, FirstPar, LastPar );
BB.UpdateEdge( anE4, aCurve, max_deviation ); }
BB.UpdateEdge( anE4, aLine2d2, theSurf, Loc, max_deviation ); }
BB.Range( anE4, FirstPar, LastPar ); BRepLib::SameParameter(NewFace);
} BRepTools::Update(NewFace);
if (Abs(lpar - lparOE) > Precision::Confusion()) myWalls.Append(NewFace);
{ if (ArcOnV2)
const TopoDS_Edge& anE3 = (ToReverse)? E4 : E3; {
gp_Pnt2d lp2d = EdgeLine2d->Value(lpar); TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First());
gp_Pnt2d lp2dOE = OELine2d->Value(lparOE); TopoDS_Vertex arcV1, arcV2;
aLine2d = GCE2d_MakeLine( lp2d, lp2dOE ).Value(); TopExp::Vertices(anArc, arcV1, arcV2);
Handle(Geom_Curve) aCurve; Standard_Boolean ArcReverse = Standard_False;
Standard_Real FirstPar = 0., LastPar = lp2d.Distance(lp2dOE); if (!arcV1.IsSame(V3))
Geom2dAdaptor_Curve AC2d( aLine2d, FirstPar, LastPar ); {
GeomAdaptor_Surface GAsurf( theSurf ); TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx;
Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d ); ArcReverse = Standard_True;
Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf ); }
Adaptor3d_CurveOnSurface ConS( HC2d, HSurf ); TopoDS_Edge EA1, EA2;
Standard_Real max_deviation = 0., average_deviation; //EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed());
GeomLib::BuildCurve3d(Precision::Confusion(), EA1 = E3;
ConS, FirstPar, LastPar, EA1.Reverse();
aCurve, max_deviation, average_deviation); if (ToReverse)
BB.UpdateEdge( anE3, aCurve, max_deviation ); EA1.Reverse();
BB.UpdateEdge( anE3, aLine2d, theSurf, Loc, max_deviation ); //////////////////////////////////////////////////////
BB.Range( anE3, FirstPar, LastPar ); if (V2.IsSame(StartVertex))
} EA2 = StartEdge;
} else
BRepLib::SameParameter(NewFace); EA2 = BRepLib_MakeEdge( V2, arcV2 );
BRepTools::Update(NewFace); anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) );
myWalls.Append(NewFace); if (EA1.Orientation() == TopAbs_REVERSED)
if (ArcOnV2) anArc.Reverse();
{ EA2.Orientation(TopAbs::Reverse(EA1.Orientation()));
TopoDS_Edge anArc = TopoDS::Edge(myInitOffsetEdge.Image(V2).First()); TopoDS_Wire arcWire;
TopoDS_Vertex arcV1, arcV2; BB.MakeWire(arcWire);
TopExp::Vertices(anArc, arcV1, arcV2); BB.Add(arcWire, EA1);
Standard_Boolean ArcReverse = Standard_False; BB.Add(arcWire, anArc);
if (!arcV1.IsSame(V3)) BB.Add(arcWire, EA2);
{ BRepLib::BuildCurves3d( arcWire, myTol );
TopoDS_Vertex aVtx = arcV1; arcV1 = arcV2; arcV2 = aVtx; arcWire.Closed(Standard_True);
ArcReverse = Standard_True; TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
} BRepTools::Update(arcFace);
TopoDS_Edge EA1, EA2; myWalls.Append(arcFace);
//EA1 = (ToReverse)? E3 : TopoDS::Edge(E3.Reversed()); TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
EA1 = E3; const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
EA1.Reverse(); PrevEdge = CEA2;
if (ToReverse) PrevVertex = V2;
EA1.Reverse(); }
////////////////////////////////////////////////////// else
if (V2.IsSame(StartVertex)) {
EA2 = StartEdge; if (isBuildFromScratch)
else {
EA2 = BRepLib_MakeEdge( V2, arcV2 ); PrevEdge = TopoDS::Edge(E4);
anArc.Orientation( ((ArcReverse)? TopAbs_REVERSED : TopAbs_FORWARD) ); PrevVertex = V1;
if (EA1.Orientation() == TopAbs_REVERSED) isBuildFromScratch = Standard_False;
anArc.Reverse(); }
EA2.Orientation(TopAbs::Reverse(EA1.Orientation())); else
TopoDS_Wire arcWire; {
BB.MakeWire(arcWire); PrevEdge = E3;
BB.Add(arcWire, EA1); PrevVertex = V2;
BB.Add(arcWire, anArc); }
BB.Add(arcWire, EA2); }
BRepLib::BuildCurves3d( arcWire, myTol ); FirstStep = Standard_False;
arcWire.Closed(Standard_True);
TopoDS_Face arcFace = BRepLib_MakeFace(arcWire, Standard_True);
BRepTools::Update(arcFace);
myWalls.Append(arcFace);
TopoDS_Shape localEA2 = EA2.Oriented(TopAbs_FORWARD);
const TopoDS_Edge& CEA2 = TopoDS::Edge(localEA2);
PrevEdge = CEA2;
PrevVertex = V2;
}
else
{
PrevEdge = E3;
PrevVertex = V2;
}
FirstStep = Standard_False;
}
} }
}
} }
//======================================================================= //=======================================================================

View File

@ -161,6 +161,7 @@ private:
Standard_Boolean myDone; Standard_Boolean myDone;
BRepOffset_Error myError; BRepOffset_Error myError;
BRepOffset_MakeLoops myMakeLoops; BRepOffset_MakeLoops myMakeLoops;
Standard_Boolean myIsPerformSewing; // Handle bad walls in thicksolid mode.
}; };

29
tests/bugs/modalg_6/bug26440_1 Executable file
View File

@ -0,0 +1,29 @@
puts "============"
puts "CR26440"
puts "============"
puts ""
##########################################################################################################
# Invalid shape as a result of solid construction in BRepOffset_MakeOffset
##########################################################################################################
restore [locate_data_file bug26440_plate.brep] sh1
thickshell result sh1 160
set square 2.40831e+07
set nbshapes_expected "
Number of shapes in shape
VERTEX : 196
EDGE : 308
WIRE : 110
FACE : 110
SHELL : 1
SOLID : 1
COMPSOLID : 0
COMPOUND : 0
SHAPE : 726
"
checknbshapes result -ref ${nbshapes_expected} -t -m "solid construction"
set 3dviewer 1

29
tests/bugs/modalg_6/bug26440_2 Executable file
View File

@ -0,0 +1,29 @@
puts "============"
puts "CR26440"
puts "============"
puts ""
##########################################################################################################
# Invalid shape as a result of solid construction in BRepOffset_MakeOffset
##########################################################################################################
restore [locate_data_file bug26440_plate2.brep] sh1
thickshell result sh1 150 i
set square 5.00111e+06
set nbshapes_expected "
Number of shapes in shape
VERTEX : 146
EDGE : 225
WIRE : 75
FACE : 75
SHELL : 1
SOLID : 1
COMPSOLID : 0
COMPOUND : 0
SHAPE : 523
"
checknbshapes result -ref ${nbshapes_expected} -t -m "solid construction"
set 3dviewer 1

29
tests/bugs/modalg_6/bug26440_3 Executable file
View File

@ -0,0 +1,29 @@
puts "============"
puts "CR26440"
puts "============"
puts ""
##########################################################################################################
# Invalid shape as a result of solid construction in BRepOffset_MakeOffset
##########################################################################################################
restore [locate_data_file bug26440_plate3.brep] sh1
thickshell result sh1 160 i
set square 1.26188e+07
set nbshapes_expected "
Number of shapes in shape
VERTEX : 88
EDGE : 145
WIRE : 55
FACE : 55
SHELL : 1
SOLID : 1
COMPSOLID : 0
COMPOUND : 0
SHAPE : 345
"
checknbshapes result -ref ${nbshapes_expected} -t -m "solid construction"
set 3dviewer 1