7fd59977 |
1 | // File: Extrema_GenExtCC.gxx |
2 | // Created: Tue Jul 18 17:42:19 1995 |
3 | // Author: Modelistation |
4 | // <model@metrox> |
5 | |
6 | #include <StdFail_NotDone.hxx> |
7 | #include <math_FunctionSetRoot.hxx> |
8 | #include <math_NewtonFunctionSetRoot.hxx> |
9 | #include <TColStd_Array2OfInteger.hxx> |
10 | #include <TColStd_Array2OfReal.hxx> |
11 | #include <Standard_NullObject.hxx> |
12 | #include <Standard_OutOfRange.hxx> |
13 | #include <Precision.hxx> |
14 | |
15 | Extrema_GenExtCC::Extrema_GenExtCC () : myDone (Standard_False) |
16 | { |
17 | } |
18 | |
19 | Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1, |
20 | const Curve2& C2, |
21 | const Standard_Integer NbU, |
22 | const Standard_Integer NbV, |
23 | const Standard_Real TolU, |
24 | const Standard_Real TolV) : myF (C1,C2, Min(TolU, TolV)), myDone (Standard_False) |
25 | { |
26 | SetCurveCache (1, new Cache (C1, C1.FirstParameter(), C1.LastParameter(), NbU, Standard_True)); |
27 | SetCurveCache (2, new Cache (C2, C2.FirstParameter(), C2.LastParameter(), NbV, Standard_True)); |
28 | Perform(); |
29 | } |
30 | |
31 | |
32 | Extrema_GenExtCC::Extrema_GenExtCC (const Curve1& C1, |
33 | const Curve2& C2, |
34 | const Standard_Real Uinf, |
35 | const Standard_Real Usup, |
36 | const Standard_Real Vinf, |
37 | const Standard_Real Vsup, |
38 | const Standard_Integer NbU, |
39 | const Standard_Integer NbV, |
40 | const Standard_Real TolU, |
41 | const Standard_Real TolV) : myF (C1,C2), myDone (Standard_False) |
42 | { |
43 | SetCurveCache (1, new Cache (C1, Uinf, Usup, NbU, Standard_True)); |
44 | SetCurveCache (2, new Cache (C2, Vinf, Vsup, NbV, Standard_True)); |
45 | Perform(); |
46 | } |
47 | |
48 | void Extrema_GenExtCC::SetCurveCache (const Standard_Integer theRank, |
49 | const Handle(Cache)& theCache) |
50 | { |
51 | Standard_OutOfRange_Raise_if (theRank < 1 || theRank > 2, "Extrema_GenExtCC::SetCurveCache()") |
52 | myF.SetCurve (theRank, *(Curve1*)theCache->CurvePtr()); |
53 | Standard_Integer anInd = theRank - 1; |
54 | myCache[anInd] = theCache; |
55 | } |
56 | |
57 | void Extrema_GenExtCC::SetTolerance (const Standard_Real Tol) |
58 | { |
59 | myF.SetTolerance (Tol); |
60 | } |
61 | |
62 | |
63 | //============================================================================= |
64 | void Extrema_GenExtCC::Perform () |
65 | /*----------------------------------------------------------------------------- |
66 | Fonction: |
67 | Recherche de toutes les distances extremales entre les courbes C1 et C2. |
68 | a partir de 2 echantillonnages (NbU,NbV). |
69 | |
70 | Methode: |
71 | L'algorithme part de l'hypothese que les echantillonnages sont suffisamment |
72 | fins pour que, s'il existe N distances extremales entre les 2 courbes, |
73 | alors il existe aussi N extrema entre les 2 ensembles de points. |
74 | Ainsi, l'algorithme consiste a partir des extrema des echantillons |
75 | pour trouver les extrema des courbes. |
76 | Les extrema sont calcules par l'algorithme math_FunctionSetRoot avec les |
77 | arguments suivants: |
78 | - myF: Extrema_FuncExtCC cree a partir de C1 et C2, |
79 | - UV: math_Vector dont les composantes sont les parametres des points de |
80 | l'extremum sur les ensembles de points, |
81 | - Tol: Min(TolU,TolV), (Prov.:math_FunctionSetRoot n'autorise pas un vecteur) |
82 | - UVinf: math_Vector dont les composantes sont les bornes inferieures de u et |
83 | v, |
84 | - UVsup: math_Vector dont les composantes sont les bornes superieures de u et |
85 | v. |
86 | |
87 | Traitement: |
88 | a- Constitution du tableau des square distances (TbDist2(0,NbU+1,0,NbV+1)): |
89 | Le tableau est volontairement etendu; les lignes 0 et NbU+1 et les |
90 | colonnes 0 et NbV+1 seront initialisees a RealFirst() ou RealLast() |
91 | pour simplifier les tests effectues dans l'etape b |
92 | (on n'a pas besoin de tester si le point est sur une extremite). |
93 | b- Calcul des extrema: |
94 | On recherche d'abord les minima et ensuite les maxima. Ces 2 traitements |
95 | se passent de facon similaire: |
96 | b.a- Initialisations: |
97 | - des 'bords' du tableau TbDist2 (a RealLast() dans le cas des minima |
98 | et a RealLast() dans le cas des maxima), |
99 | - du tableau TbSel(0,NbU+1,0,NbV+1) de selection des points pour un |
100 | calcul d'extremum local (a 0). Lorsqu'un couple de points sera |
101 | selectionne, il ne sera plus selectionnable, ainsi que les couples |
102 | adjacents (8 au maximum). |
103 | Les adresses correspondantes seront mises a 1. |
104 | b.b- Calcul des minima (ou maxima): |
105 | On boucle sur toutes les square distances du tableau TbDist2: |
106 | - recherche d'un minimum (ou maximum) sur les echantillons, |
107 | - calcul de l'extremum sur les courbes, |
108 | - mise a jour du tableau TbSel. |
109 | -----------------------------------------------------------------------------*/ |
110 | { |
111 | myDone = Standard_False; |
112 | |
113 | const Handle(Cache)& aCache1 = myCache[0]; |
114 | const Handle(Cache)& aCache2 = myCache[1]; |
115 | Standard_NullObject_Raise_if ((aCache1.IsNull() || aCache2.IsNull()), |
116 | "Extrema_GenExtCC::Perform()") |
117 | |
118 | Standard_Integer aNbU = aCache1->NbSamples(), aNbV = aCache2->NbSamples(); |
119 | Standard_OutOfRange_Raise_if ((aNbU < 2 ||aNbV < 2), "Extrema_GenExtCC::Perform()") |
120 | |
121 | /* |
122 | a- Constitution du tableau des distances (TbDist2(0,NbU+1,0,NbV+1)): |
123 | --------------------------------------------------------------- |
124 | */ |
125 | |
126 | //ensure that caches have been calculated |
127 | if (!aCache1->IsValid()) |
128 | aCache1->CalculatePoints(); |
129 | if (!aCache2->IsValid()) |
130 | aCache2->CalculatePoints(); |
131 | |
132 | // Calcul des distances |
133 | //initialization of variables in the same way as in CalculatePoints() |
134 | Standard_Real PasU = aCache1->TrimLastParameter() - aCache1->TrimFirstParameter(); |
135 | Standard_Real PasV = aCache2->TrimLastParameter() - aCache2->TrimFirstParameter(); |
136 | Standard_Real U0 = PasU / aNbU / 100.; |
137 | Standard_Real V0 = PasV / aNbV / 100.; |
138 | PasU = (PasU - U0) / (aNbU - 1); |
139 | PasV = (PasV - V0) / (aNbV - 1); |
140 | U0 = aCache1->TrimFirstParameter() + (U0/2.); |
141 | V0 = aCache2->TrimFirstParameter() + (V0/2.); |
142 | |
143 | const Curve1& aCurve1 = *((Curve1*)(myF.CurvePtr (1))); |
144 | const Curve2& aCurve2 = *((Curve1*)(myF.CurvePtr (2))); |
145 | const Handle(ArrayOfPnt)& aPntArray1 = aCache1->Points(); |
146 | const Handle(ArrayOfPnt)& aPntArray2 = aCache2->Points(); |
147 | Standard_Integer NoU, NoV; |
148 | TColStd_Array2OfReal TbDist2(0, aNbU + 1, 0, aNbV + 1); |
149 | for (NoU = 1; NoU <= aNbU; NoU++) { |
150 | const Pnt& P1 = aPntArray1->Value (NoU); |
151 | for (NoV = 1; NoV <= aNbV; NoV++) { |
152 | const Pnt& P2 = aPntArray2->Value (NoV); |
153 | TbDist2(NoU,NoV) = P1.SquareDistance(P2); |
154 | } |
155 | } |
156 | |
157 | /* |
158 | b- Calcul des minima: |
159 | ----------------- |
160 | b.a) Initialisations: |
161 | */ |
162 | // - generales |
163 | math_Vector Tol(1, 2); |
164 | Tol(1) = myF.Tolerance(); |
165 | Tol(2) = myF.Tolerance(); |
166 | math_Vector UV(1,2), UVinf(1,2), UVsup(1,2); |
167 | UVinf(1) = aCache1->TrimFirstParameter(); |
168 | UVinf(2) = aCache2->TrimFirstParameter(); |
169 | UVsup(1) = aCache1->TrimLastParameter(); |
170 | UVsup(2) = aCache2->TrimLastParameter(); |
171 | |
172 | // - des 'bords' du tableau TbDist2 |
173 | for (NoV = 0; NoV <= aNbV+1; NoV++) { |
174 | TbDist2(0,NoV) = RealLast(); |
175 | TbDist2(aNbU+1,NoV) = RealLast(); |
176 | } |
177 | for (NoU = 1; NoU <= aNbU; NoU++) { |
178 | TbDist2(NoU,0) = RealLast(); |
179 | TbDist2(NoU,aNbV+1) = RealLast(); |
180 | } |
181 | |
182 | // - du tableau TbSel(0,aNbU+1,0,aNbV+1) de selection des points |
183 | TColStd_Array2OfInteger TbSel(0,aNbU+1,0,aNbV+1); |
184 | TbSel.Init(0); |
185 | |
186 | /* |
187 | b.b) Calcul des minima: |
188 | */ |
189 | // - recherche d un minimum sur la grille |
190 | Standard_Integer Nu, Nv; |
191 | Standard_Real Dist2; |
192 | for (NoU = 1; NoU <= aNbU; NoU++) { |
193 | for (NoV = 1; NoV <= aNbV; NoV++) { |
194 | if (TbSel(NoU,NoV) == 0) { |
195 | Dist2 = TbDist2(NoU,NoV); |
196 | if ((TbDist2(NoU-1,NoV-1) >= Dist2) && |
197 | (TbDist2(NoU-1,NoV ) >= Dist2) && |
198 | (TbDist2(NoU-1,NoV+1) >= Dist2) && |
199 | (TbDist2(NoU ,NoV-1) >= Dist2) && |
200 | (TbDist2(NoU ,NoV+1) >= Dist2) && |
201 | (TbDist2(NoU+1,NoV-1) >= Dist2) && |
202 | (TbDist2(NoU+1,NoV ) >= Dist2) && |
203 | (TbDist2(NoU+1,NoV+1) >= Dist2)) { |
204 | |
205 | // - calcul de l extremum sur la surface: |
206 | UV(1) = U0 + (NoU - 1) * PasU; |
207 | UV(2) = V0 + (NoV - 1) * PasV; |
208 | |
209 | |
210 | math_FunctionSetRoot S (myF,UV,Tol,UVinf,UVsup); |
211 | |
212 | |
213 | // - mise a jour du tableau TbSel |
214 | for (Nu = NoU-1; Nu <= NoU+1; Nu++) { |
215 | for (Nv = NoV-1; Nv <= NoV+1; Nv++) { |
216 | TbSel(Nu,Nv) = 1; |
217 | } |
218 | } |
219 | } |
220 | } // if (TbSel(NoU,NoV) |
221 | } // for (NoV = 1; ... |
222 | } // for (NoU = 1; ... |
223 | /* |
224 | c- Calcul des maxima: |
225 | ----------------- |
226 | c.a) Initialisations: |
227 | */ |
228 | // - des 'bords' du tableau TbDist2 |
229 | for (NoV = 0; NoV <= aNbV+1; NoV++) { |
230 | TbDist2(0,NoV) = RealFirst(); |
231 | TbDist2(aNbU+1,NoV) = RealFirst(); |
232 | } |
233 | for (NoU = 1; NoU <= aNbU; NoU++) { |
234 | TbDist2(NoU,0) = RealFirst(); |
235 | TbDist2(NoU,aNbV+1) = RealFirst(); |
236 | } |
237 | |
238 | // - du tableau TbSel(0,aNbU+1,0,aNbV+1) de selection des points |
239 | TbSel.Init(0); |
240 | /*for (NoU = 0; NoU <= aNbU+1; NoU++) { |
241 | for (NoV = 0; NoV <= aNbV+1; NoV++) { |
242 | TbSel(NoU,NoV) = 0; |
243 | } |
244 | }*/ |
245 | /* |
246 | c.b) Calcul des maxima: |
247 | */ |
248 | // - recherche d un maximum sur la grille |
249 | for (NoU = 1; NoU <= aNbU; NoU++) { |
250 | for (NoV = 1; NoV <= aNbV; NoV++) { |
251 | if (TbSel(NoU,NoV) == 0) { |
252 | Dist2 = TbDist2(NoU,NoV); |
253 | if ((TbDist2(NoU-1,NoV-1) <= Dist2) && |
254 | (TbDist2(NoU-1,NoV ) <= Dist2) && |
255 | (TbDist2(NoU-1,NoV+1) <= Dist2) && |
256 | (TbDist2(NoU ,NoV-1) <= Dist2) && |
257 | (TbDist2(NoU ,NoV+1) <= Dist2) && |
258 | (TbDist2(NoU+1,NoV-1) <= Dist2) && |
259 | (TbDist2(NoU+1,NoV ) <= Dist2) && |
260 | (TbDist2(NoU+1,NoV+1) <= Dist2)) { |
261 | |
262 | // - calcul de l extremum sur la surface: |
263 | UV(1) = U0 + (NoU - 1) * PasU; |
264 | UV(2) = V0 + (NoV - 1) * PasV; |
265 | |
266 | math_FunctionSetRoot S (myF,UV,Tol,UVinf,UVsup); |
267 | |
268 | // - mise a jour du tableau TbSel |
269 | for (Nu = NoU-1; Nu <= NoU+1; Nu++) { |
270 | for (Nv = NoV-1; Nv <= NoV+1; Nv++) { |
271 | TbSel(Nu,Nv) = 1; |
272 | } |
273 | } |
274 | } |
275 | } // if (TbSel(NoU,NoV)) |
276 | } // for (NoV = 1; ...) |
277 | } // for (NoU = 1; ...) |
278 | myDone = Standard_True; |
279 | } |
280 | //============================================================================= |
281 | |
282 | Standard_Boolean Extrema_GenExtCC::IsDone () const { return myDone; } |
283 | //============================================================================= |
284 | |
285 | Standard_Integer Extrema_GenExtCC::NbExt () const |
286 | { |
287 | StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::NbExt()") |
288 | return myF.NbExt(); |
289 | } |
290 | //============================================================================= |
291 | |
292 | Standard_Real Extrema_GenExtCC::SquareDistance (const Standard_Integer N) const |
293 | { |
294 | StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()") |
295 | Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()") |
296 | return myF.SquareDistance(N); |
297 | } |
298 | //============================================================================= |
299 | |
300 | void Extrema_GenExtCC::Points (const Standard_Integer N, |
301 | POnC& P1, POnC& P2) const |
302 | { |
303 | StdFail_NotDone_Raise_if (!myDone, "Extrema_GenExtCC::SquareDistance()") |
304 | Standard_OutOfRange_Raise_if ((N < 1 || N > NbExt()), "Extrema_GenExtCC::SquareDistance()") |
305 | myF.Points(N,P1,P2); |
306 | } |