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 static void evalpinit(math_Vector& parinit,
20 const Blend_Point& previousP,
21 const Standard_Real parprec,
22 const Standard_Real param,
23 const math_Vector& infbound,
24 const math_Vector& supbound,
25 const Standard_Boolean classonS1,
26 const Standard_Boolean classonS2)
28 if(previousP.IsTangencyPoint()){
29 previousP.ParametersOnS1(parinit(1),parinit(2));
30 previousP.ParametersOnS2(parinit(3),parinit(4));
33 Standard_Real u1,v1,u2,v2;
34 Standard_Real du1,dv1,du2,dv2;
35 Standard_Boolean Inside=Standard_True;
36 previousP.ParametersOnS1(u1,v1);
37 previousP.ParametersOnS2(u2,v2);
38 previousP.Tangent2dOnS1().Coord(du1,dv1);
39 previousP.Tangent2dOnS2().Coord(du2,dv2);
40 Standard_Real step = param - parprec;
44 if ((u1<infbound(1)) || (u1>supbound(1))) Inside=Standard_False;
45 if ((v1<infbound(2)) || (v1>supbound(2))) Inside=Standard_False;
50 if ((u2<infbound(3)) || (u2>supbound(3))) Inside=Standard_False;
51 if ((v2<infbound(4)) || (v2>supbound(4))) Inside=Standard_False;
60 else { // on ne joue pas au plus malin
61 previousP.ParametersOnS1(parinit(1),parinit(2));
62 previousP.ParametersOnS2(parinit(3),parinit(4));
70 void Blend_Walking::InternalPerform(Blend_Function& Func,
71 Blend_FuncInv& FuncInv,
72 const Standard_Real Bound)
75 Standard_Real stepw = pasmax;
76 Standard_Integer nbp = line->NbPoints();
77 if(nbp >= 2){ //On reprend le dernier step s'il n est pas trop petit.
79 stepw = (line->Point(2).Parameter() - line->Point(1).Parameter());
82 stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter());
84 stepw = Max(stepw,100.*tolgui);
86 Standard_Real parprec = param;
88 if (sens*(parprec - Bound) >= -tolgui) {
91 Blend_Status State = Blend_OnRst12;
92 TopAbs_State situ1 =TopAbs_IN,situ2=TopAbs_IN;
94 Standard_Integer Index1 = 0, Index2 = 0, nbarc;
95 Standard_Boolean Arrive,recad1,recad2, control;
96 Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad;
98 math_Vector tolerance(1,4),infbound(1,4),supbound(1,4),parinit(1,4);
99 math_Vector solrst1(1,4),solrst2(1,4);
101 TheExtremity Ext1,Ext2;
103 //IntSurf_Transition Tline,Tarc;
105 Func.GetTolerance(tolerance,tolesp);
106 Func.GetBounds(infbound,supbound);
108 math_FunctionSetRoot rsnld(Func,tolerance,30);
111 Arrive = Standard_False;
112 param = parprec + sens*stepw;
113 if(sens *(param - Bound) > 0.) {
114 stepw = sens*(Bound - parprec)*0.5;
115 param = parprec + sens*stepw;
118 evalpinit(parinit,previousP,parprec,param,
119 infbound,supbound, clasonS1, clasonS2);
127 Standard_Boolean bonpoint = 1;
129 rsnld.Perform(Func,parinit,infbound,supbound);
131 if (!rsnld.IsDone()) {
132 State = Blend_StepTooLarge;
138 if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
139 Min(tolerance(1),tolerance(2)),0);
140 else situ1 = TopAbs_IN;
141 if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
142 Min(tolerance(3),tolerance(4)),0);
143 else situ2 = TopAbs_IN;
145 if(bonpoint && line->NbPoints() == 1 && (situ1 != TopAbs_IN || situ2 != TopAbs_IN)){
146 State = Blend_StepTooLarge;
151 recad1 = Standard_False;
152 recad2 = Standard_False;
153 echecrecad = Standard_False;
154 control = Standard_False;
156 if (situ1 == TopAbs_OUT || situ1 == TopAbs_ON) {
157 // pb inverse sur surf1
158 //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
159 //on a pris la mauvaise solution.
160 recad1 = Recadre(FuncInv,Standard_True,
161 sol,solrst1,Index1,Isvtx1,Vtx1);
166 if ((param - wtemp)/sens>= -10*tolesp){
168 control = Standard_True;
171 echecrecad = Standard_True;
172 recad1 = Standard_False;
173 State = Blend_StepTooLarge;
179 echecrecad = Standard_True;
182 if (situ2 == TopAbs_OUT || situ2 == TopAbs_ON) {
183 // pb inverse sur surf2
184 //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
185 //on a pris la mauvaise solution.
186 recad2 = Recadre(FuncInv,Standard_False,
187 sol,solrst2,Index2,Isvtx2,Vtx2);
192 if ((param - wtemp)/sens>= -10*tolesp){
194 control = Standard_True;
197 echecrecad = Standard_True;
198 recad2 = Standard_False;
199 State = Blend_StepTooLarge;
205 echecrecad = Standard_True;
209 // Que faut il controler
210 if (recad1 && recad2) {
211 if (Abs(w1-w2) <= 10*tolgui) {
212 // pas besoin de controler les recadrage
213 // Le control pouvant se planter (cf model blend10)
214 // La tolerance est choisie grossse afin, de permetre au
215 // cheminement suivant, de poser quelques sections ...
216 control = Standard_False;
218 else if (sens*(w1-w2) < 0.) {
220 recad2 = Standard_False;
224 recad1 = Standard_False;
228 // Controle effectif des recadrage
231 if (recad1 && clasonS2) {
232 situ = recdomain2->Classify(gp_Pnt2d(solrst1(3),solrst1(4)),
233 Min(tolerance(3),tolerance(4)));
234 if (situ == TopAbs_OUT) {
235 recad1 = Standard_False;
236 echecrecad = Standard_True;
239 else if (recad2 && clasonS1) {
240 situ = recdomain1->Classify(gp_Pnt2d(solrst2(3),solrst2(4)),
241 Min(tolerance(1),tolerance(1)));
242 if (situ == TopAbs_OUT) {
243 recad2 = Standard_False;
244 echecrecad = Standard_True;
249 if(recad1 || recad2) echecrecad = Standard_False;
252 if (recad1 && recad2) {
253 //sol sur 1 et 2 a la fois
254 // On passe par les arcs , pour ne pas avoir de probleme
255 // avec les surfaces periodiques.
256 State = Blend_OnRst12;
258 p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
261 p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
267 State = Blend_OnRst1;
271 while (nbarc < Index1) {
275 p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
283 State = Blend_OnRst2;
288 while (nbarc < Index2) {
292 p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
302 Standard_Boolean testdefl = 1;
304 testdefl = !Blend_GetcontextNOTESTDEFL();
306 if (recad1 || recad2) {
308 // Il vaut mieux un pas non orthodoxe que pas de recadrage!! PMN
309 State = TestArret(Func, State,
310 (testdefl && (Abs(stepw) > 3*tolgui)),
311 Standard_False, Standard_True);
314 State = TestArret(Func, State, testdefl);
318 // Ou bien le pas max est mal regle. On divise.
319 // if(line->NbPoints() == 1) State = Blend_StepTooLarge;
320 if (stepw > 2*tolgui) State = Blend_StepTooLarge;
321 // Sinon echec recadrage. On sort avec PointsConfondus
324 cout << "Echec recadrage" << endl;
326 State = Blend_SamePoints;
332 if (Blend_GettraceDRAWSECT()){
333 Drawsect(surf1,surf2,sol,param,Func, State);
339 // Mettre a jour la ligne.
341 line->Append(previousP);
344 line->Prepend(previousP);
349 if (param == Bound) {
350 Arrive = Standard_True;
351 Ext1.SetValue(previousP.PointOnS1(),
353 previousP.Parameter(), tolesp);
354 Ext2.SetValue(previousP.PointOnS2(),
356 previousP.Parameter(), tolesp);
357 if (!previousP.IsTangencyPoint()) {
358 Ext1.SetTangent(previousP.TangentOnS1());
359 Ext2.SetTangent(previousP.TangentOnS2());
362 // Indiquer que fin sur Bound.
365 param = param + sens*stepw;
366 if (sens*(param - Bound) > - tolgui) {
370 evalpinit(parinit,previousP,parprec,param,
371 infbound,supbound, clasonS1, clasonS2);
375 case Blend_StepTooLarge :
378 if (Abs(stepw) < tolgui) {
379 Ext1.SetValue(previousP.PointOnS1(),
381 previousP.Parameter(),tolesp);
382 Ext2.SetValue(previousP.PointOnS2(),
384 previousP.Parameter(),tolesp);
385 if (!previousP.IsTangencyPoint()) {
386 Ext1.SetTangent(previousP.TangentOnS1());
387 Ext2.SetTangent(previousP.TangentOnS2());
389 Arrive = Standard_True;
390 if (line->NbPoints()>=2) {
391 // Indiquer qu on s arrete en cours de cheminement
398 param = parprec + sens*stepw; // on ne risque pas de depasser Bound.
399 evalpinit(parinit,previousP,parprec,param,
400 infbound,supbound, clasonS1, clasonS2);
405 case Blend_StepTooSmall :
407 // Mettre a jour la ligne.
409 line->Append(previousP);
412 line->Prepend(previousP);
417 stepw = Min(1.5*stepw,pasmax);
418 if (param == Bound) {
419 Arrive = Standard_True;
420 Ext1.SetValue(previousP.PointOnS1(),
422 previousP.Parameter(),tolesp);
423 Ext2.SetValue(previousP.PointOnS2(),
425 previousP.Parameter(),tolesp);
426 if (!previousP.IsTangencyPoint()) {
427 Ext1.SetTangent(previousP.TangentOnS1());
428 Ext2.SetTangent(previousP.TangentOnS2());
430 // Indiquer que fin sur Bound.
433 param = param + sens*stepw;
434 if (sens*(param - Bound) > - tolgui) {
438 evalpinit(parinit,previousP,parprec,param,
439 infbound,supbound, clasonS1, clasonS2);
446 line->Append(previousP);
449 line->Prepend(previousP);
451 MakeExtremity(Ext1,Standard_True,Index1,
452 solrst1(1),Isvtx1,Vtx1);
453 // On blinde le cas singulier ou un des recadrage a planter
454 if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) {
455 Ext2.SetValue(previousP.PointOnS1(),
456 sol(3),sol(4),tolesp);
457 if (Isvtx1) MakeSingularExtremity(Ext2, Standard_False, Vtx1);
460 Ext2.SetValue(previousP.PointOnS2(),
462 previousP.Parameter(),tolesp);
464 Arrive = Standard_True;
471 line->Append(previousP);
474 line->Prepend(previousP);
476 // On blinde le cas singulier ou un des recadrage a plante
477 if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) {
478 Ext1.SetValue(previousP.PointOnS2(),
479 sol(1),sol(2),tolesp);
480 if (Isvtx2) MakeSingularExtremity(Ext1, Standard_True, Vtx2);
483 Ext1.SetValue(previousP.PointOnS1(),
485 previousP.Parameter(),tolesp);
487 MakeExtremity(Ext2,Standard_False,Index2,
488 solrst2(1),Isvtx2,Vtx2);
489 Arrive = Standard_True;
497 line->Append(previousP);
500 line->Prepend(previousP);
503 if ( (Isvtx1 != Isvtx2) &&
504 (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2*tolesp)) ) {
505 // On blinde le cas singulier ou un seul recadrage
506 // est reconnu comme vertex.
508 Isvtx2 = Standard_True;
512 Isvtx1 = Standard_True;
517 MakeExtremity(Ext1,Standard_True,Index1,
518 solrst1(1),Isvtx1,Vtx1);
519 MakeExtremity(Ext2,Standard_False,Index2,
520 solrst2(1),Isvtx2,Vtx2);
521 Arrive = Standard_True;
525 case Blend_SamePoints :
529 cout << " Points confondus dans le cheminement" << endl;
531 Ext1.SetValue(previousP.PointOnS1(),
533 previousP.Parameter(),tolesp);
534 Ext2.SetValue(previousP.PointOnS2(),
536 previousP.Parameter(),tolesp);;
537 if (!previousP.IsTangencyPoint()) {
538 Ext1.SetTangent(previousP.TangentOnS1());
539 Ext2.SetTangent(previousP.TangentOnS2());
541 Arrive = Standard_True;
551 line->SetEndPoints(Ext1,Ext2);
554 line->SetStartPoints(Ext1,Ext2);