Commit | Line | Data |
---|---|---|
973c2be1 | 1 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e | 2 | // |
973c2be1 | 3 | // This file is part of Open CASCADE Technology software library. |
b311480e | 4 | // |
d5f74e42 | 5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
9 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 10 | // |
973c2be1 | 11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. | |
b311480e | 13 | |
7fd59977 | 14 | // 06.01.99 pdn private method SurfaceNewton PRO17015: fix against hang in Extrema |
15 | // 11.01.99 pdn PRO10109 4517: protect against wrong result | |
16 | //%12 pdn 11.02.99 PRO9234 project degenerated | |
17 | // 03.03.99 rln S4135: new algorithms for IsClosed (accepts precision), Degenerated (stores precision) | |
18 | //:p7 abv 10.03.99 PRO18206: adding new method IsDegenerated() | |
19 | //:p8 abv 11.03.99 PRO7226 #489490: improving ProjectDegenerated() for degenerated edges | |
20 | //:q1 pdn, abv 15.03.99 PRO7226 #525030: adding maxpreci in NextValueOfUV() | |
21 | //:q2 abv 16.03.99: PRO7226 #412920: applying Newton algorithm before UVFromIso() | |
22 | //:q6 abv 19.03.99: ie_soapbox-B.stp #390760: improving projecting point on surface | |
23 | //#77 rln 15.03.99: S4135: returning singularity which has minimum gap between singular point and input 3D point | |
24 | //:r3 abv 30.03.99: (by smh) S4163: protect against unexpected signals | |
25 | //:#4 smh 07.04.99: S4163 Zero divide. | |
26 | //#4 szv S4163: optimizations | |
27 | //:r9 abv 09.04.99: id_turbine-C.stp #3865: check degenerated 2d point by recomputing to 3d instead of Resolution | |
28 | //:s5 abv 22.04.99 Adding debug printouts in catch {} blocks | |
29 | #include <ShapeAnalysis_Surface.ixx> | |
30 | ||
31 | #include <Geom_BoundedSurface.hxx> | |
32 | #include <Geom_BSplineSurface.hxx> | |
33 | #include <Geom_BezierSurface.hxx> //S4135 | |
34 | #include <Geom_ConicalSurface.hxx> | |
35 | #include <Geom_OffsetSurface.hxx> //S4135 | |
36 | #include <Geom_RectangularTrimmedSurface.hxx> | |
37 | #include <Geom_SphericalSurface.hxx> | |
38 | #include <Geom_SurfaceOfLinearExtrusion.hxx> | |
39 | #include <Geom_SurfaceOfRevolution.hxx> | |
40 | #include <Geom_ToroidalSurface.hxx> | |
41 | ||
42 | #include <ElSLib.hxx> | |
43 | ||
44 | #include <Precision.hxx> | |
45 | ||
46 | #include <ShapeAnalysis_Curve.hxx> | |
47 | ||
48 | #include <Standard_ErrorHandler.hxx> | |
49 | #include <Standard_Failure.hxx> | |
50 | #include <Standard_NoSuchObject.hxx> | |
51 | #include <ShapeAnalysis.hxx> | |
52 | ||
53 | #include <Adaptor3d_Curve.hxx> | |
54 | #include <GeomAdaptor_Curve.hxx> | |
55 | #include <Adaptor3d_IsoCurve.hxx> | |
56 | ||
57 | #include <GeomAbs_SurfaceForm.hxx> | |
58 | #include <BndLib_Add3dCurve.hxx> | |
59 | ||
60 | ||
61 | //======================================================================= | |
62 | //function : ShapeAnalysis_Surface | |
63 | //purpose : | |
64 | //======================================================================= | |
65 | ||
66 | ShapeAnalysis_Surface::ShapeAnalysis_Surface(const Handle(Geom_Surface)& S) : | |
67 | mySurf (S), | |
68 | myExtOK(Standard_False), //:30 | |
69 | myNbDeg (-1), | |
70 | myIsos (Standard_False), | |
71 | myIsoBoxes (Standard_False), | |
72 | myGap (0.), myUDelt (0.01), myVDelt (0.01), myUCloseVal (-1), myVCloseVal (-1) | |
73 | { | |
74 | S->Bounds(myUF,myUL,myVF,myVL); | |
75 | } | |
76 | ||
77 | //======================================================================= | |
78 | //function : Init | |
79 | //purpose : | |
80 | //======================================================================= | |
81 | ||
82 | void ShapeAnalysis_Surface::Init(const Handle(Geom_Surface)& S) | |
83 | { | |
84 | if (mySurf == S) return; | |
85 | myExtOK = Standard_False; //:30 | |
86 | mySurf = S; myAdSur.Nullify(); | |
87 | myNbDeg = -1; | |
88 | myUCloseVal = myVCloseVal = -1; myGap = 0.; | |
89 | mySurf->Bounds (myUF,myUL,myVF,myVL); | |
90 | myIsos = Standard_False; | |
91 | myIsoBoxes = Standard_False; | |
92 | myIsoUF.Nullify(); myIsoUL.Nullify(); myIsoVF.Nullify(); myIsoVL.Nullify(); | |
93 | } | |
94 | ||
95 | //======================================================================= | |
96 | //function : Init | |
97 | //purpose : | |
98 | //======================================================================= | |
99 | ||
100 | void ShapeAnalysis_Surface::Init(const Handle(ShapeAnalysis_Surface)& other) | |
101 | { | |
102 | Init (other->Surface()); | |
103 | myAdSur = other->TrueAdaptor3d(); | |
104 | myNbDeg = other->myNbDeg; //rln S4135 direct transmission (to avoid computation in <other>) | |
105 | for (Standard_Integer i = 0; i < myNbDeg; i ++) { | |
106 | other->Singularity (i+1, myPreci[i], myP3d[i], myFirstP2d[i], myLastP2d[i], myFirstPar[i], myLastPar[i], myUIsoDeg[i]); | |
107 | } | |
108 | } | |
109 | ||
110 | //======================================================================= | |
111 | //function : Adaptor3d | |
112 | //purpose : | |
113 | //======================================================================= | |
114 | ||
115 | const Handle(GeomAdaptor_HSurface)& ShapeAnalysis_Surface::Adaptor3d() | |
116 | { | |
117 | if (myAdSur.IsNull() && !mySurf.IsNull()) | |
118 | myAdSur = new GeomAdaptor_HSurface (mySurf); | |
119 | return myAdSur; | |
120 | } | |
121 | ||
122 | //======================================================================= | |
123 | //function : ComputeSingularities | |
124 | //purpose : | |
125 | //======================================================================= | |
126 | ||
127 | void ShapeAnalysis_Surface::ComputeSingularities() | |
128 | { | |
129 | //rln S4135 | |
130 | if (myNbDeg >= 0) return; | |
131 | //:51 abv 22 Dec 97: allow forcing: if (myNbDeg >= 0) return; | |
132 | //CKY 27-FEV-98 : en appel direct on peut forcer. En appel interne on optimise | |
133 | if (mySurf.IsNull()) return; | |
134 | ||
135 | Standard_Real su1, sv1, su2, sv2; | |
136 | // mySurf->Bounds(su1, su2, sv1, sv2); | |
137 | Bounds(su1, su2, sv1, sv2);//modified by rln on 12/11/97 mySurf-> is deleted | |
138 | ||
139 | myNbDeg = 0; //:r3 | |
140 | ||
141 | if (mySurf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) { | |
142 | Handle(Geom_ConicalSurface) conicS = | |
143 | Handle(Geom_ConicalSurface)::DownCast(mySurf); | |
144 | Standard_Real vApex = - conicS->RefRadius() / Sin (conicS->SemiAngle()); | |
145 | myPreci [0] = 0; | |
146 | myP3d [0] = conicS->Apex(); | |
147 | myFirstP2d[0].SetCoord (su1, vApex); | |
148 | myLastP2d [0].SetCoord (su2, vApex); | |
149 | myFirstPar[0] = su1; | |
150 | myLastPar [0] = su2; | |
151 | myUIsoDeg [0] = Standard_False; | |
152 | myNbDeg = 1; | |
153 | } | |
154 | else if (mySurf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) { | |
155 | Handle(Geom_ToroidalSurface) toroidS = | |
156 | Handle(Geom_ToroidalSurface)::DownCast(mySurf); | |
157 | Standard_Real minorR = toroidS->MinorRadius(); | |
158 | Standard_Real majorR = toroidS->MajorRadius(); | |
159 | //szv#4:S4163:12Mar99 warning - possible div by zero | |
160 | Standard_Real Ang = ACos (Min (1., majorR / minorR)); | |
161 | myPreci [0] = myPreci[1] = Max (0., majorR - minorR); | |
c6541a0c D |
162 | myP3d [0] = mySurf->Value (0., M_PI-Ang); |
163 | myFirstP2d[0].SetCoord (su1, M_PI-Ang); | |
164 | myLastP2d [0].SetCoord (su2, M_PI-Ang); | |
165 | myP3d [1] = mySurf->Value (0., M_PI+Ang); | |
166 | myFirstP2d[1].SetCoord (su2, M_PI+Ang); | |
167 | myLastP2d [1].SetCoord (su1, M_PI+Ang); | |
7fd59977 | 168 | myFirstPar[0] = myFirstPar[1] = su1; |
169 | myLastPar [0] = myLastPar [1] = su2; | |
170 | myUIsoDeg [0] = myUIsoDeg [1] = Standard_False; | |
171 | myNbDeg = ( majorR > minorR ? 1 : 2 ); | |
172 | } | |
173 | else if (mySurf->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) { | |
174 | myPreci [0] = myPreci[1] = 0; | |
175 | myP3d [0] = mySurf->Value ( su1, sv2 ); // Northern pole is first | |
176 | myP3d [1] = mySurf->Value ( su1, sv1 ); | |
177 | myFirstP2d[0].SetCoord (su2, sv2); | |
178 | myLastP2d [0].SetCoord (su1, sv2); | |
179 | myFirstP2d[1].SetCoord (su1, sv1); | |
180 | myLastP2d [1].SetCoord (su2, sv1); | |
181 | myFirstPar[0] = myFirstPar[1] = su1; | |
182 | myLastPar [0] = myLastPar [1] = su2; | |
183 | myUIsoDeg [0] = myUIsoDeg [1] = Standard_False; | |
184 | myNbDeg = 2; | |
185 | } | |
186 | else if ((mySurf->IsKind(STANDARD_TYPE(Geom_BoundedSurface))) || | |
187 | (mySurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) || //:b2 abv 18 Feb 98 | |
188 | (mySurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))) { //rln S4135 | |
189 | ||
190 | //rln S4135 //:r3 | |
191 | myP3d [0] = mySurf->Value (su1, 0.5 * (sv1 + sv2)); | |
192 | myFirstP2d[0].SetCoord (su1, sv2); | |
193 | myLastP2d [0].SetCoord (su1, sv1); | |
194 | ||
195 | myP3d [1] = mySurf->Value (su2, 0.5 * (sv1 + sv2)); | |
196 | myFirstP2d[1].SetCoord (su2, sv1); | |
197 | myLastP2d [1].SetCoord (su2, sv2); | |
198 | ||
199 | myP3d [2] = mySurf->Value (0.5 * (su1 + su2), sv1); | |
200 | myFirstP2d[2].SetCoord (su1, sv1); | |
201 | myLastP2d [2].SetCoord (su2, sv1); | |
202 | ||
203 | myP3d [3] = mySurf->Value (0.5 * (su1 + su2), sv2); | |
204 | myFirstP2d[3].SetCoord (su2, sv2); | |
205 | myLastP2d [3].SetCoord (su1, sv2); | |
206 | ||
207 | myFirstPar[0] = myFirstPar[1] = sv1; | |
208 | myLastPar [0] = myLastPar [1] = sv2; | |
209 | myUIsoDeg [0] = myUIsoDeg [1] = Standard_True; | |
210 | ||
211 | myFirstPar[2] = myFirstPar[3] = su1; | |
212 | myLastPar [2] = myLastPar [3] = su2; | |
213 | myUIsoDeg [2] = myUIsoDeg [3] = Standard_False; | |
214 | ||
215 | gp_Pnt Corner1 = mySurf->Value(su1,sv1); | |
216 | gp_Pnt Corner2 = mySurf->Value(su1,sv2); | |
217 | gp_Pnt Corner3 = mySurf->Value(su2,sv1); | |
218 | gp_Pnt Corner4 = mySurf->Value(su2,sv2); | |
219 | ||
220 | myPreci[0] = Max (Corner1.Distance(Corner2), Max (myP3d[0].Distance(Corner1), myP3d[0].Distance(Corner2))); | |
221 | myPreci[1] = Max (Corner3.Distance(Corner4), Max (myP3d[1].Distance(Corner3), myP3d[1].Distance(Corner4))); | |
222 | myPreci[2] = Max (Corner1.Distance(Corner3), Max (myP3d[2].Distance(Corner1), myP3d[2].Distance(Corner3))); | |
223 | myPreci[3] = Max (Corner2.Distance(Corner4), Max (myP3d[3].Distance(Corner2), myP3d[3].Distance(Corner4))); | |
224 | ||
225 | myNbDeg = 4; | |
226 | } | |
227 | SortSingularities(); | |
228 | } | |
229 | ||
230 | //======================================================================= | |
231 | //function : HasSingularities | |
232 | //purpose : | |
233 | //======================================================================= | |
234 | ||
235 | Standard_Boolean ShapeAnalysis_Surface::HasSingularities (const Standard_Real preci) | |
236 | { | |
237 | return NbSingularities(preci) > 0; | |
238 | } | |
239 | ||
240 | //======================================================================= | |
241 | //function : NbSingularities | |
242 | //purpose : | |
243 | //======================================================================= | |
244 | ||
245 | Standard_Integer ShapeAnalysis_Surface::NbSingularities(const Standard_Real preci) | |
246 | { | |
247 | if (myNbDeg < 0) ComputeSingularities(); | |
248 | Standard_Integer Nb = 0; | |
249 | for (Standard_Integer i = 1; i <= myNbDeg; i++) | |
250 | if (myPreci[i-1] <= preci) | |
251 | Nb++; | |
252 | return Nb; | |
253 | } | |
254 | ||
255 | //======================================================================= | |
256 | //function : Singularity | |
257 | //purpose : | |
258 | //======================================================================= | |
259 | ||
260 | Standard_Boolean ShapeAnalysis_Surface::Singularity(const Standard_Integer num, | |
261 | Standard_Real& preci, | |
262 | gp_Pnt& P3d, | |
263 | gp_Pnt2d& firstP2d, | |
264 | gp_Pnt2d& lastP2d, | |
265 | Standard_Real& firstpar, | |
266 | Standard_Real& lastpar, | |
267 | Standard_Boolean& uisodeg) | |
268 | { | |
269 | // ATTENTION, les champs sont des tableaux C, n0s partent de 0. num part de 1 | |
270 | if (myNbDeg < 0) ComputeSingularities(); | |
271 | if (num < 1 || num > myNbDeg) return Standard_False; | |
272 | P3d = myP3d [num-1]; | |
273 | preci = myPreci [num-1]; | |
274 | firstP2d = myFirstP2d [num-1]; | |
275 | lastP2d = myLastP2d [num-1]; | |
276 | firstpar = myFirstPar [num-1]; | |
277 | lastpar = myLastPar [num-1]; | |
278 | uisodeg = myUIsoDeg [num-1]; | |
279 | return Standard_True; | |
280 | } | |
281 | ||
282 | //======================================================================= | |
283 | //function : IsDegenerated | |
284 | //purpose : | |
285 | //======================================================================= | |
286 | ||
287 | Standard_Boolean ShapeAnalysis_Surface::IsDegenerated(const gp_Pnt& P3d,const Standard_Real preci) | |
288 | { | |
289 | if (myNbDeg < 0) ComputeSingularities (); | |
290 | for (Standard_Integer i = 0; i < myNbDeg && myPreci[i] <= preci; i ++) { | |
291 | myGap = myP3d[i].Distance (P3d); | |
292 | //rln S4135 | |
293 | if (myGap <= preci) | |
294 | return Standard_True; | |
295 | } | |
296 | return Standard_False; | |
297 | } | |
298 | ||
299 | //======================================================================= | |
300 | //function : DegeneratedValues | |
301 | //purpose : | |
302 | //======================================================================= | |
303 | ||
304 | Standard_Boolean ShapeAnalysis_Surface::DegeneratedValues(const gp_Pnt& P3d, | |
305 | const Standard_Real preci, | |
306 | gp_Pnt2d& firstP2d, | |
307 | gp_Pnt2d& lastP2d, | |
308 | Standard_Real& firstPar, | |
309 | Standard_Real& lastPar, | |
310 | const Standard_Boolean /*forward*/) | |
311 | { | |
312 | if (myNbDeg < 0) ComputeSingularities (); | |
313 | //#77 rln S4135: returning singularity which has minimum gap between singular point and input 3D point | |
314 | Standard_Integer indMin = -1; | |
315 | Standard_Real gapMin = RealLast(); | |
316 | for (Standard_Integer i = 0; i < myNbDeg && myPreci[i] <= preci; i ++) { | |
317 | myGap = myP3d[i].Distance (P3d); | |
318 | //rln S4135 | |
319 | if (myGap <= preci) | |
320 | if (gapMin > myGap) { | |
321 | gapMin = myGap; | |
322 | indMin = i; | |
323 | } | |
324 | } | |
325 | if (indMin >= 0) { | |
326 | myGap = gapMin; | |
327 | firstP2d = myFirstP2d[indMin]; | |
328 | lastP2d = myLastP2d[indMin]; | |
329 | firstPar = myFirstPar[indMin]; | |
330 | lastPar = myLastPar[indMin]; | |
331 | return Standard_True; | |
332 | } | |
333 | return Standard_False; | |
334 | } | |
335 | ||
336 | //======================================================================= | |
337 | //function : ProjectDegenerated | |
338 | //purpose : | |
339 | //======================================================================= | |
340 | ||
341 | Standard_Boolean ShapeAnalysis_Surface::ProjectDegenerated(const gp_Pnt& P3d, | |
342 | const Standard_Real preci, | |
343 | const gp_Pnt2d& neighbour, | |
344 | gp_Pnt2d& result) | |
345 | { | |
346 | if (myNbDeg < 0) ComputeSingularities (); | |
347 | //added by rln on 03/12/97 | |
348 | //:c1 abv 23 Feb 98: preci (3d) -> Resolution (2d) | |
349 | //#77 rln S4135 | |
350 | Standard_Integer indMin = -1; | |
351 | Standard_Real gapMin = RealLast(); | |
352 | for (Standard_Integer i = 0; i < myNbDeg && myPreci[i] <= preci; i ++) { | |
353 | Standard_Real gap2 = myP3d[i].SquareDistance (P3d); | |
354 | if ( gap2 > preci*preci ) | |
355 | gap2 = Min ( gap2, myP3d[i].SquareDistance ( Value(result) ) ); | |
356 | //rln S4135 | |
357 | if ( gap2 <= preci*preci && gapMin > gap2 ) { | |
358 | gapMin = gap2; | |
359 | indMin = i; | |
360 | } | |
361 | } | |
362 | if ( indMin < 0 ) return Standard_False; | |
363 | myGap = Sqrt ( gapMin ); | |
364 | if ( ! myUIsoDeg[indMin] ) result.SetX (neighbour.X()); | |
365 | else result.SetY (neighbour.Y()); | |
366 | return Standard_True; | |
367 | } | |
368 | ||
369 | //pdn %12 11.02.99 PRO9234 entity 15402 | |
370 | //======================================================================= | |
371 | //function : ProjectDegenerated | |
372 | //purpose : | |
373 | //======================================================================= | |
374 | ||
375 | Standard_Boolean ShapeAnalysis_Surface::ProjectDegenerated(const Standard_Integer nbrPnt, | |
376 | const TColgp_Array1OfPnt& points, | |
377 | TColgp_Array1OfPnt2d& pnt2d, | |
378 | const Standard_Real preci, | |
379 | const Standard_Boolean direct) | |
380 | { | |
381 | if (myNbDeg < 0) ComputeSingularities (); | |
382 | ||
383 | Standard_Integer step = (direct ? 1 : -1); | |
384 | //#77 rln S4135 | |
385 | Standard_Integer indMin = -1; | |
386 | Standard_Real gapMin = RealLast(), prec2 = preci*preci; | |
387 | Standard_Integer j = (direct ? 1 : nbrPnt); | |
388 | for (Standard_Integer i = 0; i < myNbDeg && myPreci[i] <= preci; i ++) { | |
389 | Standard_Real gap2 = myP3d[i].SquareDistance (points(j)); | |
390 | if ( gap2 > prec2 ) | |
391 | gap2 = Min ( gap2, myP3d[i].SquareDistance ( Value(pnt2d(j)) ) ); | |
392 | if ( gap2 <= prec2 && gapMin > gap2 ) { | |
393 | gapMin = gap2; | |
394 | indMin = i; | |
395 | } | |
396 | } | |
397 | if ( indMin <0 ) return Standard_False; | |
398 | ||
399 | myGap = Sqrt ( gapMin ); | |
400 | gp_Pnt2d pk; | |
401 | ||
402 | Standard_Integer k; // svv Jan11 2000 : porting on DEC | |
403 | for ( k=j+step; k <= nbrPnt && k >= 1; k += step ) { | |
404 | pk = pnt2d(k); | |
405 | gp_Pnt P1 = points(k); | |
406 | if ( myP3d[indMin].SquareDistance(P1) > prec2 && | |
407 | myP3d[indMin].SquareDistance(Value(pk)) > prec2 ) | |
408 | break; | |
409 | } | |
410 | ||
411 | //:p8 abv 11 Mar 99: PRO7226 #489490: if whole pcurve is degenerate, distribute evenly | |
412 | if ( k <1 || k > nbrPnt ) { | |
413 | Standard_Real x1 = ( myUIsoDeg[indMin] ? pnt2d(1).Y() : pnt2d(1).X() ); | |
414 | Standard_Real x2 = ( myUIsoDeg[indMin] ? pnt2d(nbrPnt).Y() : pnt2d(nbrPnt).X() ); | |
415 | for ( j = 1; j <= nbrPnt; j++ ) { | |
416 | //szv#4:S4163:12Mar99 warning - possible div by zero | |
417 | Standard_Real x = ( x1 * ( nbrPnt - j ) + x2 * ( j - 1 ) ) / ( nbrPnt - 1 ); | |
418 | if ( ! myUIsoDeg[indMin] ) pnt2d(j).SetX ( x ); | |
419 | else pnt2d(j).SetY ( x ); | |
420 | } | |
421 | return Standard_True; | |
422 | } | |
423 | ||
424 | for ( j = k-step; j <= nbrPnt && j >= 1; j -= step) { | |
425 | if (!myUIsoDeg[indMin]) pnt2d(j).SetX (pk.X()); | |
426 | else pnt2d(j).SetY (pk.Y()); | |
427 | } | |
428 | return Standard_True; | |
429 | } | |
430 | ||
431 | //======================================================================= | |
432 | //method : IsDegenerated | |
433 | //purpose: | |
434 | //======================================================================= | |
435 | ||
436 | Standard_Boolean ShapeAnalysis_Surface::IsDegenerated (const gp_Pnt2d &p2d1, | |
437 | const gp_Pnt2d &p2d2, | |
438 | const Standard_Real tol, | |
439 | const Standard_Real ratio) | |
440 | { | |
441 | gp_Pnt p1 = Value ( p2d1 ); | |
442 | gp_Pnt p2 = Value ( p2d2 ); | |
443 | gp_Pnt pm = Value ( 0.5 * ( p2d1.XY() + p2d2.XY() ) ); | |
444 | Standard_Real max3d = Max ( p1.Distance ( p2 ), | |
445 | Max ( pm.Distance ( p1 ), pm.Distance ( p2 ) ) ); | |
446 | if ( max3d > tol ) return Standard_False; | |
447 | ||
448 | GeomAdaptor_Surface& SA = Adaptor3d()->ChangeSurface(); | |
449 | Standard_Real RU = SA.UResolution ( 1. ); | |
450 | Standard_Real RV = SA.VResolution ( 1. ); | |
451 | ||
452 | if ( RU < Precision::PConfusion() || RV < Precision::PConfusion() ) return 0; | |
453 | Standard_Real du = Abs ( p2d1.X() - p2d2.X() ) / RU; | |
454 | Standard_Real dv = Abs ( p2d1.Y() - p2d2.Y() ) / RV; | |
455 | max3d *= ratio; | |
456 | return du * du + dv * dv > max3d * max3d; | |
457 | } | |
458 | ||
459 | //======================================================================= | |
460 | //static : ComputeIso | |
461 | //purpose : | |
462 | //======================================================================= | |
463 | ||
464 | static Handle(Geom_Curve) ComputeIso | |
465 | (const Handle(Geom_Surface)& surf, | |
466 | const Standard_Boolean utype, const Standard_Real par) | |
467 | { | |
468 | Handle(Geom_Curve) iso; | |
469 | try { | |
470 | OCC_CATCH_SIGNALS | |
471 | if (utype) iso = surf->UIso (par); | |
472 | else iso = surf->VIso (par); | |
473 | } | |
474 | catch(Standard_Failure) { | |
475 | iso.Nullify(); | |
0797d9d3 | 476 | #ifdef OCCT_DEBUG //:s5 |
7fd59977 | 477 | cout << "\nWarning: ShapeAnalysis_Surface, ComputeIso(): Exception in UVIso(): "; |
478 | Standard_Failure::Caught()->Print(cout); cout << endl; | |
479 | #endif | |
480 | } | |
481 | return iso; | |
482 | } | |
483 | ||
484 | //======================================================================= | |
485 | //function : ComputeBoundIsos | |
486 | //purpose : | |
487 | //======================================================================= | |
488 | ||
489 | void ShapeAnalysis_Surface::ComputeBoundIsos() | |
490 | { | |
491 | if (myIsos) return; | |
492 | myIsos = Standard_True; | |
493 | myIsoUF = ComputeIso (mySurf,Standard_True, myUF); | |
494 | myIsoUL = ComputeIso (mySurf,Standard_True, myUL); | |
495 | myIsoVF = ComputeIso (mySurf,Standard_False,myVF); | |
496 | myIsoVL = ComputeIso (mySurf,Standard_False,myVL); | |
497 | } | |
498 | ||
499 | //======================================================================= | |
500 | //function : UIso | |
501 | //purpose : | |
502 | //======================================================================= | |
503 | ||
504 | Handle(Geom_Curve) ShapeAnalysis_Surface::UIso(const Standard_Real U) | |
505 | { | |
506 | if (U == myUF) { ComputeBoundIsos(); return myIsoUF; } | |
507 | if (U == myUL) { ComputeBoundIsos(); return myIsoUL; } | |
508 | return ComputeIso (mySurf,Standard_True, U); | |
509 | } | |
510 | ||
511 | //======================================================================= | |
512 | //function : VIso | |
513 | //purpose : | |
514 | //======================================================================= | |
515 | ||
516 | Handle(Geom_Curve) ShapeAnalysis_Surface::VIso(const Standard_Real V) | |
517 | { | |
518 | if (V == myVF) { ComputeBoundIsos(); return myIsoVF; } | |
519 | if (V == myVL) { ComputeBoundIsos(); return myIsoVL; } | |
520 | return ComputeIso (mySurf,Standard_False,V); | |
521 | } | |
522 | ||
523 | //======================================================================= | |
524 | //function : IsUClosed | |
525 | //purpose : | |
526 | //======================================================================= | |
527 | ||
528 | Standard_Boolean ShapeAnalysis_Surface::IsUClosed(const Standard_Real preci) | |
529 | { | |
530 | Standard_Real prec = Max (preci, Precision::Confusion()); | |
531 | if (myUCloseVal < 0) { | |
532 | // Faut calculer : calculs minimaux | |
533 | Standard_Real uf,ul,vf,vl; | |
534 | Bounds (uf,ul,vf,vl);//modified by rln on 12/11/97 mySurf-> is deleted | |
535 | // mySurf->Bounds (uf,ul,vf,vl); | |
536 | if (Precision::IsInfinite (uf) || Precision::IsInfinite (ul)) myUDelt = 0.; | |
537 | else myUDelt = Abs (ul-uf) / 20;//modified by rln 11/11/97 instead of 10 | |
538 | //because of the example when 10 was not enough | |
539 | if (mySurf->IsUClosed()) { myUCloseVal = 0.; myUDelt = 0.; myGap = 0.; return Standard_True; } | |
540 | ||
541 | // Calculs adaptes | |
542 | //#67 rln S4135 | |
543 | GeomAdaptor_Surface& SurfAdapt = Adaptor3d()->ChangeSurface(); | |
544 | GeomAbs_SurfaceType surftype = SurfAdapt.GetType(); | |
545 | if (mySurf->IsKind (STANDARD_TYPE (Geom_RectangularTrimmedSurface))) | |
546 | surftype = GeomAbs_OtherSurface; | |
547 | ||
548 | switch (surftype) { | |
549 | case GeomAbs_Plane: { | |
550 | myUCloseVal = RealLast(); | |
551 | break; | |
552 | } | |
553 | case GeomAbs_SurfaceOfExtrusion: { //:c8 abv 03 Mar 98: UKI60094 #753: process Geom_SurfaceOfLinearExtrusion | |
554 | Handle(Geom_SurfaceOfLinearExtrusion) extr = | |
555 | Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(mySurf); | |
556 | Handle(Geom_Curve) crv = extr->BasisCurve(); | |
557 | Standard_Real f = crv->FirstParameter(); | |
558 | Standard_Real l = crv->LastParameter(); | |
559 | //:r3 abv (smh) 30 Mar 99: protect against unexpected signals | |
560 | if ( ! Precision::IsInfinite ( f ) && ! Precision::IsInfinite ( l ) ) { | |
561 | gp_Pnt p1 = crv->Value ( f ); | |
562 | gp_Pnt p2 = crv->Value ( l ); | |
563 | myUCloseVal = p1.Distance ( p2 ); | |
564 | } | |
565 | else myUCloseVal = RealLast(); | |
566 | break; | |
567 | } | |
568 | case GeomAbs_BSplineSurface: { | |
569 | Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(mySurf); | |
570 | Standard_Integer nbup = bs->NbUPoles(); | |
571 | Standard_Real distmin = RealLast(); | |
572 | if (bs->IsUPeriodic()) { | |
573 | myUCloseVal = 0; | |
574 | myUDelt = 0; | |
575 | } | |
576 | else if (nbup < 3) {//modified by rln on 12/11/97 | |
577 | myUCloseVal = RealLast(); | |
578 | } | |
579 | else if (bs->IsURational() || | |
580 | //#6 rln 20/02/98 ProSTEP ug_exhaust-A.stp entity #18360 (Uclosed BSpline, | |
581 | //but multiplicity of boundary knots != degree + 1) | |
582 | bs->UMultiplicity(1) != bs->UDegree()+1 || //#6 //:h4: #6 moved | |
583 | bs->UMultiplicity(bs->NbUKnots()) != bs->UDegree()+1 ) { //#6 //:h4 | |
584 | Standard_Integer nbvk = bs->NbVKnots(); | |
585 | for (Standard_Integer i = 1; i <= nbvk; i ++) { | |
586 | Standard_Real v = bs->VKnot(i); | |
587 | gp_Pnt p1 = bs->Value (uf, v); | |
588 | gp_Pnt p2 = bs->Value (ul, v); | |
589 | myUCloseVal = Max (myUCloseVal, p1.SquareDistance (p2)); | |
590 | distmin = Min (distmin, p1.SquareDistance (p2)); | |
591 | if (i > 1) { | |
592 | v = 0.5 * (bs->VKnot(i-1) + bs->VKnot(i)); | |
593 | p1 = bs->Value (uf, v); | |
594 | p2 = bs->Value (ul, v); | |
595 | myUCloseVal = Max (myUCloseVal, p1.SquareDistance (p2)); | |
596 | distmin = Min (distmin, p1.SquareDistance (p2)); | |
597 | } | |
598 | } | |
599 | myUCloseVal = Sqrt (myUCloseVal); | |
600 | distmin = Sqrt (distmin); | |
601 | myUDelt = Min (myUDelt, 0.5 * SurfAdapt.UResolution(distmin)); //#4 smh | |
602 | } | |
603 | else { | |
604 | Standard_Integer nbvp = bs->NbVPoles(); | |
605 | for (Standard_Integer i = 1; i <= nbvp; i ++) { | |
606 | myUCloseVal = Max (myUCloseVal, bs->Pole(1,i).SquareDistance(bs->Pole(nbup,i))); | |
607 | distmin = Min (distmin, bs->Pole(1,i).SquareDistance(bs->Pole(nbup,i))); | |
608 | } | |
609 | myUCloseVal = Sqrt (myUCloseVal); | |
610 | distmin = Sqrt (distmin); | |
611 | myUDelt = Min (myUDelt, 0.5 * SurfAdapt.UResolution(distmin)); //#4 smh | |
612 | } | |
613 | break; | |
614 | } | |
615 | case GeomAbs_BezierSurface: { | |
616 | Handle(Geom_BezierSurface) bz = Handle(Geom_BezierSurface)::DownCast(mySurf); | |
617 | Standard_Integer nbup = bz->NbUPoles(); | |
618 | Standard_Real distmin = RealLast(); | |
619 | if (nbup < 3) | |
620 | myUCloseVal = RealLast(); | |
621 | else { | |
622 | Standard_Integer nbvp = bz->NbVPoles(); | |
623 | for (Standard_Integer i = 1; i <= nbvp; i ++) { | |
624 | myUCloseVal = Max (myUCloseVal, bz->Pole(1,i).SquareDistance(bz->Pole(nbup,i))); | |
625 | distmin = Min (distmin, bz->Pole(1,i).SquareDistance(bz->Pole(nbup,i))); | |
626 | } | |
627 | myUCloseVal = Sqrt (myUCloseVal); | |
628 | distmin = Sqrt (distmin); | |
629 | myUDelt = Min (myUDelt, 0.5 * SurfAdapt.UResolution(distmin)); //#4 smh | |
630 | } | |
631 | break; | |
632 | } | |
633 | default: { //Geom_RectangularTrimmedSurface and Geom_OffsetSurface | |
634 | Standard_Real distmin = RealLast(); | |
635 | Standard_Integer nbpoints = 101; //can be revised | |
636 | for (Standard_Integer i = 0; i < nbpoints; i++) { | |
637 | gp_Pnt p1 = mySurf->Value (uf, vf + (vl - vf ) * i / (nbpoints - 1)); | |
638 | gp_Pnt p2 = mySurf->Value (ul, vf + (vl - vf ) * i / (nbpoints - 1)); | |
639 | myUCloseVal = Max (myUCloseVal, p1.SquareDistance (p2)); | |
640 | distmin = Min (distmin, p1.SquareDistance (p2)); | |
641 | } | |
642 | myUCloseVal = Sqrt (myUCloseVal); | |
643 | distmin = Sqrt (distmin); | |
644 | myUDelt = Min (myUDelt, 0.5 * SurfAdapt.UResolution(distmin)); //#4 smh | |
645 | break; | |
646 | } | |
647 | } //switch | |
648 | myGap = myUCloseVal; | |
649 | } | |
650 | return (myUCloseVal <= prec); | |
651 | } | |
652 | ||
653 | //======================================================================= | |
654 | //function : IsVClosed | |
655 | //purpose : | |
656 | //======================================================================= | |
657 | ||
658 | Standard_Boolean ShapeAnalysis_Surface::IsVClosed(const Standard_Real preci) | |
659 | { | |
660 | Standard_Real prec = Max (preci, Precision::Confusion()); | |
661 | if (myVCloseVal < 0) { | |
662 | // Faut calculer : calculs minimaux | |
663 | Standard_Real uf,ul,vf,vl; | |
664 | Bounds (uf,ul,vf,vl);//modified by rln on 12/11/97 mySurf-> is deleted | |
665 | // mySurf->Bounds (uf,ul,vf,vl); | |
666 | if (Precision::IsInfinite (vf) || Precision::IsInfinite (vl)) myVDelt = 0.; | |
667 | else myVDelt = Abs (vl-vf) / 20;// 2; rln S4135 | |
668 | //because of the example when 10 was not enough | |
669 | if (mySurf->IsVClosed()) { myVCloseVal = 0.; myVDelt = 0.; myGap = 0.; return Standard_True; } | |
670 | ||
671 | // Calculs adaptes | |
672 | //#67 rln S4135 | |
673 | GeomAdaptor_Surface& SurfAdapt = Adaptor3d()->ChangeSurface(); | |
674 | GeomAbs_SurfaceType surftype = SurfAdapt.GetType(); | |
675 | if (mySurf->IsKind (STANDARD_TYPE (Geom_RectangularTrimmedSurface))) | |
676 | surftype = GeomAbs_OtherSurface; | |
677 | ||
678 | switch (surftype) { | |
679 | case GeomAbs_Plane: | |
680 | case GeomAbs_Cone: | |
681 | case GeomAbs_Cylinder: | |
682 | case GeomAbs_Sphere: | |
683 | case GeomAbs_SurfaceOfExtrusion: { | |
684 | myVCloseVal = RealLast(); | |
685 | break; | |
686 | } | |
687 | case GeomAbs_SurfaceOfRevolution: { | |
688 | Handle(Geom_SurfaceOfRevolution) revol = | |
689 | Handle(Geom_SurfaceOfRevolution)::DownCast(mySurf); | |
690 | Handle(Geom_Curve) crv = revol->BasisCurve(); | |
691 | gp_Pnt p1 = crv->Value ( crv->FirstParameter() ); | |
692 | gp_Pnt p2 = crv->Value ( crv->LastParameter() ); | |
693 | myVCloseVal = p1.Distance ( p2 ); | |
694 | break; | |
695 | } | |
696 | case GeomAbs_BSplineSurface: { | |
697 | Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(mySurf); | |
698 | Standard_Integer nbvp = bs->NbVPoles(); | |
699 | Standard_Real distmin = RealLast(); | |
700 | if (bs->IsVPeriodic()) { | |
701 | myVCloseVal = 0; | |
702 | myVDelt = 0; | |
703 | } | |
704 | else if (nbvp < 3) {//modified by rln on 12/11/97 | |
705 | myVCloseVal = RealLast(); | |
706 | } | |
707 | else if (bs->IsVRational() || | |
708 | bs->VMultiplicity(1) != bs->VDegree()+1 || //#6 //:h4 | |
709 | bs->VMultiplicity(bs->NbVKnots()) != bs->VDegree()+1 ) { //#6 //:h4 | |
710 | Standard_Integer nbuk = bs->NbUKnots(); | |
711 | for (Standard_Integer i = 1; i <= nbuk; i ++) { | |
712 | Standard_Real u = bs->UKnot(i); | |
713 | gp_Pnt p1 = bs->Value (u, vf); | |
714 | gp_Pnt p2 = bs->Value (u, vl); | |
715 | myVCloseVal = Max (myVCloseVal, p1.SquareDistance (p2)); | |
716 | distmin = Min (distmin, p1.SquareDistance (p2)); | |
717 | if (i > 1) { | |
718 | u = 0.5 * (bs->UKnot(i-1) + bs->UKnot(i)); | |
719 | p1 = bs->Value (u, vf); | |
720 | p2 = bs->Value (u, vl); | |
721 | myVCloseVal = Max (myVCloseVal, p1.SquareDistance (p2)); | |
722 | distmin = Min (distmin, p1.SquareDistance (p2)); | |
723 | } | |
724 | } | |
725 | myVCloseVal = Sqrt (myVCloseVal); | |
726 | distmin = Sqrt (distmin); | |
727 | myVDelt = Min (myVDelt, 0.5 * SurfAdapt.VResolution(distmin)); //#4 smh | |
728 | } | |
729 | else { | |
730 | Standard_Integer nbup = bs->NbUPoles(); | |
731 | for (Standard_Integer i = 1; i <= nbup; i ++) { | |
732 | myVCloseVal = Max (myVCloseVal, bs->Pole(i,1).SquareDistance(bs->Pole(i,nbvp))); | |
733 | distmin = Min (distmin, bs->Pole(i,1).SquareDistance(bs->Pole(i,nbvp))); | |
734 | } | |
735 | myVCloseVal = Sqrt (myVCloseVal); | |
736 | distmin = Sqrt (distmin); | |
737 | myVDelt = Min (myVDelt, 0.5 * SurfAdapt.VResolution(distmin)); //#4 smh | |
738 | } | |
739 | break; | |
740 | } | |
741 | case GeomAbs_BezierSurface: { | |
742 | Handle(Geom_BezierSurface) bz = Handle(Geom_BezierSurface)::DownCast(mySurf); | |
743 | Standard_Integer nbvp = bz->NbVPoles(); | |
744 | Standard_Real distmin = RealLast(); | |
745 | if (nbvp < 3) | |
746 | myVCloseVal = RealLast(); | |
747 | else { | |
748 | Standard_Integer nbup = bz->NbUPoles(); | |
749 | for (Standard_Integer i = 1; i <= nbup; i ++) { | |
750 | myVCloseVal = Max (myVCloseVal, bz->Pole(i,1).SquareDistance(bz->Pole(i,nbvp))); | |
751 | distmin = Min (distmin, bz->Pole(i,1).SquareDistance(bz->Pole(i,nbvp))); | |
752 | } | |
753 | myVCloseVal = Sqrt (myVCloseVal); | |
754 | distmin = Sqrt (distmin); | |
755 | myVDelt = Min (myVDelt, 0.5 * SurfAdapt.VResolution(distmin)); //#4 smh | |
756 | } | |
757 | break; | |
758 | } | |
759 | default: { //Geom_RectangularTrimmedSurface and Geom_OffsetSurface | |
760 | Standard_Real distmin = RealLast(); | |
761 | Standard_Integer nbpoints = 101; //can be revised | |
762 | for (Standard_Integer i = 0; i < nbpoints; i++) { | |
763 | gp_Pnt p1 = mySurf->Value (uf + (ul - uf ) * i / (nbpoints - 1), vf); | |
764 | gp_Pnt p2 = mySurf->Value (uf + (ul - uf ) * i / (nbpoints - 1), vl); | |
765 | myVCloseVal = Max (myVCloseVal, p1.SquareDistance (p2)); | |
766 | distmin = Min (distmin, p1.SquareDistance (p2)); | |
767 | } | |
768 | myVCloseVal = Sqrt (myVCloseVal); | |
769 | distmin = Sqrt (distmin); | |
770 | myVDelt = Min (myVDelt, 0.5 * SurfAdapt.VResolution(distmin)); //#4 smh | |
771 | break; | |
772 | } | |
773 | } //switch | |
774 | myGap = myVCloseVal; | |
775 | } | |
776 | return (myVCloseVal <= prec); | |
777 | } | |
778 | ||
779 | //======================================================================= | |
780 | //function : SurfaceNewton | |
781 | //purpose : Newton algo (S4030) | |
782 | //======================================================================= | |
783 | Standard_Boolean ShapeAnalysis_Surface::SurfaceNewton(const gp_Pnt2d &p2dPrev, | |
784 | const gp_Pnt& P3D, | |
785 | const Standard_Real preci, | |
786 | gp_Pnt2d &sol) | |
787 | { | |
788 | GeomAdaptor_Surface& SurfAdapt = Adaptor3d()->ChangeSurface(); | |
789 | Standard_Real uf, ul, vf, vl; | |
790 | Bounds(uf, ul, vf, vl); | |
791 | Standard_Real du = SurfAdapt.UResolution (preci); | |
792 | Standard_Real dv = SurfAdapt.VResolution (preci); | |
793 | Standard_Real UF = uf - du, UL = ul + du; | |
794 | Standard_Real VF = vf - dv, VL = vl + dv; | |
795 | ||
796 | //Standard_Integer fail = 0; | |
797 | Standard_Real Tol = Precision::Confusion(); | |
798 | Standard_Real Tol2 = Tol * Tol;//, rs2p=1e10; | |
799 | Standard_Real U = p2dPrev.X(), V = p2dPrev.Y(); | |
800 | gp_Vec rsfirst = P3D.XYZ() - Value ( U, V ).XYZ(); //pdn | |
801 | for ( Standard_Integer i=0; i < 25; i++ ) { | |
802 | gp_Vec ru, rv, ruu, rvv, ruv; | |
803 | gp_Pnt pnt; | |
804 | mySurf->D2 ( U, V, pnt, ru, rv, ruu, rvv, ruv ); | |
805 | ||
806 | // normal | |
807 | Standard_Real ru2 = ru * ru, rv2 = rv * rv; | |
808 | gp_Vec n = ru ^ rv; | |
809 | Standard_Real nrm2 = n.SquareMagnitude(); | |
810 | if ( nrm2 < 1e-10 ) break; // n == 0, use standard | |
811 | ||
812 | // descriminant | |
813 | gp_Vec rs = P3D.XYZ() - Value ( U, V ).XYZ(); | |
814 | Standard_Real rSuu = ( rs * ruu ); | |
815 | Standard_Real rSvv = ( rs * rvv ); | |
816 | Standard_Real rSuv = ( rs * ruv ); | |
817 | Standard_Real D = -nrm2 + rv2 * rSuu + ru2 * rSvv - | |
818 | 2 * rSuv * (ru*rv) + rSuv*rSuv - rSuu*rSvv; | |
819 | if ( fabs ( D ) < 1e-10 ) break; // bad case; use standard | |
820 | ||
821 | // compute step | |
822 | Standard_Real fract = 1. / D; | |
823 | du = ( rs * ( ( n ^ rv ) + ru * rSvv - rv * rSuv ) ) * fract; | |
824 | dv = ( rs * ( ( ru ^ n ) + rv * rSuu - ru * rSuv ) ) * fract; | |
825 | U += du; | |
826 | V += dv; | |
2e9fd4bc | 827 | if ( U < UF || U > UL || V < VF || V > VL ) break; |
7fd59977 | 828 | // check that iterations do not diverge |
829 | //pdn Standard_Real rs2 = rs.SquareMagnitude(); | |
830 | // if ( rs2 > 4.*rs2p ) break; | |
831 | // rs2p = rs2; | |
832 | ||
833 | // test the step by uv and deviation from the solution | |
834 | Standard_Real aResolution = Max(1e-12,(U+V)*10e-16); | |
835 | if ( fabs ( du ) + fabs ( dv ) > aResolution ) continue; //Precision::PConfusion() continue; | |
836 | ||
2e9fd4bc | 837 | //if ( U < UF || U > UL || V < VF || V > VL ) break; |
7fd59977 | 838 | |
839 | //pdn PRO10109 4517: protect against wrong result | |
840 | Standard_Real rs2 = rs.SquareMagnitude(); | |
841 | if ( rs2 > rsfirst.SquareMagnitude() ) break; | |
842 | ||
843 | Standard_Real rsn = rs * n; | |
844 | if ( rs2 - rsn * rsn / nrm2 > Tol2 ) break; | |
845 | ||
846 | // if ( rs2 > 100 * preci * preci ) { fail = 6; break; } | |
847 | ||
848 | // OK, return the result | |
849 | // cout << "Newton: solution found in " << i+1 << " iterations" << endl; | |
850 | sol.SetCoord( U, V ); | |
851 | ||
852 | return ( nrm2 < 0.01 * ru2 * rv2 ? 2 : Standard_True ); //:q6 | |
853 | } | |
854 | // cout << "Newton: failed after " << i+1 << " iterations (fail " << fail << " )" << endl; | |
855 | return Standard_False; | |
856 | } | |
857 | ||
858 | //======================================================================= | |
859 | //function : NextValueOfUV | |
860 | //purpose : optimizing projection by Newton algo (S4030) | |
861 | //======================================================================= | |
862 | ||
863 | gp_Pnt2d ShapeAnalysis_Surface::NextValueOfUV(const gp_Pnt2d &p2dPrev, | |
864 | const gp_Pnt& P3D, | |
865 | const Standard_Real preci, | |
866 | const Standard_Real maxpreci) | |
867 | { | |
868 | GeomAdaptor_Surface& SurfAdapt = Adaptor3d()->ChangeSurface(); | |
869 | GeomAbs_SurfaceType surftype = SurfAdapt.GetType(); | |
870 | ||
871 | switch (surftype){ | |
872 | case GeomAbs_BezierSurface : | |
873 | case GeomAbs_BSplineSurface : | |
874 | case GeomAbs_SurfaceOfExtrusion : | |
875 | case GeomAbs_SurfaceOfRevolution : | |
876 | case GeomAbs_OffsetSurface : | |
877 | ||
7fd59977 | 878 | { |
15b54261 | 879 | if (surftype == GeomAbs_BSplineSurface) |
880 | { | |
881 | Handle(Geom_BSplineSurface) aBSpline = SurfAdapt.BSpline(); | |
882 | ||
883 | //Check near to knot position ~ near to C0 points on U isoline. | |
884 | if ( SurfAdapt.UContinuity() == GeomAbs_C0 ) | |
885 | { | |
886 | Standard_Integer aMinIndex = aBSpline->FirstUKnotIndex(); | |
887 | Standard_Integer aMaxIndex = aBSpline->LastUKnotIndex(); | |
888 | for (Standard_Integer anIdx = aMinIndex; anIdx <= aMaxIndex; ++anIdx) | |
889 | { | |
890 | Standard_Real aKnot = aBSpline->UKnot(anIdx); | |
891 | if (Abs (aKnot - p2dPrev.X()) < Precision::Confusion()) | |
892 | return ValueOfUV ( P3D, preci ); | |
893 | } | |
894 | } | |
895 | ||
896 | //Check near to knot position ~ near to C0 points on U isoline. | |
897 | if ( SurfAdapt.VContinuity() == GeomAbs_C0 ) | |
898 | { | |
899 | Standard_Integer aMinIndex = aBSpline->FirstVKnotIndex(); | |
900 | Standard_Integer aMaxIndex = aBSpline->LastVKnotIndex(); | |
901 | for (Standard_Integer anIdx = aMinIndex; anIdx <= aMaxIndex; ++anIdx) | |
902 | { | |
903 | Standard_Real aKnot = aBSpline->VKnot(anIdx); | |
904 | if (Abs (aKnot - p2dPrev.Y()) < Precision::Confusion()) | |
905 | return ValueOfUV ( P3D, preci ); | |
906 | } | |
907 | } | |
908 | } | |
909 | ||
7fd59977 | 910 | gp_Pnt2d sol; |
911 | Standard_Boolean res = SurfaceNewton(p2dPrev,P3D,preci,sol); | |
15b54261 | 912 | if ( res ) |
913 | { | |
914 | Standard_Real gap = P3D.Distance ( Value(sol) ); | |
915 | if ( res == 2 || //:q6 abv 19 Mar 99: protect against strange attractors | |
916 | ( maxpreci > 0. && gap - maxpreci > Precision::Confusion()) ) | |
917 | { //:q1: check with maxpreci | |
918 | Standard_Real U = sol.X(), V = sol.Y(); | |
919 | myGap = UVFromIso ( P3D, preci, U, V ); | |
920 | // gp_Pnt2d p = ValueOfUV ( P3D, preci ); | |
921 | if ( gap >= myGap ) return gp_Pnt2d ( U, V ); | |
922 | } | |
923 | myGap = gap; | |
924 | return sol; | |
7fd59977 | 925 | } |
926 | } | |
927 | break; | |
928 | default: | |
929 | break; | |
930 | } | |
931 | return ValueOfUV ( P3D, preci ); | |
932 | } | |
933 | ||
934 | //======================================================================= | |
935 | //function : ValueOfUV | |
936 | //purpose : | |
937 | //======================================================================= | |
938 | ||
939 | gp_Pnt2d ShapeAnalysis_Surface::ValueOfUV(const gp_Pnt& P3D,const Standard_Real preci) | |
940 | { | |
941 | GeomAdaptor_Surface& SurfAdapt = Adaptor3d()->ChangeSurface(); | |
1d47d8d0 | 942 | Standard_Real S = 0., T = 0.; |
7fd59977 | 943 | myGap = -1.; // devra etre calcule |
944 | Standard_Boolean computed = Standard_True; // a priori | |
945 | ||
946 | Standard_Real uf, ul, vf, vl; | |
947 | Bounds(uf, ul, vf, vl);//modified by rln on 12/11/97 mySurf-> is deleted | |
948 | ||
949 | { //:c9 abv 3 Mar 98: UKI60107-1 #350: to prevent 'catch' from catching exception raising below it | |
950 | try { // ajout CKY 30-DEC-1997 (cf ProStep TR6 r_89-ug) | |
951 | OCC_CATCH_SIGNALS | |
952 | GeomAbs_SurfaceType surftype = SurfAdapt.GetType(); | |
953 | switch (surftype){ | |
954 | ||
955 | case GeomAbs_Plane : | |
956 | { | |
957 | gp_Pln Plane = SurfAdapt.Plane(); | |
958 | ElSLib::Parameters( Plane, P3D, S, T); | |
959 | break; | |
960 | } | |
961 | case GeomAbs_Cylinder : | |
962 | { | |
963 | gp_Cylinder Cylinder = SurfAdapt.Cylinder(); | |
964 | ElSLib::Parameters( Cylinder, P3D, S, T); | |
c6541a0c | 965 | S += ShapeAnalysis::AdjustByPeriod(S,0.5*(uf+ul),2*M_PI); |
7fd59977 | 966 | break; |
967 | } | |
968 | case GeomAbs_Cone : | |
969 | { | |
970 | gp_Cone Cone = SurfAdapt.Cone(); | |
971 | ElSLib::Parameters( Cone, P3D, S, T); | |
c6541a0c | 972 | S += ShapeAnalysis::AdjustByPeriod(S,0.5*(uf+ul),2*M_PI); |
7fd59977 | 973 | break; |
974 | } | |
975 | case GeomAbs_Sphere : | |
976 | { | |
977 | gp_Sphere Sphere = SurfAdapt.Sphere(); | |
978 | ElSLib::Parameters( Sphere, P3D, S, T); | |
c6541a0c | 979 | S += ShapeAnalysis::AdjustByPeriod(S,0.5*(uf+ul),2*M_PI); |
7fd59977 | 980 | break; |
981 | } | |
982 | case GeomAbs_Torus : | |
983 | { | |
984 | gp_Torus Torus = SurfAdapt.Torus(); | |
985 | ElSLib::Parameters( Torus, P3D, S, T); | |
c6541a0c D |
986 | S += ShapeAnalysis::AdjustByPeriod(S,0.5*(uf+ul),2*M_PI); |
987 | T += ShapeAnalysis::AdjustByPeriod(T,0.5*(vf+vl),2*M_PI); | |
7fd59977 | 988 | break; |
989 | } | |
990 | case GeomAbs_BezierSurface : | |
991 | case GeomAbs_BSplineSurface : | |
992 | case GeomAbs_SurfaceOfExtrusion : | |
993 | case GeomAbs_SurfaceOfRevolution : | |
994 | case GeomAbs_OffsetSurface : //:d0 abv 3 Mar 98: UKI60107-1 #350 | |
995 | { | |
996 | S = (uf+ul)/2; T = (vf+vl)/2; // yaura aumoins qqchose | |
997 | //pdn to fix hangs PRO17015 | |
998 | if ((surftype==GeomAbs_SurfaceOfExtrusion)&&Precision::IsInfinite(uf)&&Precision::IsInfinite(ul)) { | |
999 | //conic case | |
1000 | gp_Pnt2d prev(S,T); | |
1001 | gp_Pnt2d solution; | |
1002 | if (SurfaceNewton(prev,P3D,preci,solution)) { | |
0797d9d3 | 1003 | #ifdef OCCT_DEBUG |
7fd59977 | 1004 | cout <<"Newton found point on conic extrusion"<<endl; |
1005 | #endif | |
1006 | return solution; | |
1007 | } | |
0797d9d3 | 1008 | #ifdef OCCT_DEBUG |
7fd59977 | 1009 | cout <<"Newton failed point on conic extrusion"<<endl; |
1010 | #endif | |
1011 | uf = -500; | |
1012 | ul = 500; | |
1013 | } | |
1014 | ||
1015 | if (Precision::IsInfinite(uf)) uf = -1000; | |
1016 | if (Precision::IsInfinite(ul)) ul = 1000; | |
1017 | if (Precision::IsInfinite(vf)) vf = -1000; | |
1018 | if (Precision::IsInfinite(vl)) vl = 1000; | |
1019 | ||
1020 | //:30 by abv 2.12.97: speed optimization | |
1021 | // code is taken from GeomAPI_ProjectPointOnSurf | |
1022 | if ( ! myExtOK ) { | |
1023 | // Standard_Real du = Abs(ul-uf)/100; Standard_Real dv = Abs(vl-vf)/100; | |
1024 | // if (IsUClosed()) du = 0; if (IsVClosed()) dv = 0; | |
1025 | // Forcer appel a IsU-VClosed | |
1026 | if (myUCloseVal < 0) IsUClosed(); | |
1027 | if (myVCloseVal < 0) IsVClosed(); | |
c15398ab RL |
1028 | Standard_Real du = 0., dv = 0.; |
1029 | //extension of the surface range is limited to non-offset surfaces as the latter | |
1030 | //can throw exception (e.g. Geom_UndefinedValue) when computing value - see id23943 | |
1031 | if (!mySurf->IsKind (STANDARD_TYPE (Geom_OffsetSurface))) { | |
1032 | //modified by rln during fixing CSR # BUC60035 entity #D231 | |
1033 | du = Min (myUDelt, SurfAdapt.UResolution (preci)); | |
1034 | dv = Min (myVDelt, SurfAdapt.VResolution (preci)); | |
1035 | } | |
7fd59977 | 1036 | myExtSrf = mySurf; |
1037 | Standard_Real Tol = Precision::PConfusion(); | |
6062bf3e | 1038 | myExtPS.SetFlag (Extrema_ExtFlag_MIN); |
7fd59977 | 1039 | myExtPS.Initialize ( myExtSrf, uf-du, ul+du, vf-dv, vl+dv, Tol, Tol ); |
1040 | myExtOK = Standard_True; | |
1041 | } | |
1042 | myExtPS.Perform ( P3D ); | |
1043 | Standard_Integer nPSurf = ( myExtPS.IsDone() ? myExtPS.NbExt() : 0 ); | |
1044 | ||
1045 | if ( nPSurf > 0 ) { | |
1046 | Standard_Real dist2Min = myExtPS.SquareDistance( 1 ); | |
1047 | Standard_Integer indMin=1; | |
1048 | for (Standard_Integer sol = 2; sol <= nPSurf ; sol++) { | |
1049 | Standard_Real dist2 = myExtPS.SquareDistance(sol); | |
1050 | if ( dist2Min > dist2 ) { | |
1051 | dist2Min = dist2; | |
1052 | indMin = sol; | |
1053 | } | |
1054 | } | |
1055 | myExtPS.Point(indMin).Parameter ( S, T ); | |
1056 | // PTV 26.06.2002 WORKAROUND protect OCC486. Remove after fix bug. | |
1057 | // file CEA_cuve-V5.igs Entityes 244, 259, 847, 925 | |
1058 | // if project point3D on SurfaceOfRevolution Extreme recompute 2d point, but | |
1059 | // returns an old distance from 3d to solution :-( | |
1060 | gp_Pnt aCheckPnt = mySurf->Value( S, T ); | |
1061 | dist2Min = P3D.SquareDistance(aCheckPnt); | |
1062 | // end of WORKAROUND | |
1063 | Standard_Real disSurf = sqrt (dist2Min);//, disCurv =1.e10; | |
1064 | ||
1065 | // Test de projection merdeuse sur les bords : | |
1066 | Standard_Real UU = S, VV = T, DistMinOnIso = RealLast(); // myGap; | |
1067 | // ForgetNewton(P3D, mySurf, preci, UU, VV, DistMinOnIso); | |
1068 | ||
1069 | //test added by rln on 08/12/97 | |
1070 | // DistMinOnIso = UVFromIso (P3D, preci, UU, VV); | |
1071 | Standard_Boolean possLockal = Standard_False; //:study S4030 (optimizing) | |
1072 | if (disSurf > preci) { | |
1073 | gp_Pnt2d pp(UU,VV); | |
1074 | if ( SurfaceNewton(pp,P3D,preci,pp)) { //:q2 abv 16 Mar 99: PRO7226 #412920 | |
1075 | Standard_Real dist = P3D.Distance ( Value(pp) ); | |
1076 | if ( dist < disSurf ) { | |
1077 | disSurf = dist; | |
1078 | S = UU = pp.X(); | |
1079 | T = VV = pp.Y(); | |
1080 | } | |
1081 | } | |
1082 | if ( disSurf < 10*preci) | |
1083 | if (mySurf->Continuity() != GeomAbs_C0){ | |
1084 | Standard_Real Tol = Precision::Confusion(); | |
1085 | gp_Vec D1U, D1V; | |
1086 | gp_Pnt pnt; | |
1087 | mySurf->D1(UU, VV, pnt, D1U, D1V); | |
1088 | gp_Vec b = D1U.Crossed(D1V); | |
1089 | gp_Vec a (pnt, P3D); | |
1090 | Standard_Real ab = a.Dot(b); | |
1091 | Standard_Real nrm2 = b.SquareMagnitude(); | |
1092 | if ( nrm2 > 1e-10 ) { | |
1093 | Standard_Real dist = a.SquareMagnitude() - (ab*ab)/nrm2; | |
1094 | possLockal = ( dist < Tol*Tol ); | |
1095 | } | |
1096 | } | |
1097 | if (!possLockal) { | |
1098 | DistMinOnIso = UVFromIso (P3D, preci, UU, VV); | |
1099 | } | |
1100 | } | |
1101 | ||
1102 | if (disSurf > DistMinOnIso) { | |
1103 | // On prend les parametres UU et VV; | |
1104 | S = UU; | |
1105 | T = VV; | |
1106 | myGap = DistMinOnIso; | |
1107 | } | |
1108 | else { | |
1109 | myGap = disSurf; | |
1110 | } | |
1111 | ||
1112 | // On essaie Intersection Droite Passant par P3D / Surface | |
1113 | // if ((myGap > preci)&&(!possLockal) ) { | |
1114 | // Standard_Real SS, TT; | |
1115 | // disCurv = FindUV(P3D, mySurf, S, T, SS, TT); | |
1116 | // if (disCurv < preci || disCurv < myGap) { | |
1117 | // S = SS; | |
1118 | // T = TT; | |
1119 | // } | |
1120 | // } | |
1121 | ||
1122 | } | |
1123 | else { | |
0797d9d3 | 1124 | #ifdef OCCT_DEBUG |
7fd59977 | 1125 | cout << "Warning: ShapeAnalysis_Surface::ValueOfUV(): Extrema failed, doing Newton" << endl; |
1126 | #endif | |
1127 | // on essai sur les bords | |
1128 | Standard_Real UU = S, VV = T;//, DistMinOnIso; | |
1129 | // ForgetNewton(P3D, mySurf, preci, UU, VV, DistMinOnIso); | |
1130 | myGap = UVFromIso (P3D, preci, UU, VV); | |
1131 | // if (DistMinOnIso > preci) { | |
1132 | // Standard_Real SS, TT; | |
1133 | // Standard_Real disCurv = FindUV(P3D, mySurf, UU, VV, SS, TT); | |
1134 | // if (disCurv < preci) { | |
1135 | // S = SS; | |
1136 | // T = TT; | |
1137 | // } | |
1138 | // } | |
1139 | // else { | |
1140 | S = UU; | |
1141 | T = VV; | |
1142 | // } | |
1143 | } | |
1144 | } | |
1145 | break; | |
1146 | ||
1147 | default : | |
1148 | computed = Standard_False; | |
1149 | break; | |
1150 | } | |
1151 | ||
1152 | } // end Try ValueOfUV (CKY 30-DEC-1997) | |
1153 | ||
1154 | catch(Standard_Failure) { | |
1155 | // Pas de raison mais qui sait. Mieux vaut retourner un truc faux que stopper | |
1156 | // L ideal serait d avoir un status ... mais qui va l interroger ? | |
1157 | // Avec ce status, on saurait que ce point est a sauter et voila tout | |
1158 | // En attendant, on met une valeur "pas idiote" mais surement fausse ... | |
1159 | //szv#4:S4163:12Mar99 optimized | |
1160 | S = (Precision::IsInfinite(uf))? 0 : (uf+ul) / 2.; | |
1161 | T = (Precision::IsInfinite(vf))? 0 : (vf+vl) / 2.; | |
0797d9d3 | 1162 | #ifdef OCCT_DEBUG //:s5 |
7fd59977 | 1163 | cout << "\nWarning: ShapeAnalysis_Surface::ValueOfUV(): Exception: "; |
1164 | Standard_Failure::Caught()->Print(cout); cout << endl; | |
1165 | #endif | |
1166 | } | |
1167 | } //:c9 | |
1168 | //szv#4:S4163:12Mar99 waste raise | |
1169 | //if (!computed) Standard_NoSuchObject::Raise("PCurveLib_ProjectPointOnSurf::ValueOfUV untreated surface type"); | |
1170 | if (computed) { if (myGap <= 0) myGap = P3D.Distance (mySurf->Value (S,T)); } | |
1171 | else { myGap = -1.; S = 0.; T = 0.; } | |
1172 | return gp_Pnt2d( S, T); | |
1173 | } | |
1174 | ||
1175 | //======================================================================= | |
1176 | //function : UVFromIso | |
1177 | //purpose : | |
1178 | //======================================================================= | |
1179 | ||
1180 | Standard_Real ShapeAnalysis_Surface::UVFromIso(const gp_Pnt& P3d,const Standard_Real preci,Standard_Real& U,Standard_Real& V) | |
1181 | { | |
1182 | // Projection qui considere les isos ... comme suit : | |
1183 | // Les 4 bords, plus les isos en U et en V | |
1184 | // En effet, souvent, un des deux est bon ... | |
1185 | Standard_Real theMin = RealLast(); | |
1186 | ||
1187 | gp_Pnt pntres; | |
1188 | Standard_Real Cf, Cl, UU,VV; | |
1189 | ||
1190 | // Initialisation des recherches : point deja trouve (?) | |
1191 | UU = U; VV = V; | |
1192 | gp_Pnt depart = mySurf->Value (U,V); | |
1193 | theMin = depart.Distance(P3d); | |
1194 | ||
1195 | if (theMin < preci/10) return theMin; // c etait deja OK | |
1196 | ComputeBoxes(); | |
1197 | if(myIsoUF.IsNull() || myIsoUL.IsNull() || myIsoVF.IsNull() || myIsoVL.IsNull()) { | |
1198 | // no isolines | |
1199 | // no more precise computation | |
1200 | return theMin; | |
1201 | } | |
1202 | try { // RAJOUT | |
1203 | OCC_CATCH_SIGNALS | |
1204 | //pdn Create BndBox containing point; | |
1205 | Bnd_Box aPBox; | |
1206 | aPBox.Set(P3d); | |
1207 | ||
1208 | //cout<<"Adaptor3d()->Surface().GetType() = "<<Adaptor3d()->Surface().GetType()<<endl; | |
1209 | ||
1210 | //modified by rln on 04/12/97 in order to use theese variables later | |
1211 | Standard_Boolean UV = Standard_True; | |
1212 | Standard_Real par=0., other=0., dist=0.; | |
1213 | Handle(Geom_Curve) iso; | |
1214 | Adaptor3d_IsoCurve anIsoCurve(Adaptor3d()); | |
1215 | for (Standard_Integer num = 0; num < 6; num ++) { | |
1216 | ||
1217 | UV = (num < 3); // 0-1-2 : iso-U 3-4-5 : iso-V | |
1218 | if( !(Adaptor3d()->Surface().GetType()==GeomAbs_OffsetSurface) ) { | |
1219 | const Bnd_Box *anIsoBox = 0; | |
1220 | switch (num) { | |
1221 | case 0 : par = myUF; iso = myIsoUF; anIsoBox = &myBndUF; break; | |
1222 | case 1 : par = myUL; iso = myIsoUL; anIsoBox = &myBndUL; break; | |
1223 | case 2 : par = U; iso = UIso (U); break; | |
1224 | case 3 : par = myVF; iso = myIsoVF; anIsoBox = &myBndVF; break; | |
1225 | case 4 : par = myVL; iso = myIsoVL; anIsoBox = &myBndVL; break; | |
1226 | case 5 : par = V; iso = VIso (V); break; | |
1227 | default: break; | |
1228 | } | |
1229 | ||
1230 | // On y va la-dessus | |
1231 | if (!Precision::IsInfinite(par) && !iso.IsNull()) { | |
1232 | if( anIsoBox && anIsoBox->Distance(aPBox) > theMin) | |
1233 | continue; | |
1234 | ||
1235 | Cf = iso->FirstParameter(); | |
1236 | Cl = iso->LastParameter(); | |
1237 | ||
1238 | if (Precision::IsInfinite(Cf)) Cf = -1000; | |
1239 | if (Precision::IsInfinite(Cl)) Cl = +1000; | |
1240 | dist = ShapeAnalysis_Curve().Project (iso,P3d,preci,pntres,other,Cf,Cl, Standard_False); | |
1241 | if (dist < theMin) { | |
1242 | theMin = dist; | |
1243 | //:q6 if (UV) VV = other; else UU = other; | |
1244 | // Selon une isoU, on calcule le meilleur V; et lycee de Versailles | |
1245 | UU = (UV ? par : other); VV = (UV ? other : par); //:q6: uncommented | |
1246 | } | |
1247 | } | |
1248 | } | |
1249 | ||
1250 | else { | |
1251 | Adaptor3d_Curve *anAdaptor = NULL; | |
1252 | GeomAdaptor_Curve aGeomCurve; | |
1253 | ||
1254 | const Bnd_Box *anIsoBox = 0; | |
1255 | switch (num) { | |
1256 | case 0 : par = myUF; aGeomCurve.Load(myIsoUF); anAdaptor=&aGeomCurve; anIsoBox = &myBndUF; break; | |
1257 | case 1 : par = myUL; aGeomCurve.Load(myIsoUL); anAdaptor=&aGeomCurve; anIsoBox = &myBndUL;break; | |
1258 | case 2 : par = U; anIsoCurve.Load(GeomAbs_IsoU,U); anAdaptor=&anIsoCurve; break; | |
1259 | case 3 : par = myVF; aGeomCurve.Load(myIsoVF); anAdaptor=&aGeomCurve; anIsoBox = &myBndVF; break; | |
1260 | case 4 : par = myVL; aGeomCurve.Load(myIsoVL); anAdaptor=&aGeomCurve; anIsoBox = &myBndVL;break; | |
1261 | case 5 : par = V; anIsoCurve.Load(GeomAbs_IsoV,V); anAdaptor=&anIsoCurve; break; | |
1262 | default : break; | |
1263 | } | |
1264 | if( anIsoBox && anIsoBox->Distance(aPBox) > theMin) | |
1265 | continue; | |
1266 | dist = ShapeAnalysis_Curve().Project(*anAdaptor,P3d,preci,pntres,other); | |
1267 | if (dist < theMin) { | |
1268 | theMin = dist; | |
1269 | UU = (UV ? par : other); VV = (UV ? other : par); //:q6: uncommented | |
1270 | } | |
1271 | } | |
1272 | } | |
1273 | ||
1274 | //added by rln on 04/12/97 iterational process | |
1275 | Standard_Real PrevU = U, PrevV = V; | |
1276 | Standard_Integer MaxIters = 5, Iters = 0; | |
1277 | if( !(Adaptor3d()->Surface().GetType()==GeomAbs_OffsetSurface) ) { | |
1278 | while (((PrevU != UU) || (PrevV != VV)) && (Iters < MaxIters) && (theMin > preci)) { | |
1279 | PrevU = UU; PrevV = VV; | |
1280 | if (UV) {par = UU; iso = UIso(UU);} | |
1281 | else {par = VV; iso = VIso(VV);} | |
1282 | if(!iso.IsNull()) { | |
1283 | Cf = iso->FirstParameter(); | |
1284 | Cl = iso->LastParameter(); | |
1285 | if (Precision::IsInfinite(Cf)) Cf = -1000; | |
1286 | if (Precision::IsInfinite(Cl)) Cl = +1000; | |
1287 | dist = ShapeAnalysis_Curve().Project (iso, P3d, preci, pntres, other, Cf, Cl, Standard_False); | |
1288 | if (dist < theMin) { | |
1289 | theMin = dist; | |
1290 | if (UV) VV = other; else UU = other; | |
1291 | } | |
1292 | } | |
1293 | UV = !UV; | |
1294 | if (UV) {par = UU; iso = UIso(UU);} | |
1295 | else {par = VV; iso = VIso(VV);} | |
1296 | if(!iso.IsNull()) { | |
1297 | Cf = iso->FirstParameter(); | |
1298 | Cl = iso->LastParameter(); | |
1299 | if (Precision::IsInfinite(Cf)) Cf = -1000; | |
1300 | if (Precision::IsInfinite(Cl)) Cl = +1000; | |
1301 | dist = ShapeAnalysis_Curve().Project (iso, P3d, preci, pntres, other, Cf, Cl, Standard_False); | |
1302 | if (dist < theMin) { | |
1303 | theMin = dist; | |
1304 | if (UV) VV = other; else UU = other; | |
1305 | } | |
1306 | } | |
1307 | UV = !UV; | |
1308 | Iters++; | |
1309 | } | |
1310 | } | |
1311 | ||
1312 | else { | |
1313 | while (((PrevU != UU) || (PrevV != VV)) && (Iters < MaxIters) && (theMin > preci)) { | |
1314 | PrevU = UU; PrevV = VV; | |
1315 | if (UV) { | |
1316 | par = UU; | |
1317 | anIsoCurve.Load(GeomAbs_IsoU,UU); | |
1318 | } | |
1319 | else { | |
1320 | par = VV; | |
1321 | anIsoCurve.Load(GeomAbs_IsoV,VV); | |
1322 | } | |
1323 | Cf = anIsoCurve.FirstParameter(); | |
1324 | Cl = anIsoCurve.LastParameter(); | |
1325 | if (Precision::IsInfinite(Cf)) Cf = -1000; | |
1326 | if (Precision::IsInfinite(Cl)) Cl = +1000; | |
1327 | dist = ShapeAnalysis_Curve().Project(anIsoCurve, P3d, preci, pntres, other); | |
1328 | if (dist < theMin) { | |
1329 | theMin = dist; | |
1330 | if (UV) VV = other; else UU = other; | |
1331 | } | |
1332 | UV = !UV; | |
1333 | if (UV) { | |
1334 | par = UU; | |
1335 | anIsoCurve.Load(GeomAbs_IsoU,UU); | |
1336 | } | |
1337 | else { | |
1338 | par = VV; | |
1339 | anIsoCurve.Load(GeomAbs_IsoV,VV); | |
1340 | } | |
1341 | Cf = anIsoCurve.FirstParameter(); | |
1342 | Cl = anIsoCurve.LastParameter(); | |
1343 | if (Precision::IsInfinite(Cf)) Cf = -1000; | |
1344 | if (Precision::IsInfinite(Cl)) Cl = +1000; | |
1345 | dist = ShapeAnalysis_Curve().ProjectAct (anIsoCurve, P3d, preci, pntres, other); | |
1346 | if (dist < theMin) { | |
1347 | theMin = dist; | |
1348 | if (UV) VV = other; else UU = other; | |
1349 | } | |
1350 | UV = !UV; | |
1351 | Iters++; | |
1352 | } | |
1353 | } | |
1354 | ||
1355 | U = UU; V = VV; | |
1356 | ||
1357 | } // fin try RAJOUT | |
1358 | catch(Standard_Failure) { | |
1359 | theMin = RealLast(); // theMin de depart | |
0797d9d3 | 1360 | #ifdef OCCT_DEBUG //:s5 |
7fd59977 | 1361 | cout << "\nWarning: ShapeAnalysis_Curve::UVFromIso(): Exception: "; |
1362 | Standard_Failure::Caught()->Print(cout); cout << endl; | |
1363 | #endif | |
1364 | } | |
1365 | return theMin; | |
1366 | } | |
1367 | ||
1368 | ||
1369 | //======================================================================= | |
1370 | //function : SortSingularities | |
1371 | //purpose : | |
1372 | //======================================================================= | |
1373 | ||
1374 | void ShapeAnalysis_Surface::SortSingularities() | |
1375 | { | |
1376 | for (Standard_Integer i = 0; i < myNbDeg - 1; i++) { | |
1377 | Standard_Real minPreci = myPreci[i]; | |
1378 | Standard_Integer minIndex = i; | |
1379 | for (Standard_Integer j = i + 1; j < myNbDeg; j++) | |
1380 | if (minPreci > myPreci[j]) { minPreci = myPreci[j]; minIndex = j; } | |
1381 | if (minIndex != i) { | |
1382 | myPreci[minIndex] = myPreci[i]; myPreci[i] = minPreci; | |
1383 | gp_Pnt tmpP3d = myP3d[minIndex]; | |
1384 | myP3d[minIndex] = myP3d[i]; myP3d[i] = tmpP3d; | |
1385 | gp_Pnt2d tmpP2d = myFirstP2d[minIndex]; | |
1386 | myFirstP2d[minIndex] = myFirstP2d[i]; myFirstP2d[i] = tmpP2d; | |
1387 | tmpP2d = myLastP2d[minIndex]; myLastP2d[minIndex] = myLastP2d[i]; myLastP2d[i] = tmpP2d; | |
1388 | Standard_Real tmpPar = myFirstPar[minIndex]; | |
1389 | myFirstPar[minIndex] = myFirstPar[i]; myFirstPar[i] = tmpPar; | |
1390 | tmpPar = myLastPar[minIndex]; myLastPar[minIndex] = myLastPar[i]; myLastPar[i] = tmpPar; | |
1391 | Standard_Boolean tmpUIsoDeg = myUIsoDeg[minIndex]; | |
1392 | myUIsoDeg[minIndex] = myUIsoDeg[i]; myUIsoDeg[i] = tmpUIsoDeg; | |
1393 | } | |
1394 | } | |
1395 | } | |
1396 | ||
1397 | ||
1398 | //======================================================================= | |
1399 | //function : SetDomain | |
1400 | //purpose : | |
1401 | //======================================================================= | |
1402 | ||
1403 | void ShapeAnalysis_Surface::SetDomain(const Standard_Real U1, | |
1404 | const Standard_Real U2, | |
1405 | const Standard_Real V1, | |
1406 | const Standard_Real V2) | |
1407 | { | |
1408 | myUF = U1; | |
1409 | myUL = U2; | |
1410 | myVF = V1; | |
1411 | myVL = V2; | |
1412 | } | |
1413 | ||
1414 | ||
1415 | void ShapeAnalysis_Surface::ComputeBoxes() | |
1416 | { | |
1417 | if(myIsoBoxes) return; | |
1418 | myIsoBoxes = Standard_True; | |
1419 | ComputeBoundIsos(); | |
1420 | if(!myIsoUF.IsNull()) | |
1421 | BndLib_Add3dCurve::Add(GeomAdaptor_Curve(myIsoUF),Precision::Confusion(),myBndUF); | |
1422 | if(!myIsoUL.IsNull()) | |
1423 | BndLib_Add3dCurve::Add(GeomAdaptor_Curve(myIsoUL),Precision::Confusion(),myBndUL); | |
1424 | if(!myIsoVF.IsNull()) | |
1425 | BndLib_Add3dCurve::Add(GeomAdaptor_Curve(myIsoVF),Precision::Confusion(),myBndVF); | |
1426 | if(!myIsoVL.IsNull()) | |
1427 | BndLib_Add3dCurve::Add(GeomAdaptor_Curve(myIsoVL),Precision::Confusion(),myBndVL); | |
1428 | } | |
1429 | ||
1430 | const Bnd_Box& ShapeAnalysis_Surface::GetBoxUF() | |
1431 | { | |
1432 | ComputeBoxes(); | |
1433 | return myBndUF; | |
1434 | } | |
1435 | ||
1436 | const Bnd_Box& ShapeAnalysis_Surface::GetBoxUL() | |
1437 | { | |
1438 | ComputeBoxes(); | |
1439 | return myBndUL; | |
1440 | } | |
1441 | ||
1442 | const Bnd_Box& ShapeAnalysis_Surface::GetBoxVF() | |
1443 | { | |
1444 | ComputeBoxes(); | |
1445 | return myBndVF; | |
1446 | } | |
1447 | ||
1448 | const Bnd_Box& ShapeAnalysis_Surface::GetBoxVL() | |
1449 | { | |
1450 | ComputeBoxes(); | |
1451 | return myBndVL; | |
1452 | } |