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