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

0026431: Can't cut a sphere from a cylinder

This branch contains fixes for 26675 and 26431 bugs.

1. Normalization has been eliminated.
2. Interfaces of AppDef_Compute::Parametrization(...) and BRepAlgo_BooleanOperations::SetApproxParameters() methods have been changed.
3. Overloaded methods for ApproxInt_Approx::SetParameters(...), TopOpeBRepTool_GeomTool::GetTolerances(...) and TopOpeBRepTool_GeomTool::SetTolerances(...) have been removed (because some fields of these classes are not used more).
4. Comments for some methods have been changed in BRepApprox_TheMultiLineOfApprox.hxx and GeomInt_TheMultiLineOfWLApprox.hxx files.
5. Some fields have been deleted from ApproxInt_MultiLine class. Kept members have become constant.
6. Interface of ksection DRAW-command has been changed.
7. Now, 2dintersect DRAW-command prints information about found segments.
8. Some code fragments have been rewritten to make them easier.
9. Algorithm of splitting WLine, which goes through pole of sphere has been improved.
10. Improve approximation algorithm in order to it will compute correct 2D- and 3D-tangent at the end of bezier constraints (including case when curve goes through or finishes on singular points).
11. Interface of IntPatch_WLine::Dump(...) method has been corrected.
12. Some methods for working with Walking-line are made more universal (available for both GeomInt and IntTools packages).
13. Problem in BRepLib::SameParameter(...) method has been fixed (see corresponding comment).
14. Small correction in Draft package.
15. Any outputs in IntPatch_Intersection::Dump(...) method have become disabled because they are useless. If anybody need in this outputs he/she will correct this method himself/herself.

Adjusting some test cases according to their new behavior.
Creation of new test cases.

----------------------------------------------------------------------------------------------------------------------------

Some explanation of new behavior of some test cases:

 1. Regressions:

a) blend simple X4
The problem is described in the issue #0026740. According to this description,  the result on the current MASTER seems to be wrong indeed.

b) boolean bcommon_complex C7 and boolean bcut_complex Q1
These test case use same shapes with different Boolean operation (COMMON and CUT). They are already BAD (on the MASTER). Now, some sub-shapes have become not-shared, simply. In my opinion, we shall apply new behavior of these tests.

c) boolean bsection M3
The problem described in the issue #0026777 exists even on the current MASTER.

d) boolean bsection M9
The problem is described in the message http://tracker.dev.opencascade.org/view.php?id=26815#c47546. Here, we have really regression in the picture.

e) boolean bsection N2

The problem is described in issue #0026814.

f) boolean volumemaker G1

The problem is described in issue #26020.

g) bugs modalg_1 bug1255 (and bug1255_1)

The problem is described in issue #26815.

h) bugs modalg_2 bug5805_18, bugs modalg_2 bug5805_42, bugs modalg_2 bug5805_46

The problem is described in issue #25925.

i) bugs modalg_3 bug602

The problem is describes in issue #602.

j) bugs modalg_5 bug24915

The problem is described in the message http://tracker.dev.opencascade.org/view.php?id=25929#c48565. It is not fixed by this issue.

k) bugs modalg_5 bug25838

The main reason is described in issue #0026816.

----------------------------------------------------------------------------
2. Improvements:

a) boolean volumemaker F9
b) bugs modalg_1 bug10160_3
c) bugs modalg_2 bug22557
d) bugs modalg_5 bug25319_1 (_2)
e) draft angle G2
f) offset shape A1
g) offset with_intersect_80 N7
This commit is contained in:
nbv
2015-11-10 10:31:19 +03:00
committed by bugmaster
parent f44aa19760
commit 4e14c88f77
81 changed files with 5716 additions and 3883 deletions

View File

