1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#ifndef OCCT_DEBUG
16#define No_Standard_RangeError
17#define No_Standard_OutOfRange
18#endif
19
20
21
22#include <math_FunctionSetRoot.hxx>
23#include <Precision.hxx>
24#include <gp_Pnt2d.hxx>
25
26#include <TopAbs_State.hxx>
27
28IntStart_SearchInside::IntStart_SearchInside (): done(Standard_False)
29{}
30
31IntStart_SearchInside::IntStart_SearchInside (TheFunction& Func,
32                                              const ThePSurface& PS,
33					      const Handle(TheTopolTool)& T,
34					      const Standard_Real Epsilon) {
35
36  Perform(Func,PS,T,Epsilon);
37}
38
39
40//=======================================================================
41//function : Perform
42//purpose  : Search all inside points
43//=======================================================================
44
45void IntStart_SearchInside::Perform (TheFunction& Func,
46				     const ThePSurface& PS,
47				     const Handle(TheTopolTool)& T,
48				     const Standard_Real Epsilon) {
49
50  done = Standard_False;
51  list.Clear();
52  Standard_Real aBinf[2], aBsup[2], aUVap[2], atoler[2];
53  math_Vector Binf(aBinf,1,2), Bsup(aBsup,1,2), UVap(aUVap,1,2), toler(atoler,1,2);
54  gp_Pnt psol;
55  Standard_Boolean testpnt;
56  Standard_Integer i,j,nbpt;
57  TopAbs_State situ;
58  Standard_Real umin,umax,vmin,vmax;
59  Binf(1) = umin = ThePSurfaceTool::FirstUParameter(PS);
60  Binf(2) = vmin = ThePSurfaceTool::FirstVParameter(PS);
61  Bsup(1) = umax = ThePSurfaceTool::LastUParameter(PS);
62  Bsup(2) = vmax = ThePSurfaceTool::LastVParameter(PS);
63
64  Standard_Integer NbsampleU= T->NbSamplesU();
65  Standard_Integer NbsampleV= T->NbSamplesV();
66  Standard_Integer Nbsample = T->NbSamples();
67
68  Standard_Real du = Bsup(1)-Binf(1);
69  Standard_Real dv = Bsup(2)-Binf(2);
70  du/=(Standard_Real)NbsampleU*0.5;
71  dv/=(Standard_Real)NbsampleV*0.5;
72
73  Standard_Real toler1 = toler(1) = ThePSurfaceTool::UResolution(PS,Precision::Confusion());
74  Standard_Real toler2 = toler(2) = ThePSurfaceTool::VResolution(PS,Precision::Confusion());
75  Standard_Real Maxtoler1toler2 = toler1;
76  if(toler2>Maxtoler1toler2) Maxtoler1toler2 = toler2;
77
78  //-- lbr le 15 mai 97
79  //-- on interdit aux points d'etre trop prets des restrictions
80  Maxtoler1toler2*=1000;
81  if(Maxtoler1toler2>du*0.001) Maxtoler1toler2=du*0.001;
82  if(Maxtoler1toler2>dv*0.001) Maxtoler1toler2=dv*0.001;
83
84
85  Func.Set(PS);
86  Standard_Real Tol = Func.Tolerance();
87
88  math_FunctionSetRoot Rsnld(Func,toler);
89
90  Standard_Integer REJET_OK=0;
91  Standard_Integer REJET_KO=0;
92
93  //-- lbr le 15 mai 97
94  umin+=du*0.01;
95  vmin+=dv*0.01;
96  umax-=du*0.01;
97  vmax-=dv*0.01;
98
99  //-- lbr le 30 octobre 97 :
100  //-- Si une surface vient tangenter 2 edges proche d un coin
101  //-- il faut faire attention qu un point de depart soit trouve au
102  //-- voisinage du coin. Car ds le cas contraire, le cheminement ne
103  //-- pourra pas passer au travers des frontieres :
104  //--
105  //-- typiquement I est un cylindre (conge)
106  //--
107  //--                 PPPPPPPPPPPPPPPPPPPP*PPPPPPPPPPPPPPPP
108  //--                 P               I     I
109  //--                 P           I           I
110  //--                 P        I
111  //--                 P      #  il faut trouver un point ici
112  //--                 P    I
113  //--                 P  I
114  //--                 PI
115  //--                 *                    I
116  //--                 PI                 I
117  //--                 P  I I I I I I I I
118  //--
119
120
121  for (i=1; i <= Nbsample+12; i++) {
122    gp_Pnt2d s2d;
123    gp_Pnt s3d;
124    Standard_Boolean nepastester=Standard_False;
125    if(i<=Nbsample) {
126      T->SamplePoint(i,s2d,s3d);
127      UVap(1)=s2d.X(); UVap(2)=s2d.Y();
128
129      Standard_Real u1,v1,u2,v2;
130      u1 = Binf(1) = Max(umin,UVap(1)-du);
131      v1 = Binf(2) = Max(vmin,UVap(2)-dv);
132      u2 = Bsup(1) = Min(umax,UVap(1)+du);
133      v2 = Bsup(2) = Min(vmax,UVap(2)+dv);
134
135
136      //-- gp_Pnt Pmilieu = ThePSurfaceTool::Value(PS,0.5*(u1+u2),0.5*(v1+v2));
137      gp_Pnt Pextrm1 = ThePSurfaceTool::Value(PS,u1,v1);
138      gp_Pnt Pextrm2 = ThePSurfaceTool::Value(PS,u2,v2);
139      Standard_Real aValf[1];
140      math_Vector Valf(aValf,1,1);
141      Func.Value(UVap,Valf);
142      Standard_Real rvalf = Valf(1);
143      Standard_Real DistPP = Pextrm1.SquareDistance(Pextrm2);
144      if(rvalf*rvalf > 3.0*DistPP) {
145	REJET_OK++;
146	nepastester=Standard_True;
147      }
148    }
149    else {
150                 if(i==Nbsample+1) { s2d.SetCoord(umin+du*0.02,vmin+dv*0.02); }
151      else       if(i==Nbsample+2) { s2d.SetCoord(umax-du*0.02,vmin+dv*0.02);  }
152      else       if(i==Nbsample+3) { s2d.SetCoord(umin+du*0.02,vmax-dv*0.02); }
153      else       if(i==Nbsample+4) { s2d.SetCoord(umax-du*0.02,vmax-dv*0.02);  }
154
155      else       if(i==Nbsample+5) { s2d.SetCoord(umin+du*0.02,vmin+dv*0.02); }
156      else       if(i==Nbsample+6) { s2d.SetCoord(umax-du*0.02,vmin+dv*0.02);  }
157      else       if(i==Nbsample+7) { s2d.SetCoord(umin+du*0.02,vmax-dv*0.02); }
158      else       if(i==Nbsample+8) { s2d.SetCoord(umax-du*0.02,vmax-dv*0.02);  }
159
160      else       if(i==Nbsample+9) { s2d.SetCoord(umin+du*0.005,vmin+dv*0.005); }
161      else       if(i==Nbsample+10){ s2d.SetCoord(umax-du*0.005,vmin+dv*0.005);  }
162      else       if(i==Nbsample+11){ s2d.SetCoord(umin+du*0.005,vmax-dv*0.005); }
163      else                         { s2d.SetCoord(umax-du*0.005,vmax-dv*0.005);  }
164
165      UVap(1)=s2d.X(); UVap(2)=s2d.Y();
166
167      Binf(1) = Max(umin,UVap(1)-du);
168      Binf(2) = Max(vmin,UVap(2)-dv);
169      Bsup(1) = Min(umax,UVap(1)+du);
170      Bsup(2) = Min(vmax,UVap(2)+dv);
171    }
172
173
174    if(nepastester==Standard_False) {
175      REJET_KO++;
176      Rsnld.Perform(Func,UVap,Binf,Bsup);
177      if (Rsnld.IsDone()) {
178	if (Abs(Func.Root()) <= Tol) {
179	  if (!Func.IsTangent()) {
180	    psol = Func.Point();
181	    Rsnld.Root(UVap);
182	    // On regarde si le point trouve est bien un nouveau point.
183	    j = 1;
184	    nbpt = list.Length();
185	    testpnt = (j <= nbpt);
186
187	    while (testpnt) {
188	      const IntSurf_InteriorPoint&  IPj = list(j);
189	      const gp_Pnt& Pj = IPj.Value();
190	      if (   (Abs(Pj.X()-psol.X()) <= Epsilon)
191		  && (Abs(Pj.Y()-psol.Y()) <= Epsilon)
192		  && (Abs(Pj.Z()-psol.Z()) <= Epsilon)
193		  && (Abs(UVap(1)-IPj.UParameter()) <= toler1)
194		  && (Abs(UVap(2)-IPj.VParameter()) <= toler2) ) {
195		testpnt = Standard_False;
196	      }
197	      else {
198		j = j+1;
199		testpnt = (j <= nbpt);
200	      }
201	    }
202	    if (j > nbpt) {
203	      //	    situ = TheSITool::Classify(PS,UVap(1),UVap(2));
204	      situ = T->Classify(gp_Pnt2d(UVap(1),UVap(2)),
205				 Maxtoler1toler2,Standard_False);   //-- ,Standard_False pour ne pas recadrer on Periodic
206	      if (situ == TopAbs_IN) {
207		list.Append(IntSurf_InteriorPoint(psol,UVap(1),UVap(2),
208						  Func.Direction3d(),
209						  Func.Direction2d()));
210	      }
211	    }
212	  }
213	}
214      }
215    }
216  }
217  //-- 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());
218  done = Standard_True;
219}
220
221
222//=======================================================================
223//function : Perform
224//purpose  : Test the given inside point
225//=======================================================================
226
227void IntStart_SearchInside::Perform (TheFunction& Func,
228				     const ThePSurface& PS,
229				     const Standard_Real UStart,
230				     const Standard_Real VStart)
231{
232  done = Standard_False;
233  list.Clear();
234  math_Vector Binf(1,2), Bsup(1,2), toler(1,2);
235
236  Binf(1) = ThePSurfaceTool::FirstUParameter(PS);
237  Binf(2) = ThePSurfaceTool::FirstVParameter(PS);
238  Bsup(1) = ThePSurfaceTool::LastUParameter(PS);
239  Bsup(2) = ThePSurfaceTool::LastVParameter(PS);
240
241  toler(1) = ThePSurfaceTool::UResolution(PS,Precision::Confusion());
242  toler(2) = ThePSurfaceTool::VResolution(PS,Precision::Confusion());
243
244  if (UStart-Binf(1) > -toler(1) && UStart-Bsup(1) < toler(1) &&
245      VStart-Binf(2) > -toler(2) && VStart-Bsup(2) < toler(2)) {
246
247    Func.Set(PS);
248    math_Vector UVap(1,2);
249    UVap(1)=UStart; UVap(2)=VStart;
250
251    math_FunctionSetRoot Rsnld(Func,toler);
252    Rsnld.Perform(Func,UVap,Binf,Bsup);
253    if (Rsnld.IsDone()) {
254      Standard_Real tol = Func.Tolerance();
255      Standard_Real valf = Func.Root();
256      if (Abs(valf) <= tol && !Func.IsTangent()) {
257	const gp_Pnt& psol = Func.Point();
258	Rsnld.Root(UVap);
259	IntSurf_InteriorPoint intp (psol,UVap(1),UVap(2),
260				    Func.Direction3d(),Func.Direction2d());
261	list.Append(intp);
262      }
263    }
264  }
265
266  done = Standard_True;
267}
268