1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
19 //26-04-1997 modified by pmn : Initialisation plus fine de la resolution
21 Standard_Integer Blend_Walking::ArcToRecadre(const Standard_Boolean OnFirst,
22 const math_Vector& sol,
23 const Standard_Integer PrevIndex,
26 Standard_Real& ponarc)
28 Standard_Integer IndexSol = 0, nbarc = 0;
29 Standard_Boolean ok = Standard_False;
30 Standard_Boolean byinter = (line->NbPoints() != 0), okinter = 0;
31 Standard_Real distmin = RealLast();
32 Standard_Real uprev = 0.0, vprev = 0.0, prm = 0.0, dist = 0.0;
33 Handle(TheTopolTool) Iter;
36 if(byinter) previousP.ParametersOnS1(uprev,vprev);
37 pt2d.SetCoord(sol(1),sol(2));
41 if(byinter) previousP.ParametersOnS2(uprev,vprev);
42 pt2d.SetCoord(sol(3),sol(4));
45 lastpt2d.SetCoord(uprev,vprev);
47 while (Iter->More()) {
51 ok = okinter = TheBlendTool::Inters(pt2d,lastpt2d,
52 surf1,Iter->Value(),prm,dist);
54 if(!ok) ok = TheBlendTool::Project(pt2d,surf1,Iter->Value(),prm,dist);
58 ok = okinter = TheBlendTool::Inters(pt2d,lastpt2d,
59 surf2,Iter->Value(),prm,dist);
61 if(!ok) ok = TheBlendTool::Project(pt2d,surf2,Iter->Value(),prm,dist);
63 if (ok && (nbarc != PrevIndex) ) {
64 if (dist<distmin || okinter) {
68 if(okinter && (PrevIndex==0)) break;
76 Standard_Boolean Blend_Walking::Recadre(Blend_FuncInv& FuncInv,
77 const Standard_Boolean OnFirst,
78 const math_Vector& sol,
80 Standard_Integer& Indexsol,
81 Standard_Boolean& IsVtx,
83 const Standard_Real Extrap)
86 Standard_Boolean jalons_Trouve = Standard_False;
87 Standard_Boolean recadre = Standard_True, ok;
88 Standard_Boolean byinter = (line->NbPoints() != 0);
90 Standard_Integer LeJalon = 0;
92 Standard_Integer LeJalon;
94 Standard_Integer nbarc;
95 Standard_Real dist,prm,pmin, vtol;
96 gp_Pnt2d pt2d, lastpt2d;
98 math_Vector toler(1,4),infb(1,4),supb(1,4),valsol(1,4);
100 Handle(Adaptor2d_HCurve2d) thecur;
101 Handle(TheTopolTool) Iter;
103 if (OnFirst) Iter = recdomain1;
104 else Iter = recdomain2;
106 Indexsol = ArcToRecadre(OnFirst, sol, 0,
107 lastpt2d, pt2d, pmin);
108 IsVtx = Standard_False;
110 return Standard_False;
115 while (nbarc < Indexsol) {
120 TheArc thearc = Iter->Value();
123 thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
126 thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
129 // Le probleme a resoudre
130 FuncInv.Set(OnFirst,thecur);
131 FuncInv.GetBounds(infb,supb);
135 FuncInv.GetTolerance(toler,tolesp/10);//Il vaut mieux garder un peu de marge
136 math_FunctionSetRoot rsnld(FuncInv,toler,35);
137 toler *= 10; // Mais on fait les tests correctements
139 // Calcul d'un point d'init
140 Standard_Real ufirst,ulast;
141 TheBlendTool::Bounds(thecur, ufirst,ulast);
142 // Pour aider a trouver les coins singuliers on recadre eventuelement le paramtere
143 if (Abs(pmin-ufirst) < Abs(ulast-ufirst)/1000) {
146 if (Abs(pmin-ulast) < Abs(ulast-ufirst)/1000) {
151 Standard_Real lastParam = previousP.Parameter();
152 // Verifie que le recadrage n'est pas un jalons
153 if (jalons.Length()!=0) {
154 Standard_Real t1, t2, t;
155 Standard_Boolean Cherche=Standard_True;
157 if (lastParam < param) {
158 t1 = lastParam; t2 = param;
161 t1 = param; t2 = lastParam;
163 for (ii=1; ii<=jalons.Length() && Cherche; ii++) {
164 t = jalons.Value(ii).Parameter();
165 if (((t1 < t) && (t2 > t)) || (t==param)) {
166 jalons_Trouve = Standard_True;
168 Cherche = Standard_False; //Ne marche que si l'on sort simultanement
170 else Cherche = t < t2; // On s'arrete si t>=t2;
173 if (!jalons_Trouve) {
174 //Initialisation par Interpolation
175 Standard_Real lambda, u, v;
176 gp_Pnt2d Pnt, Pnt1, Pnt2;//, POnC;
177 thecur->D0(pmin, Pnt);
179 previousP.ParametersOnS2(u,v);
181 Pnt2.SetCoord(sol(3), sol(4));
184 previousP.ParametersOnS1(u,v);
186 Pnt2.SetCoord(sol(1), sol(2));
189 lambda = Pnt.Distance(lastpt2d);
190 if (lambda > 1.e-12) lambda /= Pnt.Distance(lastpt2d) + Pnt.Distance(pt2d);
193 solrst(2) = (1-lambda)*lastParam + lambda*param;
194 solrst(3) = (1-lambda)*Pnt1.X() + lambda*Pnt2.X();
195 solrst(4) = (1-lambda)*Pnt1.Y() + lambda*Pnt2.Y();
198 else { // sinon on initialise par le dernier point calcule
211 if (jalons_Trouve) { // On recupere le jalon
212 Blend_Point MonJalon;
213 Standard_Boolean periodic;
214 Standard_Real uperiod = 0, vperiod = 0;
216 Standard_Real distaux;
217 MonJalon = jalons.Value(LeJalon);
218 solrst(2) = MonJalon.Parameter();
220 MonJalon.ParametersOnS2(solrst(3), solrst(4));
221 periodic = (surf2->IsUPeriodic() || surf2->IsVPeriodic());
224 MonJalon.ParametersOnS1(solrst(3), solrst(4));
225 periodic = (surf1->IsUPeriodic() || surf1->IsVPeriodic());
228 // Recadrage eventuelle pour le cas periodique
230 Handle(Adaptor3d_HSurface) surf;
231 if (OnFirst) surf = surf2;
234 lastpt2d = thecur->Value(pmin);
236 if (surf->IsUPeriodic()) {
237 uperiod = surf->UPeriod();
238 if (solrst(3)-lastpt2d.X() > uperiod*0.6) solrst(3) -= uperiod;
239 if (solrst(3)-lastpt2d.X() < -uperiod*0.6) solrst(3) += uperiod;
241 if (surf->IsVPeriodic()) {
242 vperiod = surf->VPeriod();
243 if (solrst(4)-lastpt2d.Y() > vperiod*0.6) solrst(4) -= vperiod;
244 if (solrst(4)-lastpt2d.Y() < -vperiod*0.6) solrst(4) += vperiod;
248 // Pour le parametre sur arc il faut projeter...
249 pt2d.SetCoord(solrst(3), solrst(4));
250 Pnt = thecur->Value(ufirst);
251 dist = pt2d.Distance(Pnt);
253 Pnt = thecur->Value(ulast);
254 distaux = pt2d.Distance(Pnt);
255 if ( distaux < dist) {
260 if (dist>Precision::PConfusion()) {
263 ok = TheBlendTool::Project(pt2d,surf1,thearc,prm,distaux);
266 ok = TheBlendTool::Project(pt2d,surf2,thearc,prm,distaux);
268 if (ok && (pt2d.Distance(thecur->Value(prm)) < dist)) solrst(1) = prm;
269 else solrst(1) = pmin;
271 // On verifie le jalon
272 jalons_Trouve = (FuncInv.IsSolution(solrst,tolesp));
275 if (!jalons_Trouve) {
277 rsnld.Perform(FuncInv,solrst,infb,supb);
278 if (!rsnld.IsDone()) {
279 cout << "Walking::Recadre : RSNLD not done " << endl;
280 recadre = Standard_False;
284 recadre = FuncInv.IsSolution(solrst,tolesp);
288 // En cas d'echecs, on regarde si un autre arc
289 // peut faire l'affaire (cas des sorties a proximite d'un vertex)
290 dist = (ulast - ufirst)/100;
292 ((Abs(pmin-ulast) < dist) || (Abs(pmin-ufirst) < dist)) ) {
294 Indexsol = ArcToRecadre(OnFirst, sol, Indexsol,
295 lastpt2d, pt2d, pmin);
297 return Standard_False;
302 while (nbarc < Indexsol) {
306 thearc = Iter->Value();
309 thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
312 thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
315 // Le probleme a resoudre
316 FuncInv.Set(OnFirst,thecur);
317 FuncInv.GetBounds(infb,supb);
318 FuncInv.GetTolerance(toler,tolesp/10);//Il vaut mieux garder un peu de marge
319 math_FunctionSetRoot rsnld(FuncInv,toler,35);
320 toler *= 10; // Mais on fait les tests correctements
322 rsnld.Perform(FuncInv,solrst,infb,supb);
324 if (!rsnld.IsDone()) {
325 cout << "Walking::Recadre : RSNLD not done " << endl;
326 recadre = Standard_False;
330 recadre = FuncInv.IsSolution(solrst,tolesp);
335 // Classification topologique
337 thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
340 thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
342 TheBlendTool::Bounds(thecur, ufirst,ulast);
344 Iter->Initialize(thearc);
345 Iter->InitVertexIterator();
346 IsVtx = !Iter->MoreVertex();
348 Vtx = Iter->Vertex();
349 vtol = 0.4*Abs(ulast-ufirst); // Un majorant de la tolerance
350 if (vtol > Max(TheBlendTool::Tolerance(Vtx,thearc), toler(1)))
351 vtol = Max(TheBlendTool::Tolerance(Vtx,thearc), toler(1));
352 if (Abs(TheBlendTool::Parameter(Vtx,thearc)-solrst(1)) <= vtol) {
353 IsVtx = Standard_True; // On est dans la boule du vertex ou
354 // le vertex est dans la "boule" du recadrage
358 IsVtx = !Iter->MoreVertex();
361 if (!Iter->MoreVertex()) {
362 IsVtx = Standard_False;
364 return Standard_True;
366 return Standard_False;
370 void Blend_Walking::Transition(const Standard_Boolean OnFirst,
372 const Standard_Real Param,
373 IntSurf_Transition& TLine,
374 IntSurf_Transition& TArc)
376 Standard_Boolean computetranstionaveclacorde = 0;
378 Blend_Point prevprev;
380 if(previousP.IsTangencyPoint()){
381 if(line->NbPoints() < 2) return;
382 computetranstionaveclacorde = 1;
384 prevprev = line->Point(2);
387 prevprev = line->Point(line->NbPoints() - 1);
394 gp_Vec d1u,d1v,normale,tgrst;
396 CSLib_NormalStatus stat;
398 TheArcTool::D1(A,Param,p2d,dp2d);
400 TheSurfaceTool::D1(surf1,p2d.X(),p2d.Y(),pbid,d1u,d1v);
401 if(!computetranstionaveclacorde) tgline = previousP.TangentOnS1();
402 else tgline = gp_Vec(prevprev.PointOnS1(),previousP.PointOnS1());
405 TheSurfaceTool::D1(surf2,p2d.X(),p2d.Y(),pbid,d1u,d1v);
406 if(!computetranstionaveclacorde) tgline = previousP.TangentOnS2();
407 else tgline = gp_Vec(prevprev.PointOnS2(),previousP.PointOnS2());
410 tgrst.SetLinearForm(dp2d.X(),d1u,dp2d.Y(),d1v);
412 CSLib::Normal(d1u, d1v, 1.e-9, stat, thenormal);
413 if (stat == CSLib_Defined) normale.SetXYZ(thenormal.XYZ());
415 Handle(Adaptor3d_HSurface) surf;
416 if (OnFirst) surf = surf1;
418 Standard_Integer iu, iv;
419 TColgp_Array2OfVec Der(0, 2 , 0, 2);
420 TheSurfaceTool::D2(surf,p2d.X(),p2d.Y(),pbid, Der(1,0), Der(0,1),
421 Der(2,0), Der(0,2), Der(1,1));
422 Der(2,1) = TheSurfaceTool::DN(surf, p2d.X(), p2d.Y(), 2,1);
423 Der(1,2) = TheSurfaceTool::DN(surf,p2d.X(),p2d.Y(), 1,2);
424 Der(2,2) = TheSurfaceTool::DN(surf,p2d.X(),p2d.Y(), 2,2);
425 CSLib::Normal(2, Der, 1.e-9,
427 TheSurfaceTool::FirstUParameter(surf),
428 TheSurfaceTool::LastUParameter(surf),
429 TheSurfaceTool::FirstVParameter(surf),
430 TheSurfaceTool::LastVParameter(surf),
431 stat, thenormal, iu, iv);
432 normale.SetXYZ(thenormal.XYZ());
434 if (stat == CSLib_InfinityOfSolutions)
435 cout << "Blend_Walking::Transition : Infinite de Normal" << endl;
439 IntSurf::MakeTransition(tgline,tgrst,normale,TLine,TArc);
444 void Blend_Walking::MakeExtremity(TheExtremity& Extrem,
445 const Standard_Boolean OnFirst,
446 const Standard_Integer Index,
447 const Standard_Real Param,
448 const Standard_Boolean IsVtx,
449 const TheVertex& Vtx)
452 IntSurf_Transition Tline,Tarc;
453 Standard_Integer nbarc;
454 Handle(TheTopolTool) Iter;
457 Extrem.SetValue(previousP.PointOnS1(),
459 previousP.Parameter(), tolesp);
460 if (!previousP.IsTangencyPoint())
461 Extrem.SetTangent(previousP.TangentOnS1());
465 Extrem.SetValue(previousP.PointOnS2(),
467 previousP.Parameter(), tolesp);
468 if (!previousP.IsTangencyPoint())
469 Extrem.SetTangent(previousP.TangentOnS2());
476 while (nbarc < Index) {
481 Transition(OnFirst,Iter->Value(),Param,Tline,Tarc);
482 Extrem.AddArc(Iter->Value(),Param,Tline,Tarc);
483 if (IsVtx) Extrem.SetVertex(Vtx);
486 void Blend_Walking::MakeSingularExtremity( TheExtremity& Extrem,
487 const Standard_Boolean OnFirst,
488 const TheVertex& Vtx)
490 IntSurf_Transition Tline,Tarc;
491 Handle(TheTopolTool) Iter;
496 if (!previousP.IsTangencyPoint())
497 Extrem.SetTangent(previousP.TangentOnS1());
500 if (!previousP.IsTangencyPoint())
501 Extrem.SetTangent(previousP.TangentOnS2());
506 Extrem.SetVertex(Vtx);
507 while (Iter->More()) {
508 TheArc arc = Iter->Value();
509 Iter->Initialize(arc);
510 Iter->InitVertexIterator();
511 while (Iter->MoreVertex()) {
512 if (Iter->Identical(Vtx,Iter->Vertex())) {
513 prm = TheBlendTool::Parameter(Vtx,arc);
514 Transition(OnFirst,arc,prm,Tline,Tarc);
515 Extrem.AddArc(arc,prm,Tline,Tarc);