0023952: Improving thread-safety of intersections, approximations and other modeling...
[occt.git] / src / IntStart / IntStart_SearchInside.gxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2012 OPEN CASCADE SAS
3//
4// The content of this file is subject to the Open CASCADE Technology Public
5// License Version 6.5 (the "License"). You may not use the content of this file
6// except in compliance with the License. Please obtain a copy of the License
7// at http://www.opencascade.org and read it completely before using this file.
8//
9// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11//
12// The Original Code and all software distributed under the License is
13// distributed on an "AS IS" basis, without warranty of any kind, and the
14// Initial Developer hereby disclaims all such warranties, including without
15// limitation, any warranties of merchantability, fitness for a particular
16// purpose or non-infringement. Please see the License for the specific terms
17// and conditions governing the rights and limitations under the License.
18
7fd59977 19
20#ifndef DEB
21#define No_Standard_RangeError
22#define No_Standard_OutOfRange
23#endif
24
25
26
27#include <math_FunctionSetRoot.hxx>
28#include <Precision.hxx>
29#include <gp_Pnt2d.hxx>
30
31#include <TopAbs_State.hxx>
32
33IntStart_SearchInside::IntStart_SearchInside (): done(Standard_False)
34{}
35
36IntStart_SearchInside::IntStart_SearchInside (TheFunction& Func,
37 const ThePSurface& PS,
38 const Handle(TheTopolTool)& T,
39 const Standard_Real Epsilon) {
40
41 Perform(Func,PS,T,Epsilon);
42}
43
44
45//=======================================================================
46//function : Perform
47//purpose : Search all inside points
48//=======================================================================
49
50void IntStart_SearchInside::Perform (TheFunction& Func,
51 const ThePSurface& PS,
52 const Handle(TheTopolTool)& T,
53 const Standard_Real Epsilon) {
54
55 done = Standard_False;
56 list.Clear();
1ef32e96
RL
57 Standard_Real aBinf[2], aBsup[2], aUVap[2], atoler[2];
58 math_Vector Binf(aBinf,1,2), Bsup(aBsup,1,2), UVap(aUVap,1,2), toler(atoler,1,2);
7fd59977 59 gp_Pnt psol;
60 Standard_Boolean testpnt;
61 Standard_Integer i,j,nbpt;
62 TopAbs_State situ;
63 Standard_Real umin,umax,vmin,vmax;
64 Binf(1) = umin = ThePSurfaceTool::FirstUParameter(PS);
65 Binf(2) = vmin = ThePSurfaceTool::FirstVParameter(PS);
66 Bsup(1) = umax = ThePSurfaceTool::LastUParameter(PS);
67 Bsup(2) = vmax = ThePSurfaceTool::LastVParameter(PS);
68
69 Standard_Integer NbsampleU= T->NbSamplesU();
70 Standard_Integer NbsampleV= T->NbSamplesV();
71 Standard_Integer Nbsample = T->NbSamples();
72
73 Standard_Real du = Bsup(1)-Binf(1);
74 Standard_Real dv = Bsup(2)-Binf(2);
75 du/=(Standard_Real)NbsampleU*0.5;
76 dv/=(Standard_Real)NbsampleV*0.5;
77
78 Standard_Real toler1 = toler(1) = ThePSurfaceTool::UResolution(PS,Precision::Confusion());
79 Standard_Real toler2 = toler(2) = ThePSurfaceTool::VResolution(PS,Precision::Confusion());
80 Standard_Real Maxtoler1toler2 = toler1;
81 if(toler2>Maxtoler1toler2) Maxtoler1toler2 = toler2;
82
83 //-- lbr le 15 mai 97
84 //-- on interdit aux points d'etre trop prets des restrictions
85 Maxtoler1toler2*=1000;
86 if(Maxtoler1toler2>du*0.001) Maxtoler1toler2=du*0.001;
87 if(Maxtoler1toler2>dv*0.001) Maxtoler1toler2=dv*0.001;
88
89
90 Func.Set(PS);
91 Standard_Real Tol = Func.Tolerance();
92
93 math_FunctionSetRoot Rsnld(Func,toler);
94
95 Standard_Integer REJET_OK=0;
96 Standard_Integer REJET_KO=0;
97
98 //-- lbr le 15 mai 97
99 umin+=du*0.01;
100 vmin+=dv*0.01;
101 umax-=du*0.01;
102 vmax-=dv*0.01;
103
104 //-- lbr le 30 octobre 97 :
105 //-- Si une surface vient tangenter 2 edges proche d un coin
106 //-- il faut faire attention qu un point de depart soit trouve au
107 //-- voisinage du coin. Car ds le cas contraire, le cheminement ne
108 //-- pourra pas passer au travers des frontieres :
109 //--
110 //-- typiquement I est un cylindre (conge)
111 //--
112 //-- PPPPPPPPPPPPPPPPPPPP*PPPPPPPPPPPPPPPP
113 //-- P I I
114 //-- P I I
115 //-- P I
116 //-- P # il faut trouver un point ici
117 //-- P I
118 //-- P I
119 //-- PI
120 //-- * I
121 //-- PI I
122 //-- P I I I I I I I I
123 //--
124
125
126 for (i=1; i <= Nbsample+12; i++) {
127 gp_Pnt2d s2d;
128 gp_Pnt s3d;
129 Standard_Boolean nepastester=Standard_False;
130 if(i<=Nbsample) {
131 T->SamplePoint(i,s2d,s3d);
132 UVap(1)=s2d.X(); UVap(2)=s2d.Y();
133
134 Standard_Real u1,v1,u2,v2;
135 u1 = Binf(1) = Max(umin,UVap(1)-du);
136 v1 = Binf(2) = Max(vmin,UVap(2)-dv);
137 u2 = Bsup(1) = Min(umax,UVap(1)+du);
138 v2 = Bsup(2) = Min(vmax,UVap(2)+dv);
139
140
141 //-- gp_Pnt Pmilieu = ThePSurfaceTool::Value(PS,0.5*(u1+u2),0.5*(v1+v2));
142 gp_Pnt Pextrm1 = ThePSurfaceTool::Value(PS,u1,v1);
143 gp_Pnt Pextrm2 = ThePSurfaceTool::Value(PS,u2,v2);
1ef32e96
RL
144 Standard_Real aValf[1];
145 math_Vector Valf(aValf,1,1);
7fd59977 146 Func.Value(UVap,Valf);
147 Standard_Real rvalf = Valf(1);
148 Standard_Real DistPP = Pextrm1.SquareDistance(Pextrm2);
149 if(rvalf*rvalf > 3.0*DistPP) {
150 REJET_OK++;
151 nepastester=Standard_True;
152 }
153 }
154 else {
155 if(i==Nbsample+1) { s2d.SetCoord(umin+du*0.02,vmin+dv*0.02); }
156 else if(i==Nbsample+2) { s2d.SetCoord(umax-du*0.02,vmin+dv*0.02); }
157 else if(i==Nbsample+3) { s2d.SetCoord(umin+du*0.02,vmax-dv*0.02); }
158 else if(i==Nbsample+4) { s2d.SetCoord(umax-du*0.02,vmax-dv*0.02); }
159
160 else if(i==Nbsample+5) { s2d.SetCoord(umin+du*0.02,vmin+dv*0.02); }
161 else if(i==Nbsample+6) { s2d.SetCoord(umax-du*0.02,vmin+dv*0.02); }
162 else if(i==Nbsample+7) { s2d.SetCoord(umin+du*0.02,vmax-dv*0.02); }
163 else if(i==Nbsample+8) { s2d.SetCoord(umax-du*0.02,vmax-dv*0.02); }
164
165 else if(i==Nbsample+9) { s2d.SetCoord(umin+du*0.005,vmin+dv*0.005); }
166 else if(i==Nbsample+10){ s2d.SetCoord(umax-du*0.005,vmin+dv*0.005); }
167 else if(i==Nbsample+11){ s2d.SetCoord(umin+du*0.005,vmax-dv*0.005); }
168 else { s2d.SetCoord(umax-du*0.005,vmax-dv*0.005); }
169
170 UVap(1)=s2d.X(); UVap(2)=s2d.Y();
171
172 Binf(1) = Max(umin,UVap(1)-du);
173 Binf(2) = Max(vmin,UVap(2)-dv);
174 Bsup(1) = Min(umax,UVap(1)+du);
175 Bsup(2) = Min(vmax,UVap(2)+dv);
176 }
177
178
179 if(nepastester==Standard_False) {
180 REJET_KO++;
181 Rsnld.Perform(Func,UVap,Binf,Bsup);
182 if (Rsnld.IsDone()) {
183 if (Abs(Func.Root()) <= Tol) {
184 if (!Func.IsTangent()) {
185 psol = Func.Point();
186 Rsnld.Root(UVap);
187 // On regarde si le point trouve est bien un nouveau point.
188 j = 1;
189 nbpt = list.Length();
190 testpnt = (j <= nbpt);
191
192 while (testpnt) {
193 const IntSurf_InteriorPoint& IPj = list(j);
194 const gp_Pnt& Pj = IPj.Value();
195 if ( (Abs(Pj.X()-psol.X()) <= Epsilon)
196 && (Abs(Pj.Y()-psol.Y()) <= Epsilon)
197 && (Abs(Pj.Z()-psol.Z()) <= Epsilon)
198 && (Abs(UVap(1)-IPj.UParameter()) <= toler1)
199 && (Abs(UVap(2)-IPj.VParameter()) <= toler2) ) {
200 testpnt = Standard_False;
201 }
202 else {
203 j = j+1;
204 testpnt = (j <= nbpt);
205 }
206 }
207 if (j > nbpt) {
208 // situ = TheSITool::Classify(PS,UVap(1),UVap(2));
209 situ = T->Classify(gp_Pnt2d(UVap(1),UVap(2)),
210 Maxtoler1toler2,Standard_False); //-- ,Standard_False pour ne pas recadrer on Periodic
211 if (situ == TopAbs_IN) {
212 list.Append(IntSurf_InteriorPoint(psol,UVap(1),UVap(2),
213 Func.Direction3d(),
214 Func.Direction2d()));
215 }
216 }
217 }
218 }
219 }
220 }
221 }
222 //-- printf("\n Total : %d Rejet : %d RatioPointCalc : %g nbpt =%d\n",REJET_OK+REJET_KO,REJET_OK,(double)(REJET_KO)/(double)(REJET_OK+REJET_KO),list.Length());
223 done = Standard_True;
224}
225
226
227//=======================================================================
228//function : Perform
229//purpose : Test the given inside point
230//=======================================================================
231
232void IntStart_SearchInside::Perform (TheFunction& Func,
233 const ThePSurface& PS,
234 const Standard_Real UStart,
235 const Standard_Real VStart)
236{
237 done = Standard_False;
238 list.Clear();
239 math_Vector Binf(1,2), Bsup(1,2), toler(1,2);
240
241 Binf(1) = ThePSurfaceTool::FirstUParameter(PS);
242 Binf(2) = ThePSurfaceTool::FirstVParameter(PS);
243 Bsup(1) = ThePSurfaceTool::LastUParameter(PS);
244 Bsup(2) = ThePSurfaceTool::LastVParameter(PS);
245
246 toler(1) = ThePSurfaceTool::UResolution(PS,Precision::Confusion());
247 toler(2) = ThePSurfaceTool::VResolution(PS,Precision::Confusion());
248
249 if (UStart-Binf(1) > -toler(1) && UStart-Bsup(1) < toler(1) &&
250 VStart-Binf(2) > -toler(2) && VStart-Bsup(2) < toler(2)) {
251
252 Func.Set(PS);
253 math_Vector UVap(1,2);
254 UVap(1)=UStart; UVap(2)=VStart;
255
256 math_FunctionSetRoot Rsnld(Func,toler);
257 Rsnld.Perform(Func,UVap,Binf,Bsup);
258 if (Rsnld.IsDone()) {
259 Standard_Real tol = Func.Tolerance();
260 Standard_Real valf = Func.Root();
261 if (Abs(valf) <= tol && !Func.IsTangent()) {
262 const gp_Pnt& psol = Func.Point();
263 Rsnld.Root(UVap);
264 IntSurf_InteriorPoint intp (psol,UVap(1),UVap(2),
265 Func.Direction3d(),Func.Direction2d());
266 list.Append(intp);
267 }
268 }
269 }
270
271 done = Standard_True;
272}