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

0025729: algorith BRepOffset_MakeOffset(...) produces wrong result for join type Intersection

Test case for issue CR25729
This commit is contained in:
ifv 2015-02-12 12:18:56 +03:00 committed by bugmaster
parent 2c12770c38
commit b0091bc929
6 changed files with 177 additions and 91 deletions

View File

@ -45,8 +45,17 @@
#include <Precision.hxx>
#include <gp.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <Adaptor3d_Surface.hxx>
//
static void Correct2dPoint(const Adaptor3d_Surface& theS, gp_Pnt2d& theP2d);
//
static BRepOffset_Type DefineConnectType(const TopoDS_Edge& E,
const TopoDS_Face& F1,
const TopoDS_Face& F2,
const Standard_Real SinTol,
const Standard_Boolean CorrectPoint);
//
static void CorrectOrientationOfTangent(gp_Vec& TangVec,
const TopoDS_Vertex& aVertex,
const TopoDS_Edge& anEdge)
@ -55,7 +64,6 @@ static void CorrectOrientationOfTangent(gp_Vec& TangVec,
if (aVertex.IsSame(Vlast))
TangVec.Reverse();
}
//=======================================================================
//function : BRepOffset_Analyse
//purpose :
@ -85,99 +93,32 @@ BRepOffset_Analyse::BRepOffset_Analyse(const TopoDS_Shape& S,
//=======================================================================
static void EdgeAnalyse(const TopoDS_Edge& E,
const TopoDS_Face& F1,
const TopoDS_Face& F2,
const Standard_Real SinTol,
BRepOffset_ListOfInterval& LI)
const TopoDS_Face& F1,
const TopoDS_Face& F2,
const Standard_Real SinTol,
BRepOffset_ListOfInterval& LI)
{
TopLoc_Location L;
Standard_Real f,l;
Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);
Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l);
Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l);
BRepAdaptor_Curve C(E);
f = C.FirstParameter();
l = C.LastParameter();
BRep_Tool::Range(E, F1, f, l);
BRepOffset_Interval I;
I.First(f); I.Last(l);
//
// Tangent if the regularity is at least G1.
if (BRep_Tool::HasContinuity(E,F1,F2)) {
if (BRep_Tool::Continuity(E,F1,F2) > GeomAbs_C0) {
BRepOffset_Interval I;
I.First(f); I.Last(l);
I.Type(BRepOffset_Tangent);
LI.Append(I);
return;
}
}
// First stage : Type determined by one of ends.
// Calculate normals and tangents on the curves and surface.
// normals are oriented outwards.
Standard_Real ParOnC = 0.5*(f+l);
gp_Vec T1 = C.DN(ParOnC,1).Transformed(L.Transformation());
if (T1.SquareMagnitude() > gp::Resolution()) {
T1.Normalize();
}
if (BRepOffset_Tool::OriEdgeInFace(E,F1) == TopAbs_REVERSED) {
T1.Reverse();
}
if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse();
gp_Pnt2d P = C1->Value(ParOnC);
gp_Pnt P3;
gp_Vec D1U,D1V;
S1->D1(P.X(),P.Y(),P3,D1U,D1V);
gp_Vec DN1(D1U^D1V);
if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
P = C2->Value(ParOnC);
S2->D1(P.X(),P.Y(),P3,D1U,D1V);
gp_Vec DN2(D1U^D1V);
if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
DN1.Normalize();
DN2.Normalize();
gp_Vec ProVec = DN1^DN2;
Standard_Real NormProVec = ProVec.Magnitude();
BRepOffset_Interval I;
I.First(f); I.Last(l);
if (Abs(NormProVec) < SinTol) {
// plane
if (DN1.Dot(DN2) > 0) {
//Tangent
I.Type(BRepOffset_Tangent);
}
else {
//Mixed not finished!
#ifdef OCCT_DEBUG
cout <<" faces locally mixed"<<endl;
#endif
I.Type(BRepOffset_Convex);
}
}
else {
if (NormProVec > gp::Resolution())
ProVec.Normalize();
Standard_Real Prod = T1.Dot(DN1^DN2);
if (Prod > 0.) {
//
I.Type(BRepOffset_Convex);
}
else {
//reenters
I.Type(BRepOffset_Concave);
}
//
BRepOffset_Type aType = DefineConnectType(E, F1, F2, SinTol, Standard_False);
if(aType != BRepOffset_Tangent)
{
aType = DefineConnectType(E, F1, F2, SinTol, Standard_True);
}
I.Type(aType);
LI.Append(I);
}
@ -540,3 +481,130 @@ void BRepOffset_Analyse::AddFaces (const TopoDS_Face& Face,
}
}
}
//=======================================================================
//function : Correct2dPoint
//purpose :
//=======================================================================
void Correct2dPoint(const Adaptor3d_Surface& theS, gp_Pnt2d& theP2d)
{
const Standard_Real coeff = 0.01;
Standard_Real eps;
Standard_Real u1, u2, v1, v2;
if(theS.GetType() >= GeomAbs_BezierSurface)
{
u1 = theS.FirstUParameter();
u2 = theS.LastUParameter();
v1 = theS.FirstVParameter();
v2 = theS.LastVParameter();
if(!(Precision::IsInfinite(u1) || Precision::IsInfinite(u2)))
{
eps = Max(coeff*(u2-u1), Precision::PConfusion());
if(Abs(theP2d.X()-u1) < eps)
{
theP2d.SetX(u1 + eps);
}
if(Abs(theP2d.X()-u2) < eps)
{
theP2d.SetX(u2 - eps);
}
}
if(!(Precision::IsInfinite(v1) || Precision::IsInfinite(v2)))
{
eps = Max(coeff*(v2-v1), Precision::PConfusion());
if(Abs(theP2d.Y()-v1) < eps)
{
theP2d.SetY(v1 + eps);
}
if(Abs(theP2d.Y()-v2) < eps)
{
theP2d.SetY(v2 - eps);
}
}
}
}
//=======================================================================
//function : DefineConnectType
//purpose :
//=======================================================================
BRepOffset_Type DefineConnectType(const TopoDS_Edge& E,
const TopoDS_Face& F1,
const TopoDS_Face& F2,
const Standard_Real SinTol,
const Standard_Boolean CorrectPoint)
{
TopLoc_Location L;
Standard_Real f,l;
BRepAdaptor_Surface S1(F1), S2(F2);
Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l);
Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l);
BRepAdaptor_Curve C(E);
f = C.FirstParameter();
l = C.LastParameter();
//
Standard_Real ParOnC = 0.5*(f+l);
gp_Vec T1 = C.DN(ParOnC,1).Transformed(L.Transformation());
if (T1.SquareMagnitude() > gp::Resolution()) {
T1.Normalize();
}
if (BRepOffset_Tool::OriEdgeInFace(E,F1) == TopAbs_REVERSED) {
T1.Reverse();
}
if (F1.Orientation() == TopAbs_REVERSED) T1.Reverse();
gp_Pnt2d P = C1->Value(ParOnC);
gp_Pnt P3;
gp_Vec D1U,D1V;
if(CorrectPoint)
Correct2dPoint(S1, P);
//
S1.D1(P.X(),P.Y(),P3,D1U,D1V);
gp_Vec DN1(D1U^D1V);
if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
P = C2->Value(ParOnC);
if(CorrectPoint)
Correct2dPoint(S2, P);
S2.D1(P.X(),P.Y(),P3,D1U,D1V);
gp_Vec DN2(D1U^D1V);
if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
DN1.Normalize();
DN2.Normalize();
gp_Vec ProVec = DN1^DN2;
Standard_Real NormProVec = ProVec.Magnitude();
if (Abs(NormProVec) < SinTol) {
// plane
if (DN1.Dot(DN2) > 0) {
//Tangent
return BRepOffset_Tangent;
}
else {
//Mixed not finished!
#ifdef OCCT_DEBUG
cout <<" faces locally mixed"<<endl;
#endif
return BRepOffset_Convex;
}
}
else {
if (NormProVec > gp::Resolution())
ProVec.Normalize();
Standard_Real Prod = T1.Dot(DN1^DN2);
if (Prod > 0.) {
//
return BRepOffset_Convex;
}
else {
//reenters
return BRepOffset_Concave;
}
}
}

