1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-06 10:36:12 +03:00
occt/src/ApproxInt/ApproxInt_MultiLine.gxx
nbv 4e14c88f77 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
2015-12-04 13:15:04 +03:00

578 lines
19 KiB
Plaintext

// Created on: 1993-03-22
// Created by: Laurent BUCHARD
// Copyright (c) 1993-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <TColStd_Array1OfReal.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec2d.hxx>
#include <gp_Vec.hxx>
#include <IntSurf_LineOn2S.hxx>
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
ApproxInt_MultiLine::
ApproxInt_MultiLine(const Handle_TheLine& line,
const Standard_Address svsurf,
const Standard_Integer NbP3d,
const Standard_Integer NbP2d,
const Standard_Real xo,
const Standard_Real yo,
const Standard_Real zo,
const Standard_Real u1o,
const Standard_Real v1o,
const Standard_Real u2o,
const Standard_Real v2o,
const Standard_Boolean P2DOnFirst,
const Standard_Integer IndMin,
const Standard_Integer IndMax): PtrOnmySvSurfaces(svsurf),
myLine(line),
indicemin(Min(IndMin, IndMax)),
indicemax(Max(IndMin, IndMax)),
nbp3d(NbP3d), nbp2d(NbP2d),
p2donfirst(P2DOnFirst),
Xo(xo), Yo(yo), Zo(zo),
U1o(u1o), V1o(v1o),
U2o(u2o), V2o(v2o)
{
#if OCCT_DEBUG
//if(indicemin == indicemax)
//{
// cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
//}
#endif
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
ApproxInt_MultiLine::
ApproxInt_MultiLine(const Handle_TheLine& line,
const Standard_Integer NbP3d,
const Standard_Integer NbP2d,
const Standard_Real xo,
const Standard_Real yo,
const Standard_Real zo,
const Standard_Real u1o,
const Standard_Real v1o,
const Standard_Real u2o,
const Standard_Real v2o,
const Standard_Boolean P2DOnFirst,
const Standard_Integer IndMin,
const Standard_Integer IndMax): PtrOnmySvSurfaces(0),
myLine(line),
indicemin(Min(IndMin, IndMax)),
indicemax(Max(IndMin, IndMax)),
nbp3d(NbP3d), nbp2d(NbP2d),
p2donfirst(P2DOnFirst),
Xo(xo), Yo(yo), Zo(zo),
U1o(u1o), V1o(v1o),
U2o(u2o), V2o(v2o)
{
#if OCCT_DEBUG
//if(indicemin == indicemax)
//{
// cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
//}
#endif
}
//--------------------------------------------------------------------------------
Standard_Integer ApproxInt_MultiLine::FirstPoint() const {
return(indicemin);
}
//--------------------------------------------------------------------------------
Standard_Integer ApproxInt_MultiLine::LastPoint() const {
return(indicemax);
}
//--------------------------------------------------------------------------------
Approx_Status ApproxInt_MultiLine::WhatStatus() const {
if(PtrOnmySvSurfaces)
return(Approx_PointsAdded);
else
return(Approx_NoPointsAdded);
}
//--------------------------------------------------------------------------------
Standard_Integer ApproxInt_MultiLine::NbP3d() const {
return(nbp3d);
}
//--------------------------------------------------------------------------------
Standard_Integer ApproxInt_MultiLine::NbP2d() const {
return(nbp2d);
}
//================================================================================
void ApproxInt_MultiLine::Value(const Standard_Integer Index,
TColgp_Array1OfPnt& TabPnt) const
{
const gp_Pnt& aP = myLine->Point(Index).Value();
TabPnt(1).SetCoord(aP.X()+Xo, aP.Y()+Yo, aP.Z()+Zo);
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
void ApproxInt_MultiLine::Value(const Standard_Integer Index,
TColgp_Array1OfPnt2d& TabPnt2d) const
{
IntSurf_PntOn2S POn2S(myLine->Point(Index));
Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
POn2S.Parameters(u1, v1, u2, v2);
if(nbp2d==1)
{
if(p2donfirst)
{
TabPnt2d(1).SetCoord(u1+U1o, v1+V1o);
}
else
{
TabPnt2d(1).SetCoord(u2+U2o, v2+V2o);
}
}
else
{
TabPnt2d(1).SetCoord(u1+U1o, v1+V1o);
if(TabPnt2d.Length() >= 2)
{
TabPnt2d(2).SetCoord(u2+U2o, v2+V2o);
}
}
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
void ApproxInt_MultiLine::Value(const Standard_Integer Index,
TColgp_Array1OfPnt& TabPnt,
TColgp_Array1OfPnt2d& TabPnt2d) const
{
Value(Index, TabPnt);
Value(Index, TabPnt2d);
}
//=======================================================================
//function : Tangency
//purpose :
//=======================================================================
Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
TColgp_Array1OfVec& TabVec) const
{
if(PtrOnmySvSurfaces==NULL)
return Standard_False;
const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
POn2S.Parameters(u1,v1,u2,v2);
Standard_Boolean ret=
((TheSvSurfaces *)PtrOnmySvSurfaces)->Tangency(u1, v1, u2, v2, TabVec(1));
if(!ret)
{
TabVec(1).SetCoord(0.0, 0.0, 0.0);
}
return ret;
}
//=======================================================================
//function : Tangency
//purpose :
//=======================================================================
Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
TColgp_Array1OfVec2d& TabVec2d) const
{
if(PtrOnmySvSurfaces==NULL)
return Standard_False;
const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
POn2S.Parameters(u1,v1,u2,v2);
Standard_Boolean ret = Standard_False;
if(nbp2d==1)
{
if(p2donfirst)
{
ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
}
else
{
ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(1));
}
}
else
{
ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
if(ret)
{
if(TabVec2d.Length()>=2)
{
ret =
(ret &&
((TheSvSurfaces *)PtrOnmySvSurfaces)->
TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(2)));
}
}
}
if(!ret)
{
TabVec2d(1) = gp_Vec2d(0.0, 0.0);
if(TabVec2d.Length() >= 2)
{
TabVec2d(2) = gp_Vec2d(0.0,0.0);
}
}
return ret;
}
//=======================================================================
//function : Tangency
//purpose :
//=======================================================================
Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
TColgp_Array1OfVec& TabVec,
TColgp_Array1OfVec2d& TabVec2d) const
{
return (Tangency(Index, TabVec) && Tangency(Index, TabVec2d));
}
//=======================================================================
//function : MakeMLBetween
//purpose :
//=======================================================================
ApproxInt_MultiLine
ApproxInt_MultiLine::MakeMLBetween( const Standard_Integer Low,
const Standard_Integer High,
const Standard_Integer aNbPntsToInsert) const
{
if(PtrOnmySvSurfaces==NULL) {
//-- cout<<"\n Erreur dans : ApproxInt_MultiLine ApproxInt_MultiLine::MakeMLBetween "<<endl;
Handle(IntSurf_LineOn2S) vide1 = new IntSurf_LineOn2S();
Handle(TheLine) vide = new TheLine(vide1,Standard_False);
return(ApproxInt_MultiLine(vide,
NULL,
nbp3d,
nbp2d,
Xo,Yo,Zo,U1o,V1o,U2o,V2o,
p2donfirst,
1,1));
//-- return(*this);
}
Standard_Integer NbPntsToInsert=aNbPntsToInsert;
if(NbPntsToInsert<(High-Low)) NbPntsToInsert=(High-Low);
Standard_Integer NbPnts = NbPntsToInsert + High - Low + 1;
Standard_Integer NbPntsmin = High-Low;
NbPntsmin+=NbPntsmin;
if(NbPnts<NbPntsmin) NbPnts=NbPntsmin;
gp_Vec T;
gp_Vec2d TS1,TS2;
gp_Pnt P;
//-----------------------l-------------------------------------------
//-- Indice : Low Low+1 I I+1 High --
//-- --
//-- Abs.Curv. : S(Low) S(I) S(I+1) S(High) --
//-- --
//-- On echantillonne a abcisse curviligne --
//-- constante. --
//-- L abcisse est calculee sur les params U1,V1 --
//------------------------------------------------------------------
TColStd_Array1OfReal U1(Low,High);
TColStd_Array1OfReal V1(Low,High);
TColStd_Array1OfReal U2(Low,High);
TColStd_Array1OfReal V2(Low,High);
TColStd_Array1OfReal AC(Low,High);
Standard_Real s,ds;
//------------------------------------------------------------
//-- Creation des Tableaux U1 .. V2 et AC
//--
Standard_Real u1,v1,u2,v2;
Standard_Integer i ;
myLine->Point(Low).Parameters(u1,v1,u2,v2);
U1(Low) = u1;
V1(Low) = v1;
U2(Low) = u2;
V2(Low) = v2;
AC(Low) =0.0;
#if 0
for( i=Low+1; i<=High; i++) {
myLine->Point(i).Parameters(u1,v1,u2,v2);
U1(i) = u1;
V1(i) = v1;
U2(i) = u2;
V2(i) = v2;
Standard_Real du1=u1-U1(i-1);
Standard_Real dv1=v1-V1(i-1);
AC(i) = AC(i-1) + sqrt((du1*du1)+(dv1*dv1));
}
#else
//-- Essai du 19 juin 96 (parametrage selon abs curv en XYZ)
for( i=Low+1; i<=High; i++) {
myLine->Point(i).Parameters(u1,v1,u2,v2);
U1(i) = u1;
V1(i) = v1;
U2(i) = u2;
V2(i) = v2;
AC(i) = AC(i-1) + (myLine->Point(i-1).Value()).Distance(myLine->Point(i).Value());
}
#endif
//-------------------------------------------------------------
//-- Creation des structures contenant les resultats
Handle(IntSurf_LineOn2S) ResultPntOn2SLine = new IntSurf_LineOn2S();
IntSurf_PntOn2S StartPOn2S;
TColStd_Array1OfReal StartParams(1,4);
ds = AC(High) / (NbPnts-1);
Standard_Integer Indice = Low;
Standard_Boolean HasBeenInserted = Standard_False;
Standard_Real dsmin = ds*0.3;
Standard_Real smax = AC(High);
for(i=2,s=ds; (s < smax && Indice <= High-1); i++,s+=ds) {
//----------------------------------------------------------
//-- Recherche des indices des points --
//-- Point : 2 i NbPnts-1 --
//-- s s --
//-- Current Indice tel que AC(Indice)<= s < AC(Indice+1) --
//----------------------------------------------------------
while(AC(Indice+1) <= s)
{
if(!HasBeenInserted)
ResultPntOn2SLine->Add(myLine->Point(Indice));
HasBeenInserted = Standard_False;
Indice++;
if (Indice == High)
break;
}
if (Indice == High)
break;
if(!HasBeenInserted && AC(Indice) <= s)
{
ResultPntOn2SLine->Add(myLine->Point(Indice));
HasBeenInserted = Standard_True;
}
Standard_Real a = s - AC(Indice);
Standard_Real b = AC(Indice+1) - s;
Standard_Real nab = 1.0/(a+b);
//----------------------------------------------------------
//-- Verification : Si Dist au prochain point < dsmin --
//-- Si Dist au precedent point < dsmin --
//-- --
//----------------------------------------------------------
if((a>dsmin) && (b>dsmin))
{
u1 = (U1(Indice) * b + U1(Indice+1) * a) * nab;
v1 = (V1(Indice) * b + V1(Indice+1) * a) * nab;
u2 = (U2(Indice) * b + U2(Indice+1) * a) * nab;
v2 = (V2(Indice) * b + V2(Indice+1) * a) * nab;
if(((TheSvSurfaces *)PtrOnmySvSurfaces)->Compute(u1,v1,u2,v2,P,T,TS1,TS2))
{
StartPOn2S.SetValue(P,u1,v1,u2,v2);
//-- cout<<" Insertion du point calcule : "<<u1<<","<<v1<<","<<u2<<","<<v2<<",";
//-- cout<<P.X()<<","<<P.Y()<<","<<P.Z()<<endl;
ResultPntOn2SLine->Add(StartPOn2S);
}
else
{
//-- cout<<" Probleme Non Traite ds ApproxInt_ApproxIntIntersection "<<endl;
}
}
else
{
//-- Point non situe a distance suffisante de 2 pts existants
//-- avec le point p[indice] deja insere
if(b<0.0)
{
while(AC(Indice+1) <= s)
{
if(!HasBeenInserted)
ResultPntOn2SLine->Add(myLine->Point(Indice));
//-- cout<<" Insertion du point :"<<Indice<<endl;
HasBeenInserted = Standard_False;
Indice++;
if (Indice == High)
break;
}
if(Indice == High)
break;
if(!HasBeenInserted && AC(Indice) <= s)
{
ResultPntOn2SLine->Add(myLine->Point(Indice));
HasBeenInserted = Standard_True;
}
}
else
{
s+= (dsmin - ds);
}
}
}
ResultPntOn2SLine->Add(myLine->Point(High)); //-- Point NbPnts
Handle(TheLine) temp = new TheLine(ResultPntOn2SLine,Standard_False);
//-- Verification a posteriori
//-- On verifie qu il n y a pas de virage trop important en 2d et en 3d
temp->Point(1).Parameters(u1,v1,u2,v2);
gp_Pnt2d P1A(u1,v1);
gp_Pnt2d P2A(u2,v2);
temp->Point(2).Parameters(u1,v1,u2,v2);
gp_Pnt2d P1B(u1,v1);
gp_Pnt2d P2B(u2,v2);
gp_Pnt2d P1C,P2C;
Standard_Integer CodeErreur=0;
for(i=3,NbPnts=temp->NbPnts();CodeErreur==0 && i<=NbPnts; i++)
{
Standard_Real d,du,dv,duv2;
temp->Point(i).Parameters(u1,v1,u2,v2);
//-- Virage P1A P1B P1C
P1C.SetCoord(u1,v1);
du = P1B.X()-P1A.X();
dv = P1B.Y()-P1A.Y();
duv2= 0.25*(du*du+dv*dv);
u1 = P1B.X() + du;
v1 = P1B.Y() + dv;
du = P1C.X() - u1;
dv = P1C.Y() - v1;
d = du*du+dv*dv;
if(d>duv2)
{
CodeErreur = 1;
CodeErreur = 1;
break;
}
//-- Virage P2A P2B P2C
P2C.SetCoord(u2,v2);
du = P2B.X()-P2A.X();
dv = P2B.Y()-P2A.Y();
duv2= 0.25*(du*du+dv*dv);
u2 = P2B.X() + du;
v2 = P2B.Y() + dv;
du = P2C.X() - u2;
dv = P2C.Y() - v2;
d = du*du+dv*dv;
if(d>duv2)
{
CodeErreur = 2;
break;
}
P1A=P1B;
P2A=P2B;
P1B=P1C;
P2B=P2C;
}
#if OCCT_DEBUG
//if (temp->NbPnts() < NbPntsToInsert + High - Low + 1)
//{
// cout<<" *** Pas assez de points entre :"<<
// Low<<" et "<<High<<" -> "<<temp->NbPnts()<<endl;
//}
//if(CodeErreur)
//{
// cout<<" *** CodeErreur : "<<CodeErreur<<endl;
//}
#endif
if((temp->NbPnts() >= NbPntsToInsert + High - Low + 1) && (CodeErreur==0))
{
return(ApproxInt_MultiLine( temp,
(High-Low>10)? PtrOnmySvSurfaces : NULL,
nbp3d,
nbp2d,
Xo,Yo,Zo,
U1o,V1o,
U2o,V2o,
p2donfirst,
1,ResultPntOn2SLine->NbPoints()));
}
else
{
//-- cout<<" ApproxInt_MultiLine "<<endl;
//-- cout<<" Pas de Rajout de points ds1min = "<<minds1<<" ds2min = "<<minds2<<endl;
Handle(IntSurf_LineOn2S) vide1 = new IntSurf_LineOn2S();
Handle(TheLine) vide = new TheLine(vide1,Standard_False);
return(ApproxInt_MultiLine( vide,
NULL,
nbp3d,
nbp2d,
Xo,Yo,Zo,
U1o,V1o,
U2o,V2o,
p2donfirst,
1,1));
}
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void ApproxInt_MultiLine::Dump() const
{
TColgp_Array1OfPnt anArr1(1, 1);
TColgp_Array1OfPnt2d anArr2(1, 2);
const Standard_Integer anIndF = FirstPoint(),
anIndL = LastPoint();
for(Standard_Integer ind = anIndF; ind <= anIndL; ind++)
{
Value(ind, anArr1, anArr2);
printf("%4d [%+10.20f %+10.20f %+10.20f] "
"[%+10.20f %+10.20f] [%+10.20f %+10.20f]\n",
ind, anArr1(1).X(), anArr1(1).Y(), anArr1(1).Z(), anArr2(1).X(),
anArr2(1).Y(),anArr2(2).X(),anArr2(2).Y());
}
}