@@ -852,6 +852,33 @@ Standard_Boolean IntTools_Context::IsVertexOnLine
(aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
aT = aFirst;
}
else
{
// Local search may fail. Try to use more precise algo.
Extrema_ExtPC anExt(aPv, aGAC, 1.e-10);
Standard_Real aMinDist = RealLast();
Standard_Integer aMinIdx = -1;
for (Standard_Integer anIdx = 1; anIdx <= anExt.NbExt(); anIdx++)
{
if ( anExt.IsMin(anIdx) &&
anExt.SquareDistance(anIdx) < aMinDist )
{
aMinDist = anExt.SquareDistance(anIdx);
aMinIdx = anIdx;
}
}
if (aMinIdx != -1)
{
const Extrema_POnCurv& aPOncurve = anExt.Point(aMinIdx);
aT = aPOncurve.Parameter();
if((aT > (aLast + aFirst) * 0.5) ||
(aPv.Distance(aPOncurve.Value()) > aTolSum) ||
(aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
aT = aFirst;
}
}
}
//
return Standard_True;
@@ -877,6 +904,32 @@ Standard_Boolean IntTools_Context::IsVertexOnLine
(aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
aT = aLast;
}
else
{
// Local search may fail. Try to use more precise algo.
Extrema_ExtPC anExt(aPv, aGAC, 1.e-10);
Standard_Real aMinDist = RealLast();
Standard_Integer aMinIdx = -1;
for (Standard_Integer anIdx = 1; anIdx <= anExt.NbExt(); anIdx++)
{
if ( anExt.IsMin(anIdx) &&
anExt.SquareDistance(anIdx) < aMinDist )
{
aMinDist = anExt.SquareDistance(anIdx);
aMinIdx = anIdx;
}
}
if (aMinIdx != -1)
{
const Extrema_POnCurv& aPOncurve = anExt.Point(aMinIdx);
aT = aPOncurve.Parameter();
if((aT < (aLast + aFirst) * 0.5) ||
(aPv.Distance(aPOncurve.Value()) > aTolSum) ||
(aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
aT = aLast;
}
}
}
//
return Standard_True;

View File

@@ -108,20 +108,17 @@
#include <GeomAdaptor.hxx>
#include <GeomInt_IntSS.hxx>
#include <IntTools_WLineTool.hxx>
#include <IntPatch_WLineTool.hxx>
#ifdef OCCT_DEBUG_DUMPWLINE
static
void DumpWLine(const Handle(IntPatch_WLine)& aWLine);
#endif
//
//#ifdef OCCT_DEBUG_DUMPWLINE
//static
// void DumpWLine(const Handle(IntPatch_WLine)& aWLine);
//#endif
////
static
void TolR3d(const TopoDS_Face& ,
const TopoDS_Face& ,
Standard_Real& );
static
Handle(Geom_Curve) MakeBSpline (const Handle(IntPatch_WLine)&,
const Standard_Integer,
const Standard_Integer);
static
void Parameters(const Handle(GeomAdaptor_HSurface)&,
@@ -871,17 +868,11 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
typl = L->ArcType();
//
if(typl==IntPatch_Walking) {
Handle(IntPatch_Line) anewL;
//
Handle(IntPatch_WLine) aWLine (Handle(IntPatch_WLine)::DownCast(L));
anewL = IntTools_WLineTool::ComputePurgedWLine(aWLine, myHS1, myHS2, dom1, dom2);
if(anewL.IsNull()) {
if(aWLine.IsNull()) {
return;
}
L = anewL;
//Handle(IntPatch_WLine) aWLineX (Handle(IntPatch_WLine)::DownCast(L));
//DumpWLine(aWLineX);
L = aWLine;
//
if(!myListOfPnts.IsEmpty()) {
@@ -1378,14 +1369,14 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
Handle(Geom2d_BSplineCurve) H2;
if(myApprox1) {
H1 = IntTools_WLineTool::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
H1 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
}
if(myApprox2) {
H2 = IntTools_WLineTool::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
H2 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
}
//
mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
mySeqOfCurve.Append(IntTools_Curve(GeomInt_IntSS::MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
}
} // if (!myApprox)
@@ -1394,7 +1385,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
//
Standard_Real tol2d = myTolApprox;
//
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True);
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_True);
aNbParts=myLConstruct.NbParts();
for (i=1; i<=aNbParts; i++) {
@@ -1410,14 +1401,14 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
Handle(Geom2d_BSplineCurve) H2;
if(myApprox1) {
H1 = IntTools_WLineTool::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
H1 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_True);
}
if(myApprox2) {
H2 = IntTools_WLineTool::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
H2 = GeomInt_IntSS::MakeBSpline2d(WL, 1, WL->NbPnts(), Standard_False);
}
//
mySeqOfCurve.Append(IntTools_Curve(MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
mySeqOfCurve.Append(IntTools_Curve(GeomInt_IntSS::MakeBSpline(WL,1,WL->NbPnts()), H1, H2));
}
else {
@@ -1528,14 +1519,14 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
}
//
if(myApprox1) {
H1 = IntTools_WLineTool::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
H1 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
}
//
if(myApprox2) {
H2 = IntTools_WLineTool::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
H2 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
}
//
aBSp=MakeBSpline(WL, ifprm, ilprm);
aBSp=GeomInt_IntSS::MakeBSpline(WL, ifprm, ilprm);
IntTools_Curve aIC(aBSp, H1, H2);
mySeqOfCurve.Append(aIC);
}// for (i=1; i<=aNbParts; ++i) {
@@ -1578,17 +1569,18 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
}
if(myHS1 == myHS2) {
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_False, aParType);
rejectSurface = Standard_True;
}
else {
if(reApprox && !rejectSurface)
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_False, aParType);
else {
Standard_Integer iDegMax, iDegMin, iNbIter;
//
ApproxParameters(myHS1, myHS2, iDegMin, iDegMax, iNbIter);
theapp3d.SetParameters(myTolApprox, tol2d, iDegMin, iDegMax, iNbIter, Standard_True, aParType);
theapp3d.SetParameters(myTolApprox, tol2d, iDegMin, iDegMax,
iNbIter, 30, Standard_True, aParType);
}
}
//
@@ -1654,7 +1646,8 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
if ((typs1==GeomAbs_BezierSurface || typs1==GeomAbs_BSplineSurface) &&
(typs2==GeomAbs_BezierSurface || typs2==GeomAbs_BSplineSurface)) {
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_True, aParType);
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30,
Standard_True, aParType);
Standard_Boolean bUseSurfaces;
bUseSurfaces = IntTools_WLineTool::NotUseSurfacesForApprox(myFace1, myFace2, WL, ifprm, ilprm);
@@ -1662,7 +1655,8 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
// ######
rejectSurface = Standard_True;
// ######
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False, aParType);
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30,
Standard_False, aParType);
}
}
}
@@ -1674,14 +1668,14 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
Handle(Geom2d_BSplineCurve) H1;
Handle(Geom2d_BSplineCurve) H2;
//
Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
Handle(Geom_Curve) aBSp=GeomInt_IntSS::MakeBSpline(WL,ifprm, ilprm);
//
if(myApprox1) {
H1 = IntTools_WLineTool::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
H1 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
}
//
if(myApprox2) {
H2 = IntTools_WLineTool::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
H2 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
}
//
IntTools_Curve aIC(aBSp, H1, H2);
@@ -1884,15 +1878,15 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
Handle(Geom2d_BSplineCurve) H1, H2;
bPCurvesOk = Standard_True;
//
Handle(Geom_Curve) aBSp=MakeBSpline(WL,ifprm, ilprm);
Handle(Geom_Curve) aBSp=GeomInt_IntSS::MakeBSpline(WL,ifprm, ilprm);
if(myApprox1) {
H1 = IntTools_WLineTool::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
H1 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
bPCurvesOk = CheckPCurve(H1, myFace1);
}
if(myApprox2) {
H2 = IntTools_WLineTool::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
H2 = GeomInt_IntSS::MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
bPCurvesOk = bPCurvesOk && CheckPCurve(H2, myFace2);
}
//

