mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
0030354: BOP Cut doesn't modify the attached face
The reason of this problem is in wrong work of classifier algorithm (see the message ~0080992 to the issue #30354). Therefore, the algorithm of IntTools_FClass2d class has been improved. Namely, now orientation of the polygon is computed from area-criterion instead of angle. As result, some simplification of the method IntTools_FClass2d::Init(...) has been made. <!break> 1. New constructor has been added to the class CSLib_Class2d. It allows applying TColgp_SequenceOfPnt2d. 2. DRAW-commands "addpolygonnode" and "polygonprops" have been created. They are covered by the test case "tests/geometry/2dpolygon/A1". 3. New method Poly::PolygonProperties(...) has been created. See help for detailed information. 4. New testgrid "lowalgos classifier" has been created.
This commit is contained in:
@@ -43,6 +43,8 @@
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#include <GeomLib.hxx>
|
||||
#include <Poly.hxx>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -85,7 +87,7 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
const Standard_Real TolUV)
|
||||
{
|
||||
Standard_Boolean WireIsNotEmpty, Ancienpnt3dinitialise, degenerated;
|
||||
Standard_Integer nbpnts, firstpoint, NbEdges;
|
||||
Standard_Integer firstpoint, NbEdges;
|
||||
Standard_Integer iX, aNbs1, nbs, Avant, BadWire;
|
||||
Standard_Real u, du, Tole, Tol, pfbid, plbid;
|
||||
Standard_Real FlecheU, FlecheV, TolVertex1, TolVertex;
|
||||
@@ -128,7 +130,6 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
for(; aExpF.More(); aExpF.Next()) {
|
||||
const TopoDS_Wire& aW=*((TopoDS_Wire*)&aExpF.Current());
|
||||
//
|
||||
nbpnts = 0;
|
||||
firstpoint =1;
|
||||
FlecheU = 0.;
|
||||
FlecheV = 0.;
|
||||
@@ -264,7 +265,7 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
//-- and the last point saved in SeqPnt2d
|
||||
//-- To to set the first point of the current
|
||||
//-- afar from the last saved point
|
||||
Avant = nbpnts;
|
||||
Avant = SeqPnt2d.Length();
|
||||
for(iX=firstpoint; iX<=aNbs1; iX++) {
|
||||
Standard_Boolean IsRealCurve3d;
|
||||
Standard_Integer ii;
|
||||
@@ -282,7 +283,7 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
aDstX=RealLast();
|
||||
if(degenerated==Standard_False) {
|
||||
P3d=C3d.Value(u);
|
||||
if(nbpnts>1) {
|
||||
if(!SeqPnt2d.IsEmpty()) {
|
||||
if(Ancienpnt3dinitialise) {
|
||||
aDstX=P3d.SquareDistance(Ancienpnt3d);
|
||||
}
|
||||
@@ -308,11 +309,10 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
Ancienpnt3d=P3d;
|
||||
Ancienpnt3dinitialise=Standard_True;
|
||||
}
|
||||
nbpnts++;
|
||||
SeqPnt2d.Append(P2d);
|
||||
}
|
||||
//
|
||||
ii=nbpnts;
|
||||
ii= SeqPnt2d.Length();
|
||||
if(ii>(Avant+4)) {
|
||||
Standard_Real ul, dU, dV;
|
||||
gp_Pnt2d Pp;
|
||||
@@ -386,107 +386,38 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
}
|
||||
//
|
||||
else if(WireIsNotEmpty) {
|
||||
TColgp_Array1OfPnt2d PClass(1,nbpnts);
|
||||
gp_Pnt2d anInitPnt(0., 0.);
|
||||
//
|
||||
PClass.Init(anInitPnt);
|
||||
if(nbpnts>3) {
|
||||
Standard_Integer im2=nbpnts-2;
|
||||
Standard_Integer im1=nbpnts-1;
|
||||
Standard_Integer im0=1;
|
||||
Standard_Real angle = 0.0;
|
||||
Standard_Real aX0, aY0, aX1, aY1, aS;
|
||||
//
|
||||
aS=0.;
|
||||
//
|
||||
Standard_Integer iFlag=1;
|
||||
//
|
||||
PClass(im2)=SeqPnt2d.Value(im2);
|
||||
PClass(im1)=SeqPnt2d.Value(im1);
|
||||
PClass(nbpnts)=SeqPnt2d.Value(nbpnts);
|
||||
Standard_Real aPer = 0.;
|
||||
for (Standard_Integer ii = 1; ii<nbpnts; ii++, im0++, im1++, im2++)
|
||||
{
|
||||
if(im2>=nbpnts) im2=1;
|
||||
if(im1>=nbpnts) im1=1;
|
||||
PClass(ii)=SeqPnt2d.Value(ii);
|
||||
//
|
||||
const gp_Pnt2d& aP2D1=PClass(im1);
|
||||
const gp_Pnt2d& aP2D0=PClass(im0);
|
||||
//aP2D0 is next to aP2D1
|
||||
aP2D0.Coord(aX0, aY0);
|
||||
aP2D1.Coord(aX1, aY1);
|
||||
aS=aS+(aY0+aY1)*(aX1-aX0);
|
||||
aPer += aP2D1.Distance(aP2D0);
|
||||
|
||||
gp_Vec2d A(PClass(im2),PClass(im1));
|
||||
gp_Vec2d B(PClass(im1),PClass(im0));
|
||||
|
||||
Standard_Real N = A.Magnitude() * B.Magnitude();
|
||||
if(N>1e-16) {
|
||||
Standard_Real a=A.Angle(B);
|
||||
//
|
||||
if (anIndexMap.IsBound(im1)) {
|
||||
Standard_Integer anInd = anIndexMap.Find(im1);
|
||||
const gp_Vec2d &aVPrev = aD1Prev.Value(anInd);
|
||||
const gp_Vec2d &aVNext = aD1Next.Value(anInd);
|
||||
|
||||
Standard_Real aN = aVPrev.Magnitude() * aVNext.Magnitude();
|
||||
if(aN > 1e-16) {
|
||||
Standard_Real aDerivAngle, aAbsDA, aProduct, aPA;
|
||||
//ifv 23.08.06
|
||||
aPA=Precision::Angular();
|
||||
aDerivAngle = aVPrev.Angle(aVNext);
|
||||
aAbsDA=Abs(aDerivAngle);
|
||||
if(aAbsDA <= aPA) {
|
||||
aDerivAngle = 0.;
|
||||
}
|
||||
//
|
||||
aProduct=aDerivAngle * a;
|
||||
//
|
||||
if(Abs(aAbsDA - M_PI) <= aPA) {
|
||||
if (aProduct > 0.) {
|
||||
aProduct=-aProduct;
|
||||
}
|
||||
}
|
||||
//ifv 23.08.06 : if edges continuity > G1, |aDerivAngle| ~0,
|
||||
//but can has wrong sign and causes condition aDerivAngle * a < 0.
|
||||
//that is wrong in such situation
|
||||
if (iFlag && aProduct < 0.) {
|
||||
iFlag=0;
|
||||
// Bad case.
|
||||
angle = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
angle+=a;
|
||||
}
|
||||
}//for(ii=1; ii<nbpnts; ii++,im0++,im1++,im2++) {
|
||||
if (!iFlag) {
|
||||
angle = 0.;
|
||||
}
|
||||
if (SeqPnt2d.Length() > 3)
|
||||
{
|
||||
#ifdef DEBUG_PCLASS_POLYGON
|
||||
TColgp_Array1OfPnt2d PClass(1, nbpnts);
|
||||
TColStd_Array1OfReal aKnots(1, nbpnts);
|
||||
TColStd_Array1OfInteger aMults(1, nbpnts);
|
||||
for (int i = 1; i <= nbpnts; i++)
|
||||
{
|
||||
aKnots(i) = i;
|
||||
aMults(i) = 1;
|
||||
PClass(ii) = SeqPnt2d.Value(ii);
|
||||
}
|
||||
aMults(1) = aMults(nbpnts) = 2;
|
||||
Handle(Geom2d_BSplineCurve) aPol = new Geom2d_BSplineCurve(PClass, aKnots, aMults, 1);
|
||||
DrawTrSurf::Set("pol", aPol);
|
||||
#endif
|
||||
|
||||
Standard_Real aS = 0.;
|
||||
Standard_Real aPer = 0.;
|
||||
Poly::PolygonProperties(SeqPnt2d, aS, aPer);
|
||||
|
||||
Standard_Real anExpThick = Max(2. * Abs(aS) / aPer, 1e-7);
|
||||
Standard_Real aDefl = Max(FlecheU, FlecheV);
|
||||
Standard_Real aDiscrDefl = Min(aDefl*0.1, anExpThick * 10.);
|
||||
Standard_Boolean isChanged = Standard_False;
|
||||
while (aDefl > anExpThick && aDiscrDefl > 1e-7)
|
||||
{
|
||||
// Deflection of the polygon is too much for this ratio of area and perimeter,
|
||||
// and this might lead to self-intersections.
|
||||
// Discretize the wire more tightly to eliminate the error.
|
||||
firstpoint = 1;
|
||||
isChanged = Standard_True;
|
||||
SeqPnt2d.Clear();
|
||||
FlecheU = 0.0;
|
||||
FlecheV = 0.0;
|
||||
@@ -532,41 +463,14 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
firstpoint = 2;
|
||||
}
|
||||
}
|
||||
nbpnts = SeqPnt2d.Length();
|
||||
PClass.Resize(1, nbpnts, Standard_False);
|
||||
im1 = nbpnts - 1;
|
||||
im0 = 1;
|
||||
PClass(im1) = SeqPnt2d.Value(im1);
|
||||
PClass(nbpnts) = SeqPnt2d.Value(nbpnts);
|
||||
aS = 0.;
|
||||
aPer = 0.;
|
||||
for (Standard_Integer ii = 1; ii<nbpnts; ii++, im0++, im1++)
|
||||
{
|
||||
if (im1 >= nbpnts) im1 = 1;
|
||||
PClass(ii) = SeqPnt2d.Value(ii);
|
||||
aS += (PClass(im1).X() - PClass(im0).X())*(PClass(im0).Y() + PClass(im1).Y())*.5;
|
||||
aPer += (PClass(im0).XY() - PClass(im1).XY()).Modulus();
|
||||
}
|
||||
#ifdef DEBUG_PCLASS_POLYGON
|
||||
TColStd_Array1OfReal aKnots(1, nbpnts);
|
||||
TColStd_Array1OfInteger aMults(1, nbpnts);
|
||||
for (int i = 1; i <= nbpnts; i++)
|
||||
{
|
||||
aKnots(i) = i;
|
||||
aMults(i) = 1;
|
||||
}
|
||||
aMults(1) = aMults(nbpnts) = 2;
|
||||
Handle(Geom2d_BSplineCurve) aPol = new Geom2d_BSplineCurve(PClass, aKnots, aMults, 1);
|
||||
DrawTrSurf::Set("pol1", aPol);
|
||||
#endif
|
||||
|
||||
anExpThick = Max(2. * Abs(aS) / aPer, 1e-7);
|
||||
aDefl = Max(FlecheU, FlecheV);
|
||||
aDiscrDefl = Min(aDiscrDefl * 0.1, anExpThick * 10.);
|
||||
}
|
||||
|
||||
if(aS>0.){
|
||||
myIsHole=Standard_False;
|
||||
if (isChanged)
|
||||
{
|
||||
Poly::PolygonProperties(SeqPnt2d, aS, aPer);
|
||||
}
|
||||
//
|
||||
if(FlecheU<Toluv)
|
||||
@@ -575,25 +479,35 @@ void IntTools_FClass2d::Init(const TopoDS_Face& aFace,
|
||||
if(FlecheV<Toluv)
|
||||
FlecheV = Toluv;
|
||||
|
||||
TabClass.Append((void *)new CSLib_Class2d(PClass,
|
||||
TabClass.Append((void *)new CSLib_Class2d(SeqPnt2d,
|
||||
FlecheU,
|
||||
FlecheV,
|
||||
Umin,Vmin,Umax,Vmax));
|
||||
//
|
||||
if((angle<2 && angle>-2)||(angle>10)||(angle<-10)) {
|
||||
if(Abs(aS) < Precision::SquareConfusion()) {
|
||||
BadWire=1;
|
||||
TabOrien.Append(-1);
|
||||
}
|
||||
else {
|
||||
TabOrien.Append((angle>0.0)? 1 : 0);
|
||||
else
|
||||
{
|
||||
if (aS > 0.0)
|
||||
{
|
||||
myIsHole = Standard_False;
|
||||
TabOrien.Append(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
myIsHole = Standard_True;
|
||||
TabOrien.Append(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BadWire=1;
|
||||
TabOrien.Append(-1);
|
||||
TColgp_Array1OfPnt2d PPClass(1,2);
|
||||
PPClass.Init(anInitPnt);
|
||||
TabClass.Append((void *)new CSLib_Class2d(PPClass,
|
||||
SeqPnt2d.Clear();
|
||||
TabClass.Append((void *)new CSLib_Class2d(SeqPnt2d,
|
||||
FlecheU,
|
||||
FlecheV,
|
||||
Umin,Vmin,Umax,Vmax));
|
||||
|
@@ -522,9 +522,6 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
|
||||
#ifdef INTTOOLS_FACEFACE_DEBUG
|
||||
if(!myListOfPnts.IsEmpty()) {
|
||||
char aBuff[10000];
|
||||
const IntSurf_PntOn2S& aPt = myListOfPnts.First();
|
||||
Standard_Real u1, v1, u2, v2;
|
||||
aPt.Parameters(u1, v1, u2, v2);
|
||||
|
||||
Sprintf(aBuff,"bopcurves <face1 face2> -2d");
|
||||
IntSurf_ListIteratorOfListOfPntOn2S IterLOP1(myListOfPnts);
|
||||
|
Reference in New Issue
Block a user