b311480e |
1 | // Created on: 1998-05-12 |
2 | // Created by: Philippe NOUAILLE |
3 | // Copyright (c) 1998-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
7fd59977 |
17 | |
42cf5bc1 |
18 | #include <Blend_AppFunction.hxx> |
42cf5bc1 |
19 | #include <BRepBlend_AppFuncRoot.hxx> |
7fd59977 |
20 | #include <BRepBlend_Line.hxx> |
42cf5bc1 |
21 | #include <gp_Pnt.hxx> |
7fd59977 |
22 | #include <math_FunctionSetRoot.hxx> |
42cf5bc1 |
23 | #include <Standard_Type.hxx> |
7fd59977 |
24 | |
92efcf78 |
25 | IMPLEMENT_STANDARD_RTTIEXT(BRepBlend_AppFuncRoot,Approx_SweepFunction) |
26 | |
7fd59977 |
27 | BRepBlend_AppFuncRoot::BRepBlend_AppFuncRoot(Handle(BRepBlend_Line)& Line, |
28 | Blend_AppFunction& Func, |
29 | const Standard_Real Tol3d, |
30 | const Standard_Real Tol2d) |
31 | :myLine(Line), |
32 | myFunc(&Func), |
33 | myTolerance(1,Func.NbVariables()), |
34 | X1(1,Func.NbVariables()), |
35 | X2(1,Func.NbVariables()), |
36 | XInit(1,Func.NbVariables()), |
37 | Sol(1,Func.NbVariables()) |
38 | { |
39 | Standard_Integer NbPoles, NbKnots, Degree, NbPoles2d; |
40 | Standard_Integer ii; |
41 | |
42 | // Tolerances |
43 | Func.GetTolerance(myTolerance, Tol3d); |
44 | Standard_Integer dim = Func.NbVariables(); |
45 | for (ii=1; ii<= dim; ii++) { |
46 | if (myTolerance(ii)>Tol2d) { myTolerance(ii) = Tol2d;} |
47 | } |
48 | |
81bba717 |
49 | // Tables |
7fd59977 |
50 | Func.GetShape( NbPoles, NbKnots, Degree, NbPoles2d); |
51 | |
81bba717 |
52 | // Calculation of BaryCentre (rationnal case). |
7fd59977 |
53 | if (Func.IsRational()) { |
54 | Standard_Real Xmax =-1.e100, Xmin = 1.e100, |
55 | Ymax =-1.e100, Ymin = 1.e100, |
56 | Zmax =-1.e100, Zmin = 1.e100; |
57 | Blend_Point P; |
58 | for (ii=1; ii<=myLine->NbPoints(); ii++) { |
59 | P = myLine->Point(ii); |
60 | Xmax = Max ( Max(P.PointOnS1().X(), P.PointOnS2().X()), Xmax); |
61 | Xmin = Min ( Min(P.PointOnS1().X(), P.PointOnS2().X()), Xmin); |
62 | Ymax = Max ( Max(P.PointOnS1().Y(), P.PointOnS2().Y()), Ymax); |
63 | Ymin = Min ( Min(P.PointOnS1().Y(), P.PointOnS2().Y()), Ymin); |
64 | Zmax = Max ( Max(P.PointOnS1().Z(), P.PointOnS2().Z()), Zmax); |
65 | Zmin = Min ( Min(P.PointOnS1().Z(), P.PointOnS2().Z()), Zmin); |
66 | |
67 | myBary.SetCoord((Xmax+Xmin)/2, (Ymax+Ymin)/2, (Zmax+Zmin)/2); |
68 | } |
69 | } |
70 | else {myBary.SetCoord(0,0,0);} |
71 | } |
72 | |
73 | //================================================================================ |
74 | // Function: D0 |
81bba717 |
75 | // Purpose : Calculation of section for v = Param, if calculation fails |
76 | // Standard_False is raised. |
7fd59977 |
77 | //================================================================================ |
78 | Standard_Boolean BRepBlend_AppFuncRoot::D0(const Standard_Real Param, |
35e08fe8 |
79 | const Standard_Real /*First*/, |
80 | const Standard_Real /*Last*/, |
81 | TColgp_Array1OfPnt& Poles, |
82 | TColgp_Array1OfPnt2d& Poles2d, |
83 | TColStd_Array1OfReal& Weigths) |
7fd59977 |
84 | { |
85 | Standard_Boolean Ok=Standard_True; |
86 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
87 | Ok = SearchPoint( *Func, Param, myPnt); |
88 | |
89 | if (Ok) (*Func).Section(myPnt, |
35e08fe8 |
90 | Poles, |
91 | Poles2d, |
92 | Weigths); |
7fd59977 |
93 | return Ok; |
94 | } |
95 | |
96 | //================================================================================ |
97 | // Function: D1 |
81bba717 |
98 | // Purpose : Calculation of the partial derivative of the section corresponding to v |
99 | // for v = Param, if the calculation fails Standard_False is raised. |
7fd59977 |
100 | //================================================================================ |
101 | Standard_Boolean BRepBlend_AppFuncRoot::D1(const Standard_Real Param, |
35e08fe8 |
102 | const Standard_Real /*First*/, |
103 | const Standard_Real /*Last*/, |
7fd59977 |
104 | TColgp_Array1OfPnt& Poles, |
105 | TColgp_Array1OfVec& DPoles, |
106 | TColgp_Array1OfPnt2d& Poles2d, |
107 | TColgp_Array1OfVec2d& DPoles2d, |
108 | TColStd_Array1OfReal& Weigths, |
109 | TColStd_Array1OfReal& DWeigths) |
110 | { |
111 | Standard_Boolean Ok=Standard_True; |
112 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
113 | |
114 | Ok = SearchPoint( *Func, Param, myPnt); |
115 | |
116 | if (Ok) { |
117 | Ok = (*Func).Section(myPnt, |
118 | Poles, DPoles, |
119 | Poles2d, DPoles2d, |
120 | Weigths, DWeigths); |
121 | } |
122 | |
123 | return Ok; |
124 | } |
125 | |
126 | //=========================================================================== |
127 | // Function: D2 |
81bba717 |
128 | // Purpose : Calculation of the derivative and second partial of the |
129 | // section corresponding to v. |
130 | // For v = Param, if the calculation fails Standard_False is raised. |
7fd59977 |
131 | //=========================================================================== |
132 | Standard_Boolean BRepBlend_AppFuncRoot::D2(const Standard_Real Param, |
35e08fe8 |
133 | const Standard_Real /*First*/, |
134 | const Standard_Real /*Last*/, |
7fd59977 |
135 | TColgp_Array1OfPnt& Poles, |
136 | TColgp_Array1OfVec& DPoles, |
137 | TColgp_Array1OfVec& D2Poles, |
138 | TColgp_Array1OfPnt2d& Poles2d, |
139 | TColgp_Array1OfVec2d& DPoles2d, |
140 | TColgp_Array1OfVec2d& D2Poles2d, |
141 | TColStd_Array1OfReal& Weigths, |
142 | TColStd_Array1OfReal& DWeigths, |
143 | TColStd_Array1OfReal& D2Weigths) |
144 | { |
145 | Standard_Boolean Ok=Standard_True; |
146 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
147 | |
148 | Ok = SearchPoint( *Func, Param, myPnt); |
149 | if (Ok) { |
150 | Ok = (*Func).Section(myPnt, |
151 | Poles, DPoles, D2Poles, |
152 | Poles2d, DPoles2d, D2Poles2d, |
153 | Weigths, DWeigths, D2Weigths); |
154 | } |
155 | return Ok; |
156 | } |
157 | |
158 | Standard_Integer BRepBlend_AppFuncRoot::Nb2dCurves() const |
159 | { |
160 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
161 | Standard_Integer i,j,k,nbpol2d; |
162 | (*Func).GetShape(i,j,k,nbpol2d); |
163 | return nbpol2d; |
164 | } |
165 | |
166 | void BRepBlend_AppFuncRoot::SectionShape(Standard_Integer& NbPoles, |
167 | Standard_Integer& NbKnots, |
168 | Standard_Integer& Degree) const |
169 | { |
170 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
171 | Standard_Integer ii; |
172 | (*Func).GetShape( NbPoles, NbKnots, Degree, ii); |
173 | } |
174 | |
175 | void BRepBlend_AppFuncRoot::Knots(TColStd_Array1OfReal& TKnots) const |
176 | { |
177 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
178 | Func->Knots(TKnots); |
179 | } |
180 | |
181 | void BRepBlend_AppFuncRoot::Mults(TColStd_Array1OfInteger& TMults) const |
182 | { |
183 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
184 | Func->Mults(TMults); |
185 | } |
186 | |
187 | Standard_Boolean BRepBlend_AppFuncRoot::IsRational() const |
188 | { |
189 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
190 | return (*Func).IsRational(); |
191 | } |
192 | |
193 | Standard_Integer BRepBlend_AppFuncRoot::NbIntervals(const GeomAbs_Shape S) const |
194 | { |
195 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
196 | return Func->NbIntervals(S); |
197 | } |
198 | |
199 | void BRepBlend_AppFuncRoot::Intervals(TColStd_Array1OfReal& T,const GeomAbs_Shape S) const |
200 | { |
201 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
202 | Func->Intervals(T, S); |
203 | } |
204 | |
205 | void BRepBlend_AppFuncRoot::SetInterval(const Standard_Real First,const Standard_Real Last) |
206 | { |
207 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
208 | Func->Set(First, Last); |
209 | } |
210 | |
211 | void BRepBlend_AppFuncRoot::Resolution(const Standard_Integer Index, |
212 | const Standard_Real Tol, |
213 | Standard_Real& TolU, |
214 | Standard_Real& TolV) const |
215 | { |
216 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
217 | Func->Resolution(Index,Tol,TolU,TolV); |
218 | } |
219 | |
220 | void BRepBlend_AppFuncRoot::GetTolerance(const Standard_Real BoundTol, |
221 | const Standard_Real SurfTol, |
222 | const Standard_Real AngleTol, |
223 | TColStd_Array1OfReal& Tol3d) const |
224 | { |
225 | Standard_Integer ii; |
226 | math_Vector V3d(1, Tol3d.Length()), V1d(1, Tol3d.Length()); |
227 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
228 | |
229 | Func->GetTolerance(BoundTol, SurfTol, AngleTol, V3d, V1d); |
230 | for (ii=1; ii<=Tol3d.Length(); ii++) Tol3d(ii) = V3d(ii); |
231 | } |
232 | |
233 | void BRepBlend_AppFuncRoot::SetTolerance(const Standard_Real Tol3d, |
234 | const Standard_Real Tol2d) |
235 | { |
236 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
237 | Standard_Integer ii, dim = Func->NbVariables(); |
238 | Func->GetTolerance(myTolerance, Tol3d); |
239 | for (ii=1; ii<=dim; ii++) { |
240 | if (myTolerance(ii)>Tol2d) { myTolerance(ii) = Tol2d;} |
241 | } |
242 | } |
243 | |
244 | gp_Pnt BRepBlend_AppFuncRoot::BarycentreOfSurf() const |
245 | { |
246 | return myBary; |
247 | } |
248 | |
249 | Standard_Real BRepBlend_AppFuncRoot::MaximalSection() const |
250 | { |
251 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
252 | return Func->GetSectionSize(); |
253 | } |
254 | |
255 | void BRepBlend_AppFuncRoot::GetMinimalWeight(TColStd_Array1OfReal& Weigths) const |
256 | { |
257 | Blend_AppFunction* Func = (Blend_AppFunction*)myFunc; |
258 | Func->GetMinimalWeight(Weigths); |
259 | } |
260 | |
261 | |
262 | //================================================================================ |
263 | // |
264 | // Function : SearchPoint |
265 | // |
81bba717 |
266 | // Purpose : Find point solution with parameter Param (on 2 Surfaces) |
7fd59977 |
267 | // |
81bba717 |
268 | // Algorithm : |
269 | // 1) Approximative solution is found from already calculated Points |
270 | // 2) Convergence is done by a method of type Newton |
7fd59977 |
271 | // |
81bba717 |
272 | // Possible causes of fails : |
273 | // - Singularity on surfaces. |
274 | // - no information oin the "line" resulting from processing. |
7fd59977 |
275 | // |
276 | //================================================================================ |
277 | |
278 | Standard_Boolean BRepBlend_AppFuncRoot::SearchPoint(Blend_AppFunction& Func, |
279 | const Standard_Real Param, |
280 | Blend_Point& Pnt) |
281 | { |
282 | Standard_Boolean Trouve; |
283 | Standard_Integer dim = Func.NbVariables(); |
81bba717 |
284 | // (1) Find a point of init |
7fd59977 |
285 | Standard_Integer I1=1, I2=myLine->NbPoints(), Index; |
286 | Standard_Real t1, t2; |
287 | |
81bba717 |
288 | // (1.a) It is checked if it is inside |
7fd59977 |
289 | if (Param < myLine->Point(I1).Parameter()) {return Standard_False;} |
290 | if (Param > myLine->Point(I2).Parameter()) {return Standard_False;} |
291 | |
81bba717 |
292 | // (1.b) Find the interval |
7fd59977 |
293 | Trouve = SearchLocation(Param, I1, I2, Index); |
294 | |
81bba717 |
295 | // (1.c) If the point is already calculated it is returned |
7fd59977 |
296 | if (Trouve) { |
297 | Pnt = myLine->Point(Index); |
298 | Vec(XInit,Pnt); |
299 | } |
300 | else { |
54adc5e9 |
301 | // (1.d) Initialisation by linear interpolation |
7fd59977 |
302 | Pnt = myLine->Point(Index); |
303 | Vec(X1,Pnt); |
304 | t1 = Pnt.Parameter(); |
305 | |
306 | Pnt = myLine->Point(Index+1); |
307 | Vec(X2,Pnt); |
308 | t2 = Pnt.Parameter(); |
309 | |
310 | Standard_Real Parammt1 = (Param-t1) / (t2-t1); |
311 | Standard_Real t2mParam = (t2-Param) / (t2-t1); |
312 | for(Standard_Integer i = 1; i <= dim; i++){ |
313 | XInit(i) = X2(i) * Parammt1 + X1(i) * t2mParam; |
314 | } |
315 | } |
316 | |
81bba717 |
317 | // (2) Calculation of the solution ------------------------ |
7fd59977 |
318 | Func.Set(Param); |
319 | Func.GetBounds(X1, X2); |
320 | math_FunctionSetRoot rsnld(Func, myTolerance, 30); |
321 | |
322 | rsnld.Perform(Func, XInit, X1, X2); |
323 | |
324 | if (!rsnld.IsDone()) { |
63c629aa |
325 | # ifdef BREPBLEND_DEB |
04232180 |
326 | std::cout << "AppFunc : RNLD Not done en t = " << Param << std::endl; |
7fd59977 |
327 | # endif |
328 | return Standard_False; |
329 | } |
330 | rsnld.Root(Sol); |
331 | |
81bba717 |
332 | // (3) Storage of the point |
7fd59977 |
333 | Point(Func,Param,Sol,Pnt); |
334 | |
81bba717 |
335 | // (4) Insertion of the point if the calculation seems long. |
7fd59977 |
336 | if ((!Trouve)&&(rsnld.NbIterations()>3)) { |
0797d9d3 |
337 | #ifdef OCCT_DEBUG |
04232180 |
338 | std::cout << "Evaluation in t = " << Param << "given" << std::endl; |
339 | rsnld.Dump(std::cout); |
7fd59977 |
340 | #endif |
341 | myLine->InsertBefore(Index+1, Pnt); |
342 | } |
343 | return Standard_True; |
344 | } |
345 | |
346 | |
347 | //============================================================================= |
348 | // |
349 | // Function : SearchLocation |
350 | // |
81bba717 |
351 | // Purpose : Binary search of the line of the parametric interval containing |
352 | // Param in the list of calculated points (myline) |
353 | // if the point of parameter Param is already stored in the list |
354 | // True is raised and ParamIndex corresponds to line of Point. |
355 | // Complexity of this algorithm is log(n)/log(2) |
7fd59977 |
356 | //================================================================================ |
357 | Standard_Boolean BRepBlend_AppFuncRoot::SearchLocation(const Standard_Real Param, |
358 | const Standard_Integer FirstIndex, |
359 | const Standard_Integer LastIndex, |
360 | Standard_Integer& ParamIndex) const |
361 | { |
362 | Standard_Integer Ideb = FirstIndex, Ifin = LastIndex, Idemi; |
363 | Standard_Real Valeur; |
364 | |
365 | Valeur = myLine->Point(Ideb).Parameter(); |
366 | if (Param == Valeur) { |
367 | ParamIndex = Ideb; |
368 | return Standard_True; |
369 | } |
370 | |
371 | Valeur = myLine->Point(Ifin).Parameter(); |
372 | if (Param == Valeur) { |
373 | ParamIndex = Ifin; |
374 | return Standard_True; |
375 | } |
376 | |
377 | while ( Ideb+1 != Ifin) { |
378 | Idemi = (Ideb+Ifin)/2; |
379 | Valeur = myLine->Point(Idemi).Parameter(); |
380 | if (Valeur < Param) {Ideb = Idemi;} |
381 | else { |
382 | if ( Valeur > Param) { Ifin = Idemi;} |
383 | else { ParamIndex = Idemi; |
384 | return Standard_True;} |
385 | } |
386 | } |
387 | |
388 | ParamIndex = Ideb; |
389 | return Standard_False; |
390 | } |
391 | |