mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
0026979: Parabola curve intersection with variety of surfaces produces incorrect results.
Method Intf_Tool::ParabBox now properly estimates the number of segments for a 3D parabola. Fix input arguments of called Bnd_Box::Get method in Intf_Tool::HyprBox method.
This commit is contained in:
parent
715fcb5a92
commit
7b5f784419
@ -730,7 +730,7 @@ void Intf_Tool::HyprBox(const gp_Hypr& theHypr,
|
||||
Standard_Integer npi;
|
||||
Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
|
||||
//
|
||||
domain.Get(Xmax, Ymax, Zmax, Xmin, Ymin, Zmin);
|
||||
domain.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
|
||||
//
|
||||
for (npi=0; npi<nbPi; npi++) {
|
||||
Xmin=Min(Xmin, xint[npi]);
|
||||
@ -1007,31 +1007,272 @@ Standard_Integer Intf_Tool::Inters3d(const gp_Hypr& theCurv,
|
||||
return aNbDiffPoints;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Inters3d
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_Integer Intf_Tool::Inters3d(const gp_Parab& theCurv,
|
||||
const Bnd_Box& Domain)
|
||||
{
|
||||
Standard_Integer nbpi=0;
|
||||
Standard_Integer npi;
|
||||
Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
|
||||
|
||||
Domain.Get(xmin, ymin, zmin, xmax, ymax, zmax);
|
||||
|
||||
if (!Domain.IsOpenXmin()) {
|
||||
IntAna_IntConicQuad Inters1(theCurv,
|
||||
gp_Pln(1., 0., 0., -xmin),
|
||||
Precision::Angular());
|
||||
if (Inters1.IsDone()) {
|
||||
if (!Inters1.IsInQuadric()) {
|
||||
for (npi = 1; npi <= Inters1.NbPoints(); npi++) {
|
||||
yint[nbpi] = Inters1.Point(npi).Y();
|
||||
zint[nbpi] = Inters1.Point(npi).Z();
|
||||
if (ymin <= yint[nbpi] && yint[nbpi] < ymax &&
|
||||
zmin <= zint[nbpi] && zint[nbpi] < zmax) {
|
||||
xint[nbpi] = xmin;
|
||||
parint[nbpi] = Inters1.ParamOnConic(npi);
|
||||
bord[nbpi] = 1;
|
||||
nbpi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Domain.IsOpenYmin()) {
|
||||
IntAna_IntConicQuad Inters1(theCurv,
|
||||
gp_Pln( 0., 1., 0., -ymin),
|
||||
Precision::Angular());
|
||||
if (Inters1.IsDone()) {
|
||||
if (!Inters1.IsInQuadric()) {
|
||||
for (npi = 1; npi <= Inters1.NbPoints(); npi++) {
|
||||
xint[nbpi] = Inters1.Point(npi).X();
|
||||
zint[nbpi] = Inters1.Point(npi).Z();
|
||||
if (xmin < xint[nbpi] && xint[nbpi] <= xmax &&
|
||||
zmin <= zint[nbpi] && zint[nbpi] < zmax) {
|
||||
yint[nbpi] = ymin;
|
||||
parint[nbpi] = Inters1.ParamOnConic(npi);
|
||||
bord[nbpi] = 2;
|
||||
nbpi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Domain.IsOpenZmin()) {
|
||||
IntAna_IntConicQuad Inters1(theCurv,
|
||||
gp_Pln( 0., 0., 1., -zmin),
|
||||
Precision::Angular());
|
||||
if (Inters1.IsDone()) {
|
||||
if (!Inters1.IsInQuadric()) {
|
||||
for (npi = 1; npi <= Inters1.NbPoints(); npi++) {
|
||||
xint[nbpi] = Inters1.Point(npi).X();
|
||||
yint[nbpi] = Inters1.Point(npi).Y();
|
||||
if (xmin < xint[nbpi] && xint[nbpi] <= xmax &&
|
||||
ymin < yint[nbpi] && yint[nbpi] <= ymax) {
|
||||
zint[nbpi] = zmin;
|
||||
parint[nbpi] = Inters1.ParamOnConic(npi);
|
||||
bord[nbpi] = 3;
|
||||
nbpi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Domain.IsOpenXmax()) {
|
||||
IntAna_IntConicQuad Inters1(theCurv,
|
||||
gp_Pln(-1., 0., 0., xmax),
|
||||
Precision::Angular());
|
||||
if (Inters1.IsDone()) {
|
||||
if (!Inters1.IsInQuadric()) {
|
||||
for (npi = 1; npi <= Inters1.NbPoints(); npi++) {
|
||||
yint[nbpi] = Inters1.Point(npi).Y();
|
||||
zint[nbpi] = Inters1.Point(npi).Z();
|
||||
if (ymin < yint[nbpi] && yint[nbpi] <= ymax &&
|
||||
zmin < zint[nbpi] && zint[nbpi] <= zmax) {
|
||||
xint[nbpi] = xmax;
|
||||
parint[nbpi] = Inters1.ParamOnConic(npi);
|
||||
bord[nbpi] = 4;
|
||||
nbpi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Domain.IsOpenYmax()) {
|
||||
IntAna_IntConicQuad Inters1(theCurv,
|
||||
gp_Pln( 0.,-1., 0., ymax),
|
||||
Precision::Angular());
|
||||
if (Inters1.IsDone()) {
|
||||
if (!Inters1.IsInQuadric()) {
|
||||
for (npi = 1; npi <= Inters1.NbPoints(); npi++) {
|
||||
xint[nbpi] = Inters1.Point(npi).X();
|
||||
zint[nbpi] = Inters1.Point(npi).Z();
|
||||
if (xmin <= xint[nbpi] && xint[nbpi] < xmax &&
|
||||
zmin < zint[nbpi] && zint[nbpi] <= zmax) {
|
||||
yint[nbpi] = ymax;
|
||||
parint[nbpi] = Inters1.ParamOnConic(npi);
|
||||
bord[nbpi] = 5;
|
||||
nbpi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Domain.IsOpenZmax()) {
|
||||
IntAna_IntConicQuad Inters1(theCurv,
|
||||
gp_Pln( 0., 0.,-1., zmax),
|
||||
Precision::Angular());
|
||||
if (Inters1.IsDone()) {
|
||||
if (!Inters1.IsInQuadric()) {
|
||||
for (npi = 1; npi <= Inters1.NbPoints(); npi++) {
|
||||
xint[nbpi] = Inters1.Point(npi).X();
|
||||
yint[nbpi] = Inters1.Point(npi).Y();
|
||||
if (xmin <= xint[nbpi] && xint[nbpi] < xmax &&
|
||||
ymin <= yint[nbpi] && yint[nbpi] < ymax) {
|
||||
zint[nbpi] = zmax;
|
||||
parint[nbpi] = Inters1.ParamOnConic(npi);
|
||||
bord[nbpi] = 6;
|
||||
nbpi++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Integer aNbDiffPoints = nbpi;
|
||||
|
||||
//Sort parint and check if parint contains several
|
||||
//matched values. If that is true they will be deleted.
|
||||
for (Standard_Integer i = nbpi - 1; i > 0 ; i--) {
|
||||
for (Standard_Integer j = 0; j < i; j++) {
|
||||
if (parint[i] <= parint[j]) {
|
||||
std::swap(parint[i], parint[j]);
|
||||
std::swap(zint[i], zint[j]);
|
||||
std::swap(yint[i], yint[j]);
|
||||
std::swap(xint[i], xint[j]);
|
||||
std::swap(bord[i], bord[j]);
|
||||
}
|
||||
|
||||
if ((i < nbpi - 1) && IsEqual(parint[i], parint[i+1])) {
|
||||
aNbDiffPoints--;
|
||||
for (Standard_Integer k = i; k < aNbDiffPoints; k++) {
|
||||
parint[k] = parint[k+1];
|
||||
zint[k] = zint[k+1];
|
||||
yint[k] = yint[k+1];
|
||||
xint[k] = xint[k+1];
|
||||
bord[k] = bord[k+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aNbDiffPoints;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ParabBox
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
void Intf_Tool::ParabBox(const gp_Parab&,
|
||||
const Bnd_Box& domain,
|
||||
Bnd_Box& boxParab)
|
||||
void Intf_Tool::ParabBox(const gp_Parab& theParab,
|
||||
const Bnd_Box& domain,
|
||||
Bnd_Box& boxParab)
|
||||
{
|
||||
nbSeg=0;
|
||||
boxParab.SetVoid();
|
||||
if (domain.IsWhole()) {
|
||||
if (domain.IsWhole()) {
|
||||
boxParab.SetWhole();
|
||||
nbSeg=1;
|
||||
beginOnCurve[0]=-Precision::Infinite();
|
||||
endOnCurve[0]=Precision::Infinite();
|
||||
return;
|
||||
}
|
||||
else if (domain.IsVoid()) return;
|
||||
else if (domain.IsVoid()) return;
|
||||
|
||||
|
||||
Standard_Integer nbPi = Inters3d(theParab, domain);
|
||||
|
||||
if (nbPi > 0) {
|
||||
Standard_Integer npi;
|
||||
Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
|
||||
|
||||
domain.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
|
||||
|
||||
for (npi = 0; npi < nbPi; npi++) {
|
||||
Xmin = Min(Xmin, xint[npi]);
|
||||
Xmax = Max(Xmax, xint[npi]);
|
||||
Ymin = Min(Ymin, yint[npi]);
|
||||
Ymax = Max(Ymax, yint[npi]);
|
||||
Zmin = Min(Zmin, zint[npi]);
|
||||
Zmax = Max(Zmax, yint[npi]);
|
||||
}
|
||||
|
||||
boxParab.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
|
||||
|
||||
gp_Pnt Pn;
|
||||
gp_Vec Tan;
|
||||
Standard_Real sinan = 0;
|
||||
Standard_Boolean out = Standard_True;
|
||||
|
||||
for (npi = 0; npi < nbPi; npi++) {
|
||||
ElCLib::D1(parint[npi], theParab, Pn, Tan);
|
||||
switch (bord[npi]) {
|
||||
case 1: sinan = gp_XYZ(1., 0., 0.) * Tan.XYZ(); break;
|
||||
case 2: sinan = gp_XYZ(0., 1., 0.) * Tan.XYZ(); break;
|
||||
case 3: sinan = gp_XYZ(0., 0., 1.) * Tan.XYZ(); break;
|
||||
case 4: sinan = gp_XYZ(-1., 0., 0.) * Tan.XYZ(); break;
|
||||
case 5: sinan = gp_XYZ(0., -1., 0.) * Tan.XYZ(); break;
|
||||
case 6: sinan = gp_XYZ(0., 0., -1.) * Tan.XYZ(); break;
|
||||
}
|
||||
if (Abs(sinan) > Precision::Angular()) {
|
||||
if (sinan > 0.) {
|
||||
out = Standard_False;
|
||||
beginOnCurve[nbSeg] = parint[npi];
|
||||
nbSeg++;
|
||||
}
|
||||
else {
|
||||
if (out) {
|
||||
beginOnCurve[nbSeg] = -Precision::Infinite();
|
||||
nbSeg++;
|
||||
}
|
||||
endOnCurve[nbSeg - 1] = parint[npi];
|
||||
out = Standard_True;
|
||||
|
||||
Standard_Integer ipmin;
|
||||
if (beginOnCurve[nbSeg - 1] < -10.) ipmin = -10;
|
||||
else ipmin = (Standard_Integer)(beginOnCurve[nbSeg - 1]);
|
||||
|
||||
Standard_Integer ipmax;
|
||||
if (endOnCurve[nbSeg - 1] > 10.) ipmax = 10;
|
||||
else ipmax = (Standard_Integer)(endOnCurve[nbSeg - 1]);
|
||||
|
||||
ipmin = ipmin * 10 + 1;
|
||||
ipmax = ipmax * 10 - 1;
|
||||
Standard_Integer ip, pas = 1;
|
||||
for (ip = ipmin; ip <= ipmax; ip += pas) {
|
||||
boxParab.Add(ElCLib::Value(Standard_Real(ip) / 10., theParab));
|
||||
if (Abs(ip) <= 10) pas = 1;
|
||||
else pas = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!domain.IsOut(ElCLib::Value(0., theParab))) {
|
||||
boxParab = domain;
|
||||
beginOnCurve[0] = -Precision::Infinite();
|
||||
endOnCurve[0] = Precision::Infinite();
|
||||
nbSeg = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================
|
||||
//function : NbSegments
|
||||
//purpose :
|
||||
|
39
tests/lowalgos/intcs/bug26979
Normal file
39
tests/lowalgos/intcs/bug26979
Normal file
@ -0,0 +1,39 @@
|
||||
puts "================"
|
||||
puts "0026979: Modeling Algorithms - Parabola curve intersection with variety of surfaces produces incorrect results"
|
||||
puts "================"
|
||||
puts ""
|
||||
|
||||
set BugNumber OCC26979
|
||||
|
||||
parabola c -5.0 -1.0 0.25 0 0 1 0.25
|
||||
trim c c 0 1000
|
||||
|
||||
beziersurf bz 3 3 -4 0 -1 -4 1 0 -4 0 1 -3 1 -1 -3 2 0 -3 1 1 -2 0 -1 -2 1 0 -2 0 1
|
||||
|
||||
bsplinesurf bs \
|
||||
1 5 0 1 1 1 2 1 3 1 4 1 \
|
||||
1 5 0 1 1 1 2 1 3 1 4 1 \
|
||||
-3 0.5 -1 1 -2 0.5 0 1 -3 0.5 1 1 \
|
||||
-2 1.5 -1 1 -1 1.5 0 1 -2 1.5 1 1 \
|
||||
-3 2.5 -1 1 -2 2.5 0 1 -3 2.5 1 1
|
||||
|
||||
torus tor 3 1
|
||||
|
||||
circle c1 0 0 0 4
|
||||
trim c1 c1 -3.5 1
|
||||
extsurf ext c1 0 0 1
|
||||
|
||||
circle c2 0 0 0 0 -1 0 1 0 0 3
|
||||
trim c2 c2 -pi/2 pi/2
|
||||
revsurf rev c2 0 0 0 0 0 1
|
||||
|
||||
# intersect all surfaces
|
||||
set surfaces [list bz bs tor ext rev]
|
||||
foreach s $surfaces {
|
||||
set num [llength [intersect result $c $s 1e-7]];
|
||||
if {$num == 0} {
|
||||
puts "Faulty ${BugNumber}: no intersection point is got"
|
||||
} else {
|
||||
puts "OK ${BugNumber}";
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user