mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
0030913: Invalid result of Fusing slices
Refactoring of the Line-Line intersection method strengthening the parallel and coincidence criteria to allow almost parallel lines have an intersection point.
This commit is contained in:
parent
3dd193aa6d
commit
115d350e09
@ -1395,7 +1395,7 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F,
|
|||||||
if (aCT1==GeomAbs_Line && aCT2==GeomAbs_Line) {
|
if (aCT1==GeomAbs_Line && aCT2==GeomAbs_Line) {
|
||||||
// check for the two lines coincidence
|
// check for the two lines coincidence
|
||||||
Standard_Real aPAR_T, aT11, aT12, aT21, aT22, aT1m, aT2m;
|
Standard_Real aPAR_T, aT11, aT12, aT21, aT22, aT1m, aT2m;
|
||||||
Standard_Real aD2, aTolE1, aTolE2, aTol2, aDot;
|
Standard_Real aD2, aTolE1, aTolE2, aTol2;
|
||||||
gp_Lin2d aL1, aL2;
|
gp_Lin2d aL1, aL2;
|
||||||
gp_Pnt2d aP1m;
|
gp_Pnt2d aP1m;
|
||||||
//
|
//
|
||||||
@ -1423,14 +1423,10 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F,
|
|||||||
if (aT2m>aT21 && aT2m<aT22) {
|
if (aT2m>aT21 && aT2m<aT22) {
|
||||||
const gp_Dir2d& aDir1=aL1.Direction();
|
const gp_Dir2d& aDir1=aL1.Direction();
|
||||||
const gp_Dir2d& aDir2=aL2.Direction();
|
const gp_Dir2d& aDir2=aL2.Direction();
|
||||||
aDot=aDir1*aDir2;
|
if (aDir1.IsParallel (aDir2, Precision::Angular()))
|
||||||
if (aDot<0.) {
|
{
|
||||||
aDot=-aDot;
|
localok = Standard_False;
|
||||||
}
|
break;// from for (k = 0; k < 2; ++k){...
|
||||||
//
|
|
||||||
if ((1.-aDot)<5.e-11){//0.00001 rad
|
|
||||||
localok = Standard_False;
|
|
||||||
break;// from for (k = 0; k < 2; ++k){...
|
|
||||||
}
|
}
|
||||||
}//if (aT2m>aT21 && aT2m<aT22) {
|
}//if (aT2m>aT21 && aT2m<aT22) {
|
||||||
}//if (aD2<aTol2) {
|
}//if (aD2<aTol2) {
|
||||||
|
@ -837,141 +837,139 @@ void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
|
|||||||
//=======================================================================
|
//=======================================================================
|
||||||
void IntTools_EdgeEdge::ComputeLineLine()
|
void IntTools_EdgeEdge::ComputeLineLine()
|
||||||
{
|
{
|
||||||
Standard_Boolean IsParallel, IsCoincide;
|
Standard_Real aTol = myTol * myTol;
|
||||||
Standard_Real aSin, aCos, aAng, aTol;
|
|
||||||
Standard_Real aT1, aT2, aT11, aT12, aT21, aT22;
|
gp_Lin aL1 = myCurve1.Line();
|
||||||
gp_Pnt aP11, aP12;
|
gp_Lin aL2 = myCurve2.Line();
|
||||||
gp_Lin aL1, aL2;
|
|
||||||
gp_Dir aD1, aD2;
|
gp_Dir aD1 = aL1.Direction();
|
||||||
IntTools_CommonPrt aCommonPrt;
|
gp_Dir aD2 = aL2.Direction();
|
||||||
//
|
|
||||||
IsParallel = Standard_False;
|
Standard_Real anAngle = aD1.Angle (aD2);
|
||||||
IsCoincide = Standard_False;
|
Standard_Boolean IsCoincide = anAngle < Precision::Angular();
|
||||||
aTol = myTol*myTol;
|
if (IsCoincide)
|
||||||
aL1 = myCurve1.Line();
|
|
||||||
aL2 = myCurve2.Line();
|
|
||||||
aD1 = aL1.Position().Direction();
|
|
||||||
aD2 = aL2.Position().Direction();
|
|
||||||
myRange1.Range(aT11, aT12);
|
|
||||||
myRange2.Range(aT21, aT22);
|
|
||||||
//
|
|
||||||
aCommonPrt.SetEdge1(myEdge1);
|
|
||||||
aCommonPrt.SetEdge2(myEdge2);
|
|
||||||
//
|
|
||||||
aCos = aD1.Dot(aD2);
|
|
||||||
aAng = (aCos >= 0.) ? 2.*(1. - aCos) : 2.*(1. + aCos);
|
|
||||||
//
|
|
||||||
if(aAng <= Precision::Angular()) {
|
|
||||||
IsParallel = Standard_True;
|
|
||||||
if(aL1.SquareDistance(aL2.Location()) <= aTol) {
|
|
||||||
IsCoincide = Standard_True;
|
|
||||||
aP11 = ElCLib::Value(aT11, aL1);
|
|
||||||
aP12 = ElCLib::Value(aT12, aL1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aP11 = ElCLib::Value(aT11, aL1);
|
|
||||||
aP12 = ElCLib::Value(aT12, aL1);
|
|
||||||
if(aL2.SquareDistance(aP11) <= aTol && aL2.SquareDistance(aP12) <= aTol) {
|
|
||||||
IsCoincide = Standard_True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if (IsCoincide) {
|
|
||||||
Standard_Real t21, t22;
|
|
||||||
//
|
|
||||||
t21 = ElCLib::Parameter(aL2, aP11);
|
|
||||||
t22 = ElCLib::Parameter(aL2, aP12);
|
|
||||||
if((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
Standard_Real temp;
|
|
||||||
if(t21 > t22) {
|
|
||||||
temp = t21;
|
|
||||||
t21 = t22;
|
|
||||||
t22 = temp;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if(t21 >= aT21) {
|
|
||||||
if(t22 <= aT22) {
|
|
||||||
aCommonPrt.SetRange1(aT11, aT12);
|
|
||||||
aCommonPrt.SetAllNullFlag(Standard_True);
|
|
||||||
aCommonPrt.AppendRange2(t21, t22);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aCommonPrt.SetRange1(aT11, aT12 - (t22 - aT22));
|
|
||||||
aCommonPrt.AppendRange2(t21, aT22);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aCommonPrt.SetRange1(aT11 + (aT21 - t21), aT12);
|
|
||||||
aCommonPrt.AppendRange2(aT21, t22);
|
|
||||||
}
|
|
||||||
aCommonPrt.SetType(TopAbs_EDGE);
|
|
||||||
myCommonParts.Append(aCommonPrt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if (IsParallel) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
{
|
{
|
||||||
TopoDS_Iterator aIt1, aIt2;
|
if (aL1.SquareDistance (aL2.Location()) > aTol)
|
||||||
aIt1.Initialize(myEdge1);
|
return;
|
||||||
for (; aIt1.More(); aIt1.Next()) {
|
}
|
||||||
const TopoDS_Shape& aV1 = aIt1.Value();
|
|
||||||
aIt2.Initialize(myEdge2);
|
Standard_Real aT11, aT12, aT21, aT22;
|
||||||
for (; aIt2.More(); aIt2.Next()) {
|
myRange1.Range (aT11, aT12);
|
||||||
const TopoDS_Shape& aV2 = aIt2.Value();
|
myRange2.Range (aT21, aT22);
|
||||||
if (aV2.IsSame(aV1)) {
|
|
||||||
|
gp_Pnt aP11 = ElCLib::Value (aT11, aL1);
|
||||||
|
gp_Pnt aP12 = ElCLib::Value (aT12, aL1);
|
||||||
|
|
||||||
|
if (!IsCoincide)
|
||||||
|
{
|
||||||
|
gp_Pnt O2 (aL2.Location());
|
||||||
|
if (!Precision::IsInfinite (aT21) && !Precision::IsInfinite (aT22))
|
||||||
|
O2 = ElCLib::Value ((aT21 + aT22) / 2., aL2);
|
||||||
|
|
||||||
|
gp_Vec aVec1 = gp_Vec (O2, aP11).Crossed (aD2);
|
||||||
|
gp_Vec aVec2 = gp_Vec (O2, aP12).Crossed (aD2);
|
||||||
|
|
||||||
|
Standard_Real aSqDist1 = aVec1.SquareMagnitude();
|
||||||
|
Standard_Real aSqDist2 = aVec2.SquareMagnitude();
|
||||||
|
|
||||||
|
IsCoincide = (aSqDist1 <= aTol && aSqDist2 <= aTol);
|
||||||
|
|
||||||
|
if (!IsCoincide && aVec1.Dot (aVec2) > 0)
|
||||||
|
// the lines do not intersect
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntTools_CommonPrt aCommonPrt;
|
||||||
|
aCommonPrt.SetEdge1 (myEdge1);
|
||||||
|
aCommonPrt.SetEdge2 (myEdge2);
|
||||||
|
|
||||||
|
if (IsCoincide)
|
||||||
|
{
|
||||||
|
Standard_Real t21 = ElCLib::Parameter (aL2, aP11);
|
||||||
|
Standard_Real t22 = ElCLib::Parameter (aL2, aP12);
|
||||||
|
|
||||||
|
if ((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21))
|
||||||
|
// projections are out of range
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (t21 > t22)
|
||||||
|
std::swap (t21, t22);
|
||||||
|
|
||||||
|
if (t21 >= aT21)
|
||||||
|
{
|
||||||
|
if (t22 <= aT22)
|
||||||
|
{
|
||||||
|
aCommonPrt.SetRange1 (aT11, aT12);
|
||||||
|
aCommonPrt.SetAllNullFlag (Standard_True);
|
||||||
|
aCommonPrt.AppendRange2 (t21, t22);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aCommonPrt.SetRange1 (aT11, aT12 - (t22 - aT22));
|
||||||
|
aCommonPrt.AppendRange2 (t21, aT22);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aCommonPrt.SetRange1 (aT11 + (aT21 - t21), aT12);
|
||||||
|
aCommonPrt.AppendRange2 (aT21, t22);
|
||||||
|
}
|
||||||
|
aCommonPrt.SetType (TopAbs_EDGE);
|
||||||
|
myCommonParts.Append (aCommonPrt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gp_Vec O1O2 (aL1.Location(), aL2.Location());
|
||||||
|
gp_XYZ aCross = aD1.XYZ().Crossed (aD2.XYZ());
|
||||||
|
Standard_Real aDistLL = O1O2.Dot (gp_Vec (aCross.Normalized()));
|
||||||
|
if (Abs (aDistLL) > myTol)
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Fast check that no intersection needs to be added
|
||||||
|
for (TopoDS_Iterator it1 (myEdge1); it1.More(); it1.Next())
|
||||||
|
{
|
||||||
|
for (TopoDS_Iterator it2 (myEdge2); it2.More(); it2.Next())
|
||||||
|
{
|
||||||
|
if (it1.Value().IsSame (it2.Value()))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
aSin = 1. - aCos*aCos;
|
Standard_Real aSqSin = aCross.SquareModulus();
|
||||||
gp_Pnt O1 = aL1.Location();
|
Standard_Real aT2 = (aD1.XYZ() * (O1O2.Dot (aD1)) - (O1O2.XYZ())).Dot (aD2.XYZ());
|
||||||
gp_Pnt O2 = aL2.Location();
|
aT2 /= aSqSin;
|
||||||
gp_Vec O1O2 (O1, O2);
|
|
||||||
//
|
if (aT2 < aT21 || aT2 > aT22)
|
||||||
aT2 = (aD1.XYZ()*(O1O2.Dot(aD1))-(O1O2.XYZ())).Dot(aD2.XYZ());
|
// out of range
|
||||||
aT2 /= aSin;
|
|
||||||
//
|
|
||||||
if(aT2 < aT21 || aT2 > aT22) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
//
|
gp_Pnt aP2 = ElCLib::Value (aT2, aL2);
|
||||||
gp_Pnt aP2(ElCLib::Value(aT2, aL2));
|
Standard_Real aT1 = gp_Vec (aL1.Location(), aP2).Dot (aD1);
|
||||||
aT1 = (gp_Vec(O1, aP2)).Dot(aD1);
|
|
||||||
//
|
if (aT1 < aT11 || aT1 > aT12)
|
||||||
if(aT1 < aT11 || aT1 > aT12) {
|
// out of range
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
//
|
gp_Pnt aP1 = ElCLib::Value (aT1, aL1);
|
||||||
gp_Pnt aP1(ElCLib::Value(aT1, aL1));
|
Standard_Real aDist = aP1.SquareDistance (aP2);
|
||||||
Standard_Real aDist = aP1.SquareDistance(aP2);
|
|
||||||
//
|
if (aDist > aTol)
|
||||||
if (aDist > aTol) {
|
// no intersection
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
//
|
|
||||||
// compute correct range on the edges
|
// compute correct range on the edges
|
||||||
Standard_Real anAngle, aDt1, aDt2;
|
Standard_Real aDt1 = IntTools_Tools::ComputeIntRange (myTol1, myTol2, anAngle);
|
||||||
//
|
Standard_Real aDt2 = IntTools_Tools::ComputeIntRange (myTol2, myTol1, anAngle);
|
||||||
anAngle = aD1.Angle(aD2);
|
|
||||||
//
|
aCommonPrt.SetRange1 (aT1 - aDt1, aT1 + aDt1);
|
||||||
aDt1 = IntTools_Tools::ComputeIntRange(myTol1, myTol2, anAngle);
|
aCommonPrt.AppendRange2 (aT2 - aDt2, aT2 + aDt2);
|
||||||
aDt2 = IntTools_Tools::ComputeIntRange(myTol2, myTol1, anAngle);
|
aCommonPrt.SetType (TopAbs_VERTEX);
|
||||||
//
|
aCommonPrt.SetVertexParameter1 (aT1);
|
||||||
aCommonPrt.SetRange1(aT1 - aDt1, aT1 + aDt1);
|
aCommonPrt.SetVertexParameter2 (aT2);
|
||||||
aCommonPrt.AppendRange2(aT2 - aDt2, aT2 + aDt2);
|
myCommonParts.Append (aCommonPrt);
|
||||||
aCommonPrt.SetType(TopAbs_VERTEX);
|
|
||||||
aCommonPrt.SetVertexParameter1(aT1);
|
|
||||||
aCommonPrt.SetVertexParameter2(aT2);
|
|
||||||
myCommonParts.Append(aCommonPrt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
|
37
tests/bugs/modalg_7/bug30913_1
Normal file
37
tests/bugs/modalg_7/bug30913_1
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
puts "========"
|
||||||
|
puts "0030913: Invalid result of Fusing slices"
|
||||||
|
puts "========"
|
||||||
|
puts ""
|
||||||
|
|
||||||
|
restore [locate_data_file bug30913_case1.brep] s
|
||||||
|
|
||||||
|
bclearobjects
|
||||||
|
bcleartools
|
||||||
|
set exp [explode s]
|
||||||
|
baddobjects s_1
|
||||||
|
eval baddtools [lrange $exp 1 end]
|
||||||
|
|
||||||
|
# Use gluing Shift option
|
||||||
|
bglue 1
|
||||||
|
# Avoid History filling
|
||||||
|
setfillhistory 0
|
||||||
|
|
||||||
|
bfillds
|
||||||
|
bbop result 1
|
||||||
|
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
unifysamedom result result
|
||||||
|
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
checkprops result -s 3.81335e+06 -v 1.39597e+08
|
||||||
|
checknbshapes result -vertex 12042 -edge 18169 -wire 6223 -face 6176 -shell 1 -solid 1 -t
|
||||||
|
|
||||||
|
if {![regexp "This shape seems to be OK" [bopcheck result]]} {
|
||||||
|
puts "Error: result is a self-intersecting shape"
|
||||||
|
}
|
||||||
|
|
||||||
|
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||||
|
|
||||||
|
boptions -default
|
39
tests/bugs/modalg_7/bug30913_2
Normal file
39
tests/bugs/modalg_7/bug30913_2
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
puts "========"
|
||||||
|
puts "0030913: Invalid result of Fusing slices"
|
||||||
|
puts "========"
|
||||||
|
puts ""
|
||||||
|
|
||||||
|
restore [locate_data_file bug30913_case2.brep] s
|
||||||
|
|
||||||
|
bclearobjects
|
||||||
|
bcleartools
|
||||||
|
set exp [explode s]
|
||||||
|
baddobjects s_1
|
||||||
|
eval baddtools [lrange $exp 1 end]
|
||||||
|
|
||||||
|
# Use gluing Shift option
|
||||||
|
bglue 1
|
||||||
|
# Avoid History filling
|
||||||
|
setfillhistory 0
|
||||||
|
|
||||||
|
bfillds
|
||||||
|
bbop result 1
|
||||||
|
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
dchrono unify restart
|
||||||
|
unifysamedom result result
|
||||||
|
dchrono unify stop counter UNIFY_SD
|
||||||
|
|
||||||
|
checkshape result
|
||||||
|
|
||||||
|
checkprops result -s 3.89766e+06 -v 1.40733e+08
|
||||||
|
checknbshapes result -vertex 46597 -edge 70375 -wire 24212 -face 23995 -shell 1 -solid 1 -t
|
||||||
|
|
||||||
|
#if {![regexp "This shape seems to be OK" [bopcheck result]]} {
|
||||||
|
# puts "Error: result is a self-intersecting shape"
|
||||||
|
#}
|
||||||
|
|
||||||
|
checkview -display result -2d -path ${imagedir}/${test_image}.png
|
||||||
|
|
||||||
|
boptions -default
|
Loading…
x
Reference in New Issue
Block a user