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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <Blend_AppFunction.hxx>
19 #include <Blend_Point.hxx>
20 #include <BRepBlend_AppFuncRoot.hxx>
21 #include <BRepBlend_Line.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>
33 IMPLEMENT_STANDARD_RTTIEXT(BRepBlend_AppFuncRoot,Approx_SweepFunction)
35 BRepBlend_AppFuncRoot::BRepBlend_AppFuncRoot(Handle(BRepBlend_Line)& Line,
36 Blend_AppFunction& Func,
37 const Standard_Real Tol3d,
38 const Standard_Real Tol2d)
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())
47 Standard_Integer NbPoles, NbKnots, Degree, NbPoles2d;
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;}
58 Func.GetShape( NbPoles, NbKnots, Degree, NbPoles2d);
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;
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);
75 myBary.SetCoord((Xmax+Xmin)/2, (Ymax+Ymin)/2, (Zmax+Zmin)/2);
78 else {myBary.SetCoord(0,0,0);}
81 //================================================================================
83 // Purpose : Calculation of section for v = Param, if calculation fails
84 // Standard_False is raised.
85 //================================================================================
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)
93 Standard_Boolean Ok=Standard_True;
94 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
95 Ok = SearchPoint( *Func, Param, myPnt);
97 if (Ok) (*Func).Section(myPnt,
104 //================================================================================
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 //================================================================================
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)
119 Standard_Boolean Ok=Standard_True;
120 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
122 Ok = SearchPoint( *Func, Param, myPnt);
125 Ok = (*Func).Section(myPnt,
134 //===========================================================================
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 //===========================================================================
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)
153 Standard_Boolean Ok=Standard_True;
154 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
156 Ok = SearchPoint( *Func, Param, myPnt);
158 Ok = (*Func).Section(myPnt,
159 Poles, DPoles, D2Poles,
160 Poles2d, DPoles2d, D2Poles2d,
161 Weigths, DWeigths, D2Weigths);
166 Standard_Integer BRepBlend_AppFuncRoot::Nb2dCurves() const
168 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
169 Standard_Integer i,j,k,nbpol2d;
170 (*Func).GetShape(i,j,k,nbpol2d);
174 void BRepBlend_AppFuncRoot::SectionShape(Standard_Integer& NbPoles,
175 Standard_Integer& NbKnots,
176 Standard_Integer& Degree) const
178 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
180 (*Func).GetShape( NbPoles, NbKnots, Degree, ii);
183 void BRepBlend_AppFuncRoot::Knots(TColStd_Array1OfReal& TKnots) const
185 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
189 void BRepBlend_AppFuncRoot::Mults(TColStd_Array1OfInteger& TMults) const
191 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
195 Standard_Boolean BRepBlend_AppFuncRoot::IsRational() const
197 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
198 return (*Func).IsRational();
201 Standard_Integer BRepBlend_AppFuncRoot::NbIntervals(const GeomAbs_Shape S) const
203 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
204 return Func->NbIntervals(S);
207 void BRepBlend_AppFuncRoot::Intervals(TColStd_Array1OfReal& T,const GeomAbs_Shape S) const
209 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
210 Func->Intervals(T, S);
213 void BRepBlend_AppFuncRoot::SetInterval(const Standard_Real First,const Standard_Real Last)
215 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
216 Func->Set(First, Last);
219 void BRepBlend_AppFuncRoot::Resolution(const Standard_Integer Index,
220 const Standard_Real Tol,
222 Standard_Real& TolV) const
224 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
225 Func->Resolution(Index,Tol,TolU,TolV);
228 void BRepBlend_AppFuncRoot::GetTolerance(const Standard_Real BoundTol,
229 const Standard_Real SurfTol,
230 const Standard_Real AngleTol,
231 TColStd_Array1OfReal& Tol3d) const
234 math_Vector V3d(1, Tol3d.Length()), V1d(1, Tol3d.Length());
235 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
237 Func->GetTolerance(BoundTol, SurfTol, AngleTol, V3d, V1d);
238 for (ii=1; ii<=Tol3d.Length(); ii++) Tol3d(ii) = V3d(ii);
241 void BRepBlend_AppFuncRoot::SetTolerance(const Standard_Real Tol3d,
242 const Standard_Real Tol2d)
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;}
252 gp_Pnt BRepBlend_AppFuncRoot::BarycentreOfSurf() const
257 Standard_Real BRepBlend_AppFuncRoot::MaximalSection() const
259 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
260 return Func->GetSectionSize();
263 void BRepBlend_AppFuncRoot::GetMinimalWeight(TColStd_Array1OfReal& Weigths) const
265 Blend_AppFunction* Func = (Blend_AppFunction*)myFunc;
266 Func->GetMinimalWeight(Weigths);
270 //================================================================================
272 // Function : SearchPoint
274 // Purpose : Find point solution with parameter Param (on 2 Surfaces)
277 // 1) Approximative solution is found from already calculated Points
278 // 2) Convergence is done by a method of type Newton
280 // Possible causes of fails :
281 // - Singularity on surfaces.
282 // - no information oin the "line" resulting from processing.
284 //================================================================================
286 Standard_Boolean BRepBlend_AppFuncRoot::SearchPoint(Blend_AppFunction& Func,
287 const Standard_Real Param,
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;
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;}
300 // (1.b) Find the interval
301 Trouve = SearchLocation(Param, I1, I2, Index);
303 // (1.c) If the point is already calculated it is returned
305 Pnt = myLine->Point(Index);
309 // (1.d) Intialisation by linear interpolation
310 Pnt = myLine->Point(Index);
312 t1 = Pnt.Parameter();
314 Pnt = myLine->Point(Index+1);
316 t2 = Pnt.Parameter();
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;
325 // (2) Calculation of the solution ------------------------
327 Func.GetBounds(X1, X2);
328 math_FunctionSetRoot rsnld(Func, myTolerance, 30);
330 rsnld.Perform(Func, XInit, X1, X2);
332 if (!rsnld.IsDone()) {
333 # ifdef BREPBLEND_DEB
334 std::cout << "AppFunc : RNLD Not done en t = " << Param << std::endl;
336 return Standard_False;
340 // (3) Storage of the point
341 Point(Func,Param,Sol,Pnt);
343 // (4) Insertion of the point if the calculation seems long.
344 if ((!Trouve)&&(rsnld.NbIterations()>3)) {
346 std::cout << "Evaluation in t = " << Param << "given" << std::endl;
347 rsnld.Dump(std::cout);
349 myLine->InsertBefore(Index+1, Pnt);
351 return Standard_True;
355 //=============================================================================
357 // Function : SearchLocation
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 //================================================================================
365 Standard_Boolean BRepBlend_AppFuncRoot::SearchLocation(const Standard_Real Param,
366 const Standard_Integer FirstIndex,
367 const Standard_Integer LastIndex,
368 Standard_Integer& ParamIndex) const
370 Standard_Integer Ideb = FirstIndex, Ifin = LastIndex, Idemi;
371 Standard_Real Valeur;
373 Valeur = myLine->Point(Ideb).Parameter();
374 if (Param == Valeur) {
376 return Standard_True;
379 Valeur = myLine->Point(Ifin).Parameter();
380 if (Param == Valeur) {
382 return Standard_True;
385 while ( Ideb+1 != Ifin) {
386 Idemi = (Ideb+Ifin)/2;
387 Valeur = myLine->Point(Idemi).Parameter();
388 if (Valeur < Param) {Ideb = Idemi;}
390 if ( Valeur > Param) { Ifin = Idemi;}
391 else { ParamIndex = Idemi;
392 return Standard_True;}
397 return Standard_False;