View File

@ -83,7 +83,7 @@
#ifdef DRAW
#include <DBRep.hxx>
Standard_IMPORT extern Standard_Boolean AffichInt2d;
Standard_Boolean Inter2dAffichInt2d;
static Standard_Integer NbF2d = 0;
static Standard_Integer NbE2d = 0;
static Standard_Integer NbNewVertices = 0;
@ -245,7 +245,7 @@ static void Store (const TopoDS_Edge& E1,
}
#ifdef DRAW
if (AffichInt2d) {
if (Inter2dAffichInt2d) {
if (!OnE1 && !OnE2) {
char name[256];
sprintf(name,"VV_%d",NbNewVertices++);
@ -272,7 +272,7 @@ static void EdgeInter(const TopoDS_Face& F,
Standard_Boolean WithOri)
{
#ifdef DRAW
if (AffichInt2d) {
if (Inter2dAffichInt2d) {
char name[256];
sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
DBRep::Set(name,E1);
@ -543,7 +543,7 @@ static void RefEdgeInter(const TopoDS_Face& F,
gp_Pnt& Pref)
{
#ifdef DRAW
if (AffichInt2d) {
if (Inter2dAffichInt2d) {
char name[256];
sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
DBRep::Set(name,E1);

View File

@ -129,6 +129,9 @@
Standard_Boolean ChronBuild = Standard_False;
Standard_Integer NbAE = 0;
Standard_Integer NbAF = 0;
Standard_Integer NVP = 0;
Standard_Integer NVM = 0;
Standard_Integer NVN = 0;
static OSD_Chronometer Clock;
char name[100];

View File

@ -1405,6 +1405,7 @@ void BRepOffset_Offset::Init(const TopoDS_Vertex& Vertex,
for (it.Initialize(LEdge); it.More(); it.Next()) {
sprintf(name,"EOnSph_%d_%d",NbOFFSET,NbEdges++);
#ifdef DRAW
const TopoDS_Shape& CurE = it.Value();
DBRep::Set(name, CurE);
#endif
}

View File

@ -2342,9 +2342,6 @@ void BiTgte_Blend::ComputeShape()
BRep_Builder B;
#ifdef DRAW
Standard_Integer NbNT = 1;
#endif
// Maj of the Map of created.
// Update edges that do not change in the resulting shape

View File

@ -0,0 +1,17 @@
puts "========="
puts "OCC25729"
puts "========="
puts ""
###############################################
# algorith BRepOffset_MakeOffset(...) produces wrong result for join type Intersection
###############################################
restore [locate_data_file bug25729_source_shape.brep] s
offsetparameter 1.e-7 i i
offsetload s 0.14
offsetperform result
checkshape result
set 2dviewer 1