1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

[Salome issue 45822] Pipe feature errors

This commit is contained in:
jfa
2025-08-14 13:24:00 +01:00
parent 0ffa879d95
commit a7fb645f2c
3 changed files with 191 additions and 5 deletions

View File

@@ -646,6 +646,15 @@ void Extrema_ExtCC::PrepareParallelResult(const Standard_Real theUt11,
Precision::Confusion(),
theUt11,
theUt12);
// if (!ExtPCir.IsDone())
// {
// // The point is in the center of the circle => there are infinite solutions
// ClearSolutions();
// const Standard_Real aRadius = Extrema_CurveTool::Circle(*myC[0]).Radius();
// mySqDist.Append(aRadius * aRadius);
// myIsParallel = Standard_True;
// break;
// }
if (ExtPCir.NbExt() < 1)
{
continue;
@@ -702,6 +711,15 @@ void Extrema_ExtCC::PrepareParallelResult(const Standard_Real theUt11,
Precision::Confusion(),
theUt11,
theUt12);
// if (!ExtPCir.IsDone())
// {
// // The point is in the center of the circle => there are infinite solutions
// ClearSolutions();
// const Standard_Real aRadius = Extrema_CurveTool::Circle(*myC[0]).Radius();
// mySqDist.Append(aRadius * aRadius);
// myIsParallel = Standard_True;
// break;
// }
Standard_Boolean isFound = !myIsParallel;
@@ -809,13 +827,13 @@ void Extrema_ExtCC::PrepareResults(const Extrema_ExtElC& AlgExt,
if (myDone)
{
myIsParallel = AlgExt.IsParallel();
if (myIsParallel)
NbExt = AlgExt.NbExt();
if (myIsParallel && NbExt == 0)
{
PrepareParallelResult(Ut11, Ut12, Ut21, Ut22, AlgExt.SquareDistance());
}
else
{
NbExt = AlgExt.NbExt();
for (i = 1; i <= NbExt; i++)
{
// Verification de la validite des parametres
@@ -833,11 +851,25 @@ void Extrema_ExtCC::PrepareResults(const Extrema_ExtElC& AlgExt,
if (Extrema_CurveTool::IsPeriodic(*myC[0]))
{
U = ElCLib::InPeriod(U, Ut11, Ut11 + Extrema_CurveTool::Period(*myC[0]));
if (Abs(U - Ut11) < Precision::Confusion())
{
U = Ut11;
}
else
{
U = ElCLib::InPeriod(U, Ut11, Ut11 + Extrema_CurveTool::Period(*myC[0]));
}
}
if (Extrema_CurveTool::IsPeriodic(*myC[1]))
{
U2 = ElCLib::InPeriod(U2, Ut21, Ut21 + Extrema_CurveTool::Period(*myC[1]));
if (Abs(U2 - Ut21) < Precision::Confusion())
{
U2 = Ut21;
}
else
{
U2 = ElCLib::InPeriod(U2, Ut21, Ut21 + Extrema_CurveTool::Period(*myC[1]));
}
}
if ((U >= Ut11 - RealEpsilon()) && (U <= Ut12 + RealEpsilon())

View File

@@ -436,6 +436,137 @@ Standard_Boolean Extrema_ExtElC::PlanarLineCircleExtrema(const gp_Lin& theLin,
return Standard_True;
}
//=================================================================================================
Standard_Boolean Extrema_ExtElC::PerpendicularCirclesExtrema(const gp_Circ& C1,
const gp_Circ& C2,
const gp_Pln& aPlc1,
const gp_Pln& aPlc2,
const Standard_Real aTolD,
const Standard_Real angPlanes)
{
if (angPlanes <= M_PI_4)
{
return Standard_False; // The planes are more "parallel" than "perpendicular"
}
Standard_Real aTolD2 = aTolD * aTolD;
gp_Pnt aPc1 = C1.Location();
gp_Pnt aPc2 = C2.Location();
Standard_Real aD1 = aPlc2.SquareDistance(aPc1);
if (aD1 < aTolD2)
{
// The center of the first circle is on the plane of the second circle,
// and the center of the second circle is on the plane of the first circle.
// => the intersection line of the two planes is along the connection of the circles' centers.
// Compute the number of extremes based on the distance between the centers of the circles.
Standard_Real aDist = aPc1.Distance(aPc2);
Standard_Real aMinR = Min(C1.Radius(), C2.Radius());
Standard_Real aMaxR = Max(C1.Radius(), C2.Radius());
if (aDist >= aMaxR + aMinR - aTolD)
{
// The circles are either far apart or just touching.
// There is one solution for the closest points on the circles.
myNbExt = 1;
gp_Vec aVec(aPc1, aPc2);
aVec.Normalize();
gp_Pnt aP1 = aPc1.Translated(aVec * C1.Radius());
gp_Pnt aP2 = aPc2.Translated(-aVec * C2.Radius());
aDist -= aMaxR + aMinR;
mySqDist[0] = aDist * aDist;
myPoint[0][0].SetValues(ElCLib::Parameter(C1, aP1), aP1);
myPoint[0][1].SetValues(ElCLib::Parameter(C2, aP2), aP2);
myIsPar = Standard_False;
return Standard_True;
}
if (Abs(aDist - aMaxR) < aTolD)
{
// The bigger circle is going through the center of the smaller circle.
// There are infinite solutions on the small circle.
myNbExt = 1;
gp_Vec aVec(aPc1, aPc2);
aVec.Normalize();
gp_Pnt aP1 = aPc1.Translated(aVec * C1.Radius());
gp_Pnt aP2 = aPc2.Translated(-aVec * C2.Radius());
aDist = aMinR;
mySqDist[0] = aDist * aDist;
myPoint[0][0].SetValues(ElCLib::Parameter(C1, aP1), aP1);
myPoint[0][1].SetValues(ElCLib::Parameter(C2, aP2), aP2);
myIsPar = Standard_True; // indicator for infinite solutions
return Standard_True;
}
if (aDist <= aMaxR - aMinR + aTolD)
{
// The smaller circle is completely inside the bigger circle.
// There is one solution for the closest points on the circles.
myNbExt = 1;
gp_Vec aVec(aPc1, aPc2);
if (aVec.Magnitude() < aTolD)
{
// Both circle centers are coincident.
aVec = aPlc1.Axis().Direction().Crossed(aPlc2.Axis().Direction());
myNbExt++;
}
aVec.Normalize();
if (C1.Radius() < C2.Radius())
{
aVec.Reverse();
}
gp_Pnt aP1 = aPc1.Translated(aVec * C1.Radius());
gp_Pnt aP2 = aPc2.Translated(aVec * C2.Radius());
Standard_Real aD = aMaxR - aDist - aMinR;
mySqDist[0] = aD * aD;
myPoint[0][0].SetValues(ElCLib::Parameter(C1, aP1), aP1);
myPoint[0][1].SetValues(ElCLib::Parameter(C2, aP2), aP2);
if (myNbExt > 1)
{
gp_Pnt aP3 = aPc1.Translated(-aVec * C1.Radius());
gp_Pnt aP4 = aPc2.Translated(-aVec * C2.Radius());
mySqDist[1] = mySqDist[0];
myPoint[1][0].SetValues(ElCLib::Parameter(C1, aP3), aP3);
myPoint[1][1].SetValues(ElCLib::Parameter(C2, aP4), aP4);
}
myIsPar = Standard_False;
return Standard_True;
}
if (aDist < aMaxR + aMinR - aTolD)
{
// The circles are intersecting.
// There is one solution for the closest points on the circles.
myNbExt = 1;
gp_Vec aVec(aPc2, aPc1);
if (aVec.Magnitude() < aMaxR)
{
// The center of the small circle is inside the big circle.
aVec.Reverse();
}
aVec.Normalize();
if (C1.Radius() < C2.Radius())
{
aVec.Reverse();
}
gp_Pnt aP1 = aPc1.Translated(aVec * C1.Radius());
gp_Pnt aP2 = aPc2.Translated(aVec * C2.Radius());
Standard_Real aD = (aMaxR + aMinR - aDist);
mySqDist[0] = aD * aD;
myPoint[0][0].SetValues(ElCLib::Parameter(C1, aP1), aP1);
myPoint[0][1].SetValues(ElCLib::Parameter(C2, aP2), aP2);
myIsPar = Standard_False;
return Standard_True;
}
// std::cout << "====> Extrema_ExtElC: unsupported case for circles in different planes." << std::endl;
// std::cout << " Distance between centers: " << aDist << std::endl;
// std::cout << " Angle between planes ...: " << angPlanes * 180.0 / M_PI << " deg" << std::endl;
// std::cout << " Radius Circle 1 ........: " << C1.Radius() << std::endl;
// std::cout << " Radius Circle 2 ........: " << C2.Radius() << std::endl;
}
return Standard_False;
}
//=======================================================================
// function : Extrema_ExtElC
// purpose :
@@ -973,6 +1104,22 @@ Extrema_ExtElC::Extrema_ExtElC(const gp_Circ& C1, const gp_Circ& C2)
bIsSamePlane = aDc1.IsParallel(aDc2, aTolA) && aD2 < aTolD2;
if (!bIsSamePlane)
{
// Handle the specific case:
// * where both planes are "almost perpendicular" (=> angle between planes > 45 deg)
// * where the center of each circle is on the plane of the other circle
// (=> the circle centers are on the intersection line of the two planes)
const Standard_Real angPlanes = aDc1.Angle(aDc2);
if (aD2 < aTolD2 && angPlanes > M_PI_4)
{
// The center of the second circle is on the plane of the first circle and
// both planes are "almost perpendicular".
gp_Pln aPlc2(aPc2, aDc2);
if (PerpendicularCirclesExtrema(C1, C2, aPlc1, aPlc2, aTolD, angPlanes))
{
myDone = Standard_True;
return;
}
}
return;
}

View File

@@ -28,6 +28,7 @@ class gp_Circ;
class gp_Elips;
class gp_Hypr;
class gp_Parab;
class gp_Pln;
//! It calculates all the distance between two elementary
//! curves.
@@ -85,7 +86,13 @@ public:
protected:
//! Computes extrema in case when considered line and circle are in one plane
Standard_EXPORT Standard_Boolean PlanarLineCircleExtrema(const gp_Lin& C1, const gp_Circ& C2);
//! Computes extrema in case when two circles are in almost perpendicular planes
//! and their centers are on the intersection line of these planes
//! (angle between planes > 45 degrees)
Standard_EXPORT Standard_Boolean PerpendicularCirclesExtrema(const gp_Circ& C1, const gp_Circ& C2,
const gp_Pln& aPlc1, const gp_Pln& aPlc2,
const Standard_Real aTolD,
const Standard_Real angPlanes);
private:
Standard_Boolean myDone;
Standard_Boolean myIsPar;