OCC22529 FitALL works incorrectly for small flat shapes
[occt.git] / src / Extrema / Extrema_FuncExtPS.cxx
CommitLineData
7fd59977 1// File: Extrema_FuncExtPS.cxx
2// Created: Tue Jul 18 08:11:24 1995
3// Author: Modelistation
4// <model@metrox>
5
6// Modified by skv - Thu Sep 30 15:21:07 2004 OCC593
7
8
9#include <Extrema_FuncExtPS.ixx>
10#include <gp_Vec.hxx>
11#include <gp_Pnt.hxx>
12#include <Standard_TypeMismatch.hxx>
13#include <Precision.hxx>
14#include <GeomAbs_IsoType.hxx>
15
16/*-----------------------------------------------------------------------------
17 Fonctions permettant de rechercher une distance extremale entre un point P
18et une surface S (en partant d'un point approche S(u0,v0)).
19 Cette classe herite de math_FunctionSetWithDerivatives et est utilisee par
20l'algorithme math_FunctionSetRoot.
21 Si on note Dus et Dvs, les derivees en u et v, les 2 fonctions a annuler sont:
22 { F1(u,v) = (S(u,v)-P).Dus(u,v) }
23 { F2(u,v) = (S(u,v)-P).Dvs(u,v) }
24 Si on note Duus, Dvvs et Duvs, les derivees secondes de S, les derivees de F1
25et F2 sont egales a:
26 { Duf1(u,v) = Dus(u,v).Dus(u,v) + (S(u,v)-P).Duus(u,v)
27 = ||Dus(u,v)|| ** 2 + (S(u,v)-P).Duus(u,v)
28 { Dvf1(u,v) = Dvs(u,v).Dus(u,v) + (S(u,v)-P).Duvs(u,v)
29 { Duf2(u,v) = Dus(u,v).Dvs(u,v) + (S(u,v)-P).Duvs(u,v) = dF1v(u,v)
30 { Dvf2(u,v) = Dvs(u,v).Dvs(u,v) + (S(u,v)-P).Dvvs(u,v)
31 = ||Dvs(u,v)|| ** 2 + (S(u,v)-P).Dvvs(u,v)
32
33----------------------------------------------------------------------------*/
34// modified by NIZHNY-EAP Wed Nov 21 17:33:05 2001
35// -- Dus and Dvs normalized, Df modified accordingly (BUC61043)
36//=============================================================================
37//------------------------------------------------------------------------------
38// This method checks if isocurve is punctual (for details see Geom_OffsetSurface
39// and Geom_OsculatingSurface
40//-------------------------------------------------------------------------------
41
42static Standard_Boolean IsoIsDeg (const Adaptor3d_Surface& S,
43 const Standard_Real Param,
44 const GeomAbs_IsoType IT,
45 const Standard_Real TolMin,
46 const Standard_Real TolMax)
47{
48 Standard_Real U1=0.,U2=0.,V1=0.,V2=0.,T;
49 Standard_Boolean Along = Standard_True;
50 U1 = S.FirstUParameter();
51 U2 = S.LastUParameter();
52 V1 = S.FirstVParameter();
53 V2 = S.LastVParameter();
54 gp_Vec D1U,D1V;
55 gp_Pnt P;
56 Standard_Real Step,D1NormMax;
57 if (IT == GeomAbs_IsoV)
58 {
59 Step = (U2 - U1)/10;
60 D1NormMax=0.;
61 for (T=U1;T<=U2;T=T+Step)
62 {
63 S.D1(T,Param,P,D1U,D1V);
64 D1NormMax=Max(D1NormMax,D1U.Magnitude());
65 }
66
67 if (D1NormMax >TolMax || D1NormMax < TolMin )
68 Along = Standard_False;
69 }
70 else
71 {
72 Step = (V2 - V1)/10;
73 D1NormMax=0.;
74 for (T=V1;T<=V2;T=T+Step)
75 {
76 S.D1(Param,T,P,D1U,D1V);
77 D1NormMax=Max(D1NormMax,D1V.Magnitude());
78 }
79
80 if (D1NormMax >TolMax || D1NormMax < TolMin )
81 Along = Standard_False;
82
83
84 }
85 return Along;
86}
87
88
89Extrema_FuncExtPS::Extrema_FuncExtPS ()
90{
91 myPinit = Standard_False;
92 mySinit = Standard_False;
93 myUIsoIsDeg = Standard_False;
94 myVIsoIsDeg = Standard_False;
95}
96//=============================================================================
97Extrema_FuncExtPS::Extrema_FuncExtPS (const gp_Pnt& P,
98 const Adaptor3d_Surface& S)
99{
100 myP = P;
101 myS = (Adaptor3d_SurfacePtr)&S;
102 myUIsoIsDeg = Standard_False;
103 myVIsoIsDeg = Standard_False;
104 GeomAbs_SurfaceType aSType = S.GetType();
105 if(aSType == GeomAbs_BezierSurface ||
106 aSType == GeomAbs_BSplineSurface) {
107 Standard_Real u1, u2, v1, v2;
108 Standard_Real tol = Precision::Confusion();
109 u1 = S.FirstUParameter();
110 u2 = S.LastUParameter();
111 v1 = S.FirstVParameter();
112 v2 = S.LastVParameter();
113 myUIsoIsDeg = IsoIsDeg(S, u1, GeomAbs_IsoU, 0., tol) ||
114 IsoIsDeg(S, u2, GeomAbs_IsoU, 0., tol);
115 myVIsoIsDeg = IsoIsDeg(S, v1, GeomAbs_IsoV, 0., tol) ||
116 IsoIsDeg(S, v2, GeomAbs_IsoV, 0., tol);
117 }
118 myPinit = Standard_True;
119 mySinit = Standard_True;
120}
121
122//=============================================================================
123void Extrema_FuncExtPS::Initialize(const Adaptor3d_Surface& S)
124{
125 myS = (Adaptor3d_SurfacePtr)&S;
126 myUIsoIsDeg = Standard_False;
127 myVIsoIsDeg = Standard_False;
128 GeomAbs_SurfaceType aSType = S.GetType();
129 if(aSType == GeomAbs_BezierSurface ||
130 aSType == GeomAbs_BSplineSurface) {
131 Standard_Real u1, u2, v1, v2;
132 Standard_Real tol = Precision::Confusion();
133 u1 = S.FirstUParameter();
134 u2 = S.LastUParameter();
135 v1 = S.FirstVParameter();
136 v2 = S.LastVParameter();
137 myUIsoIsDeg = IsoIsDeg(S, u1, GeomAbs_IsoU, 0., tol) ||
138 IsoIsDeg(S, u2, GeomAbs_IsoU, 0., tol);
139 myVIsoIsDeg = IsoIsDeg(S, v1, GeomAbs_IsoV, 0., tol) ||
140 IsoIsDeg(S, v2, GeomAbs_IsoV, 0., tol);
141 }
142 mySinit = Standard_True;
143 myPoint.Clear();
144 mySqDist.Clear();
145}
146
147//=============================================================================
148
149void Extrema_FuncExtPS::SetPoint(const gp_Pnt& P)
150{
151 myP = P;
152 myPinit = Standard_True;
153 myPoint.Clear();
154 mySqDist.Clear();
155}
156
157//=============================================================================
158
159//=============================================================================
160
161Standard_Integer Extrema_FuncExtPS::NbVariables () const { return 2;}
162//=============================================================================
163
164Standard_Integer Extrema_FuncExtPS::NbEquations () const { return 2;}
165//=============================================================================
166
167Standard_Boolean Extrema_FuncExtPS::Value (const math_Vector& UV,
168 math_Vector& F)
169{
170 if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
171 myU = UV(1);
172 myV = UV(2);
173 gp_Vec Dus, Dvs;
174 myS->D1(myU,myV,myPs,Dus,Dvs);
175
176 gp_Vec PPs (myP,myPs);
177 // EAP
178 if(myVIsoIsDeg)
179 {
180 Standard_Real DusMod = Dus.Magnitude();
181 if (DusMod>gp::Resolution() && DusMod<1.)
182 Dus.Multiply(1/DusMod);
183 }
184 if (myUIsoIsDeg) {
185 Standard_Real DvsMod = Dvs.Magnitude();
186 if (DvsMod>gp::Resolution() && DvsMod<1.)
187 Dvs.Multiply(1/DvsMod);
188 }
189
190 F(1) = PPs.Dot(Dus);
191 F(2) = PPs.Dot(Dvs);
192
193 return Standard_True;
194}
195//=============================================================================
196
197Standard_Boolean Extrema_FuncExtPS::Derivatives (const math_Vector& UV,
198 math_Matrix& Df)
199{
200 math_Vector F(1,2);
201 return Values(UV,F,Df);
202}
203//=============================================================================
204
205Standard_Boolean Extrema_FuncExtPS::Values (const math_Vector& UV,
206 math_Vector& F,
207 math_Matrix& Df)
208{
209 if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
210 myU = UV(1);
211 myV = UV(2);
212 gp_Vec Dus, Dvs, Duus, Dvvs, Duvs;
213 myS->D2(myU,myV,myPs,Dus,Dvs,Duus,Dvvs,Duvs);
214
215 gp_Vec PPs (myP,myPs);
216 // EAP
217// Df(1,1) = Dus.SquareMagnitude() + PPs.Dot(Duus);
218// Df(1,2) = Dvs.Dot(Dus) + PPs.Dot(Duvs);
219// Df(2,1) = Df(1,2);
220// Df(2,2) = Dvs.SquareMagnitude() + PPs.Dot(Dvvs);
221
222 // 25/03/02 akm : (OCC231) Further normalization of derivatives for surfaces
223 // with singularities will hence be performed only when modulus
224 // becomes less than 1.0. Thus the continuity will be kept,
225 // and normalization will be switched off 'far' from singularities.
226 // 1. V iso
227 Standard_Real DusMod2 = Dus.SquareMagnitude();
228 if (myVIsoIsDeg)
229 {
230 Standard_Real DusMod = Sqrt(DusMod2);
231 if (DusMod2>gp::Resolution() && DusMod2<1.)
232 {
233 Dus.Multiply(1/DusMod);
234 Df(1,1) = DusMod2 + PPs.Dot( (Duus*DusMod - Dus*(Dus.Dot(Duus)/DusMod)) / DusMod2 );
235 Df(1,2) = Dvs.Dot(Dus) + PPs.Dot( (Duvs*DusMod-Dus*(Dus.Dot(Duvs)/DusMod)) / DusMod2 );
236 }
237 else {
238 Df(1,1) = DusMod2 + PPs.Dot(Duus);
239 Df(1,2) = Dvs.Dot(Dus) + PPs.Dot(Duvs);
240 }
241 }
242 else {
243 Df(1,1) = DusMod2 + PPs.Dot(Duus);
244 Df(1,2) = Dvs.Dot(Dus) + PPs.Dot(Duvs);
245 }
246 // 2. U iso
247 Standard_Real DvsMod2 = Dvs.SquareMagnitude();
248 if (myUIsoIsDeg)
249 {
250 Standard_Real DvsMod = Sqrt(DvsMod2);
251 if (DvsMod2>gp::Resolution() && DvsMod2<1.)
252 {
253 Dvs.Multiply(1/DvsMod);
254 Df(2,1) = Dvs.Dot(Dus) + PPs.Dot( (Duvs*DvsMod-Dvs*(Dvs.Dot(Duvs)/DvsMod)) / DvsMod2 );
255 Df(2,2) = DvsMod2 + PPs.Dot( (Duus*DvsMod - Dus*(Dus.Dot(Duus)/DvsMod)) / DvsMod2 );
256 }
257 else {
258 Df(2,1) = Dvs.Dot(Dus) + PPs.Dot(Duvs);
259 Df(2,2) = DvsMod2 + PPs.Dot(Dvvs);
260 }
261 }
262 else {
263 Df(2,1) = Dvs.Dot(Dus) + PPs.Dot(Duvs);
264 Df(2,2) = DvsMod2 + PPs.Dot(Dvvs);
265 }
266
267 F(1) = PPs.Dot(Dus);
268 F(2) = PPs.Dot(Dvs);
269
270 return Standard_True;
271}
272//=============================================================================
273
274Standard_Integer Extrema_FuncExtPS::GetStateNumber ()
275{
276 if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
277 mySqDist.Append(myPs.SquareDistance(myP));
278 myPoint.Append(Extrema_POnSurf(myU,myV,myPs));
279 return 0;
280}
281//=============================================================================
282
283Standard_Integer Extrema_FuncExtPS::NbExt () const
284{
285 return mySqDist.Length();
286}
287//=============================================================================
288
289Standard_Real Extrema_FuncExtPS::SquareDistance (const Standard_Integer N) const
290{
291 if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
292 return mySqDist.Value(N);
293}
294//=============================================================================
295
296Extrema_POnSurf Extrema_FuncExtPS::Point (const Standard_Integer N) const
297{
298 if (!myPinit || !mySinit) Standard_TypeMismatch::Raise();
299 return myPoint.Value(N);
300}
301//=============================================================================
302
303// Modified by skv - Thu Sep 30 15:21:07 2004 OCC593 Begin
304Standard_Boolean Extrema_FuncExtPS::HasDegIso() const
305{
306 return myUIsoIsDeg || myVIsoIsDeg;
307}
308// Modified by skv - Thu Sep 30 15:21:07 2004 OCC593 End