View File

@@ -13,26 +13,25 @@
#include <IntTools_WLineTool.hxx>
#include <Adaptor3d_TopolTool.hxx>
#include <BRep_Tool.hxx>
#include <Extrema_ExtCC.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomInt_LineConstructor.hxx>
#include <GeomInt.hxx>
#include <Geom2dAPI_InterCurveCurve.hxx>
#include <Geom2d_Circle.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomInt.hxx>
#include <GeomInt_LineConstructor.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Surface.hxx>
#include <gp_Circ.hxx>
#include <IntTools_Context.hxx>
#include <Precision.hxx>
#include <TColgp_SequenceOfPnt2d.hxx>
#include <TColStd_Array1OfListOfInteger.hxx>
#include <TColStd_SequenceOfReal.hxx>
#include <TColgp_SequenceOfPnt2d.hxx>
/////////////////////// NotUseSurfacesForApprox /////////////////////////
@@ -228,38 +227,6 @@ Standard_Boolean IntTools_WLineTool::NotUseSurfacesForApprox(const TopoDS_Face&
/////////////////////// end of NotUseSurfacesForApprox //////////////////
//=======================================================================
//function : MakeBSpline2d
//purpose :
//=======================================================================
Handle(Geom2d_BSplineCurve) IntTools_WLineTool::
MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
const Standard_Integer ideb,
const Standard_Integer ifin,
const Standard_Boolean onFirst)
{
Standard_Integer i, nbpnt = ifin-ideb+1;
TColgp_Array1OfPnt2d poles(1,nbpnt);
TColStd_Array1OfReal knots(1,nbpnt);
TColStd_Array1OfInteger mults(1,nbpnt);
Standard_Integer ipidebm1;
for(i = 1, ipidebm1 = i+ideb-1; i <= nbpnt; ipidebm1++, i++) {
Standard_Real U, V;
if(onFirst)
theWLine->Point(ipidebm1).ParametersOnS1(U, V);
else
theWLine->Point(ipidebm1).ParametersOnS2(U, V);
poles(i).SetCoord(U, V);
mults(i) = 1;
knots(i) = i-1;
}
mults(1) = mults(nbpnt) = 2;
return new Geom2d_BSplineCurve(poles,knots,mults,1);
}
/////////////////////// DecompositionOfWLine ////////////////////////////
//=======================================================================
@@ -767,7 +734,6 @@ Standard_Boolean IntTools_WLineTool::
Standard_Real& theReachedTol3d,
const Handle(IntTools_Context)& aContext)
{
Standard_Boolean bRet, bAvoidLineConstructor;
Standard_Integer aNbPnts, aNbParts;
//
@@ -1492,558 +1458,4 @@ Standard_Boolean IntTools_WLineTool::
return Standard_True;
}
///////////////////// end of DecompositionOfWLine ///////////////////////
/////////////////////// ComputePurgedWLine //////////////////////////////
//=========================================================================
// function : FillPointsHash
// purpose : Fill points hash by input data.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
NCollection_Array1<Standard_Integer> &thePointsHash)
{
// 1 - Delete point.
// 0 - Store point.
// -1 - Vertex point (not delete).
Standard_Integer i, v;
for(i = 1; i <= theWLine->NbPnts(); i++)
thePointsHash.SetValue(i, 0);
for(v = 1; v <= theWLine->NbVertex(); v++)
{
IntPatch_Point aVertex = theWLine->Vertex(v);
Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
thePointsHash.SetValue(avertexindex, -1);
}
}
//=========================================================================
// function : MakeNewWLine
// purpose : Makes new walking line according to the points hash
// Static subfunction in ComputePurgedWLine and DeleteOuter.
//=========================================================================
static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
const NCollection_Array1<Standard_Integer> &thePointsHash)
{
Standard_Integer i;
Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
Standard_Integer anOldLineIdx = 1, aVertexIdx = 1;
for(i = 1; i <= thePointsHash.Upper(); i++)
{
if (thePointsHash(i) == 0)
{
// Store this point.
aPurgedLineOn2S->Add(theWLine->Point(i));
anOldLineIdx++;
}
else if (thePointsHash(i) == -1)
{
// Add vertex.
IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
aVertex.SetParameter(anOldLineIdx++);
aLocalWLine->AddVertex(aVertex);
aPurgedLineOn2S->Add(theWLine->Point(i));
}
}
return aLocalWLine;
}
//=========================================================================
// function : MovePoint
// purpose : Move point into surface param space. No interpolation used
// because walking algorithm should care for closeness to the param space.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static void MovePoint(const Handle(GeomAdaptor_HSurface) &theS1,
Standard_Real &U1, Standard_Real &V1)
{
if (U1 < theS1->FirstUParameter())
U1 = theS1->FirstUParameter();
if (U1 > theS1->LastUParameter())
U1 = theS1->LastUParameter();
if (V1 < theS1->FirstVParameter())
V1 = theS1->FirstVParameter();
if (V1 > theS1->LastVParameter())
V1 = theS1->LastVParameter();
}
//=========================================================================
// function : DeleteOuterPoints
// purpose : Check and delete out of bounds points on walking line.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static Handle(IntPatch_WLine)
DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
const Handle(GeomAdaptor_HSurface) &theS1,
const Handle(GeomAdaptor_HSurface) &theS2,
const Handle(Adaptor3d_TopolTool) &theDom1,
const Handle(Adaptor3d_TopolTool) &theDom2)
{
Standard_Integer i;
NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
FillPointsHash(theWLine, aDelOuterPointsHash);
if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
theS2->IsUPeriodic() || theS2->IsVPeriodic() )
return theWLine;
gp_Pnt2d aPntOnF1, aPntOnF2;
Standard_Real aX1, aY1, aX2, aY2;
// Iterate over points in walking line and delete which are out of bounds.
// Forward.
Standard_Boolean isAllDeleted = Standard_True;
Standard_Boolean aChangedFirst = Standard_False;
Standard_Integer aFirstGeomIdx = 1;
for(i = 1; i <= theWLine->NbPnts(); i++)
{
theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
aPntOnF1.SetCoord(aX1, aY1);
aPntOnF2.SetCoord(aX2, aY2);
TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
if (aState1 == TopAbs_OUT ||
aState2 == TopAbs_OUT )
{
aDelOuterPointsHash(i) = 1;
aChangedFirst = Standard_True;
}
else
{
isAllDeleted = Standard_False;
aFirstGeomIdx = Max (i - 1, 1);
if (aDelOuterPointsHash(i) == -1)
aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
aDelOuterPointsHash(i) = -1;
break;
}
}
if (isAllDeleted)
{
// ALL points are out of bounds:
// case boolean bcut_complex F5 and similar.
return theWLine;
}
// Backward.
Standard_Boolean aChangedLast = Standard_False;
Standard_Integer aLastGeomIdx = theWLine->NbPnts();
for(i = theWLine->NbPnts(); i >= 1; i--)
{
theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
aPntOnF1.SetCoord(aX1, aY1);
aPntOnF2.SetCoord(aX2, aY2);
TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
if (aState1 == TopAbs_OUT ||
aState2 == TopAbs_OUT )
{
aDelOuterPointsHash(i) = 1;
aChangedLast = Standard_True; // Move vertex to first good point
}
else
{
aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
if (aDelOuterPointsHash(i) == -1)
aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
aDelOuterPointsHash(i) = -1;
break;
}
}
if (!aChangedFirst && !aChangedLast)
{
// Nothing is done, return input.
return theWLine;
}
// Build new line and modify geometry of necessary vertexes.
Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash);
if (aChangedFirst)
{
// Vertex geometry.
IntPatch_Point aVertex = aLocalWLine->Vertex(1);
aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
Standard_Real aU1, aU2, aV1, aV2;
theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
MovePoint(theS1, aU1, aV1);
MovePoint(theS2, aU2, aV2);
aVertex.SetParameters(aU1, aV1, aU2, aV2);
aLocalWLine->Replace(1, aVertex);
// Change point in walking line.
aLocalWLine->SetPoint(1, aVertex);
}
if (aChangedLast)
{
// Vertex geometry.
IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
Standard_Real aU1, aU2, aV1, aV2;
theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
MovePoint(theS1, aU1, aV1);
MovePoint(theS2, aU2, aV2);
aVertex.SetParameters(aU1, aV1, aU2, aV2);
aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
// Change point in walking line.
aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
}
return aLocalWLine;
}
//=========================================================================
// function : IsInsideIn2d
// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
// In 2d space. Static subfunction in DeleteByTube.
//=========================================================================
static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
const gp_Vec2d& aBaseVec,
const gp_Pnt2d& aNextPnt,
const Standard_Real aSquareMaxDist)
{
gp_Vec2d aVec2d(aBasePnt, aNextPnt);
//d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
Standard_Real aCross = aVec2d.Crossed(aBaseVec);
Standard_Real aSquareDist = aCross * aCross
/ aBaseVec.SquareMagnitude();
return (aSquareDist <= aSquareMaxDist);
}
//=========================================================================
// function : IsInsideIn3d
// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
// In 3d space. Static subfunction in DeleteByTube.
//=========================================================================
static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
const gp_Vec& aBaseVec,
const gp_Pnt& aNextPnt,
const Standard_Real aSquareMaxDist)
{
gp_Vec aVec(aBasePnt, aNextPnt);
//d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
/ aBaseVec.SquareMagnitude();
return (aSquareDist <= aSquareMaxDist);
}
static const Standard_Integer aMinNbBadDistr = 15;
static const Standard_Integer aNbSingleBezier = 30;
//=========================================================================
// function : DeleteByTube
// purpose : Check and delete points using tube criteria.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static Handle(IntPatch_WLine)
DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
const Handle(GeomAdaptor_HSurface) &theS1,
const Handle(GeomAdaptor_HSurface) &theS2)
{
// III: Check points for tube criteria:
// Workaround to handle case of small amount points after purge.
// Test "boolean boptuc_complex B5" and similar.
Standard_Integer aNbPnt = 0 , i;
if (theWLine->NbPnts() <= 2)
return theWLine;
NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
FillPointsHash(theWLine, aNewPointsHash);
// Inital computations.
Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
// Choose base tolerance and scale it to pipe algorithm.
const Standard_Real aBaseTolerance = Precision::Approximation();
Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
theS1->VResolution(aBaseTolerance));
Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
theS2->VResolution(aBaseTolerance));
Standard_Real aTol1 = aResS1Tol * aResS1Tol;
Standard_Real aTol2 = aResS2Tol * aResS2Tol;
Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
const Standard_Real aLimitCoeff = 0.99 * 0.99;
for(i = 3; i <= theWLine->NbPnts(); i++)
{
Standard_Boolean isDeleteState = Standard_False;
theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
if (aNewPointsHash(i - 1) != - 1 &&
IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
{
// Handle possible uneven parametrization on one of 2d subspaces.
// Delete point only when expected lengths are close to each other (aLimitCoeff).
// Example:
// c2d1 - line
// c3d - line
// c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
, gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
, gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
Standard_Real aStepCoeff = Min(aStepOnS1, aStepOnS2) / Max(aStepOnS1, aStepOnS2);
if (aStepCoeff > aLimitCoeff)
{
// Set hash flag to "Delete" state.
isDeleteState = Standard_True;
aNewPointsHash.SetValue(i - 1, 1);
// Change middle point.
UonS1[1] = UonS1[2];
UonS2[1] = UonS2[2];
VonS1[1] = VonS1[2];
VonS2[1] = VonS2[2];
}
}
if (!isDeleteState)
{
// Compute new pipe parameters.
UonS1[0] = UonS1[1];
VonS1[0] = VonS1[1];
UonS2[0] = UonS2[1];
VonS2[0] = VonS2[1];
UonS1[1] = UonS1[2];
VonS1[1] = VonS1[2];
UonS2[1] = UonS2[2];
VonS2[1] = VonS2[2];
aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
aBase3dPnt = theWLine->Point(i - 1).Value();
aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
aNbPnt++;
}
}
// Workaround to handle case of small amount of points after purge.
// Test "boolean boptuc_complex B5" and similar.
// This is possible since there are at least two points.
if (aNewPointsHash(1) == -1 &&
aNewPointsHash(2) == -1 &&
aNbPnt <= 3)
{
// Delete first.
aNewPointsHash(1) = 1;
}
if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
aNewPointsHash(theWLine->NbPnts() ) == -1 &&
aNbPnt <= 3)
{
// Delete last.
aNewPointsHash(theWLine->NbPnts()) = 1;
}
// Purgre when too small amount of points left.
if (aNbPnt <= 2)
{
for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
{
if (aNewPointsHash(i) != -1)
{
aNewPointsHash(i) = 1;
}
}
}
// Handle possible bad distribution of points,
// which are will converted into one single bezier curve (less than 30 points).
// Make distribution more even:
// max step will be nearly to 0.1 of param distance.
if (aNbPnt + 2 > aMinNbBadDistr &&
aNbPnt + 2 < aNbSingleBezier )
{
for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
{
Standard_Integer aHashIdx =
Standard_Integer(anIdx * theWLine->NbPnts() / 9);
//Store this point.
aNewPointsHash(aHashIdx) = 0;
}
}
return MakeNewWLine(theWLine, aNewPointsHash);
}
//=========================================================================
// function : ComputePurgedWLine
// purpose :
//=========================================================================
Handle(IntPatch_WLine) IntTools_WLineTool::
ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
const Handle(GeomAdaptor_HSurface) &theS1,
const Handle(GeomAdaptor_HSurface) &theS2,
const Handle(Adaptor3d_TopolTool) &theDom1,
const Handle(Adaptor3d_TopolTool) &theDom2)
{
Standard_Integer i, k, v, nb, nbvtx;
Handle(IntPatch_WLine) aResult;
nbvtx = theWLine->NbVertex();
nb = theWLine->NbPnts();
if (nb==2)
{
const IntSurf_PntOn2S& p1 = theWLine->Point(1);
const IntSurf_PntOn2S& p2 = theWLine->Point(2);
if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
return aResult;
}
Handle(IntPatch_WLine) aLocalWLine;
Handle(IntPatch_WLine) aTmpWLine = theWLine;
Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
for(i = 1; i <= nb; i++)
aLineOn2S->Add(theWLine->Point(i));
for(v = 1; v <= nbvtx; v++)
aLocalWLine->AddVertex(theWLine->Vertex(v));
// I: Delete equal points
for(i = 1; i <= aLineOn2S->NbPoints(); i++)
{
Standard_Integer aStartIndex = i + 1;
Standard_Integer anEndIndex = i + 5;
nb = aLineOn2S->NbPoints();
anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
if((aStartIndex > nb) || (anEndIndex <= 1))
continue;
k = aStartIndex;
while(k <= anEndIndex)
{
if(i != k)
{
IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
Standard_Real UV[8];
p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
Standard_Real aMax = Abs(UV[0]);
for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
{
if (aMax < Abs(UV[anIdx]))
aMax = Abs(UV[anIdx]);
}
if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
{
aTmpWLine = aLocalWLine;
aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
for(v = 1; v <= aTmpWLine->NbVertex(); v++)
{
IntPatch_Point aVertex = aTmpWLine->Vertex(v);
Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
if(avertexindex >= k)
{
aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
}
aLocalWLine->AddVertex(aVertex);
}
aLineOn2S->RemovePoint(k);
anEndIndex--;
continue;
}
}
k++;
}
}
if (aLineOn2S->NbPoints() <= 2)
{
if (aLineOn2S->NbPoints() == 2)
return aLocalWLine;
else
return aResult;
}
// Avoid purge in case of C0 continuity:
// Intersection approximator may produce invalid curve after purge, example:
// bugs modalg_5 bug24731.
// Do not run purger when base number of points is too small.
if (theS1->UContinuity() == GeomAbs_C0 ||
theS1->VContinuity() == GeomAbs_C0 ||
theS2->UContinuity() == GeomAbs_C0 ||
theS2->VContinuity() == GeomAbs_C0 ||
nb < aNbSingleBezier)
{
return aLocalWLine;
}
// II: Delete out of borders points.
Handle(IntPatch_WLine) aLocalWLineOuter =
DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
/// III: Delete points by tube criteria.
Handle(IntPatch_WLine) aLocalWLineTube =
DeleteByTube(aLocalWLineOuter, theS1, theS2);
if(aLocalWLineTube->NbPnts() > 1)
{
aResult = aLocalWLineTube;
}
return aResult;
}
/////////////////////// end of ComputePurgedWLine ///////////////////////
///////////////////// end of DecompositionOfWLine ///////////////////////

View File

@@ -38,33 +38,6 @@ public:
const Standard_Integer ifprm,
const Standard_Integer ilprm);
//! I
//! Removes equal points (leave one of equal points) from theWLine
//! and recompute vertex parameters.
//!
//! II
//! Removes point out of borders in case of non periodic surfaces.
//!
//! III
//! Removes exceed points using tube criteria:
//! delete 7D point if it lies near to expected lines in 2d and 3d.
//! Each task (2d, 2d, 3d) have its own tolerance and checked separately.
//!
//! Returns new WLine or null WLine if the number
//! of the points is less than 2.
Standard_EXPORT static
Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
const Handle(GeomAdaptor_HSurface) &theS1,
const Handle(GeomAdaptor_HSurface) &theS2,
const Handle(Adaptor3d_TopolTool) &theDom1,
const Handle(Adaptor3d_TopolTool) &theDom2);
Standard_EXPORT static
Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine) &theWLine,
const Standard_Integer ideb,
const Standard_Integer ifin,
const Standard_Boolean onFirst);
Standard_EXPORT static
Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
const Handle(GeomAdaptor_HSurface)& theSurface1,