Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/opencascade/Blend_Walking_4.gxx is written in an unsupported language. File is not indexed.

0001 // Copyright (c) 1995-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014 
0015 #include <gce_MakePln.hxx>
0016 #include <Extrema_ExtPS.hxx>
0017 #include <Extrema_ExtPC.hxx>
0018 
0019 #ifdef DRAW
0020 #include <DrawTrSurf.hxx>
0021 #endif
0022 
0023 
0024 static const Standard_Real CosRef3D = 0.88;
0025 
0026 static void RecadreIfPeriodic(Standard_Real& NewU,
0027                               Standard_Real& NewV,
0028                               const Standard_Real OldU,
0029                               const Standard_Real OldV,
0030                               const Standard_Real UPeriod,
0031                               const Standard_Real VPeriod)
0032 {
0033   if (UPeriod > 0.)
0034   {
0035     Standard_Real sign = (NewU < OldU)? 1 : -1;
0036     while (Abs(NewU - OldU) > UPeriod/2)
0037       NewU += sign * UPeriod;
0038   }
0039   if (VPeriod > 0.)
0040   {
0041     Standard_Real sign = (NewV < OldV)? 1 : -1;
0042     while (Abs(NewV - OldV) > VPeriod/2)
0043       NewV += sign * VPeriod;
0044   }
0045 }
0046 
0047 static void evalpinit(math_Vector& parinit,
0048                       const Blend_Point& previousP,
0049                       const Standard_Real parprec,
0050                       const Standard_Real param,
0051                       const math_Vector& infbound,
0052                       const math_Vector& supbound,
0053                       const Standard_Boolean classonS1, 
0054                       const Standard_Boolean classonS2)
0055 {
0056   if(previousP.IsTangencyPoint()){
0057     previousP.ParametersOnS1(parinit(1),parinit(2));
0058     previousP.ParametersOnS2(parinit(3),parinit(4));
0059   }
0060   else {
0061     Standard_Real u1,v1,u2,v2;
0062     Standard_Real du1,dv1,du2,dv2;
0063     Standard_Boolean Inside=Standard_True;
0064     previousP.ParametersOnS1(u1,v1);
0065     previousP.ParametersOnS2(u2,v2);
0066     previousP.Tangent2dOnS1().Coord(du1,dv1);
0067     previousP.Tangent2dOnS2().Coord(du2,dv2);
0068     Standard_Real step = param - parprec;
0069     u1+= step*du1;
0070     v1+= step*dv1;
0071     if ( classonS1 ) {
0072       if ((u1<infbound(1)) || (u1>supbound(1))) Inside=Standard_False;
0073       if ((v1<infbound(2)) || (v1>supbound(2))) Inside=Standard_False;
0074     }
0075     u2+= step*du2;
0076     v2+= step*dv2;
0077     if ( classonS2) {
0078       if ((u2<infbound(3)) || (u2>supbound(3))) Inside=Standard_False;
0079       if ((v2<infbound(4)) || (v2>supbound(4))) Inside=Standard_False;
0080     }
0081 
0082     if (Inside) {
0083       parinit(1) = u1;
0084       parinit(2) = v1;
0085       parinit(3) = u2;
0086       parinit(4) = v2;
0087     }
0088     else { // on ne joue pas au plus malin
0089       previousP.ParametersOnS1(parinit(1),parinit(2));
0090       previousP.ParametersOnS2(parinit(3),parinit(4));
0091     }
0092     
0093   }
0094 }
0095 
0096 
0097 
0098 void Blend_Walking::InternalPerform(Blend_Function& Func,
0099                                     Blend_FuncInv& FuncInv,
0100                                     const Standard_Real Bound)
0101 {
0102   Standard_Real Cosi = 0., Cosi2 = 0.;
0103 
0104   Standard_Real stepw = pasmax;
0105   Standard_Integer nbp = line->NbPoints();
0106   if(nbp >= 2){ //On reprend le dernier step s'il n est pas trop petit.
0107     if(sens < 0.){
0108       stepw = (line->Point(2).Parameter() - line->Point(1).Parameter());
0109     }
0110     else{
0111       stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter());
0112     }
0113     stepw = Max(stepw,100.*tolgui);
0114   }
0115   Standard_Real parprec = param;
0116   gp_Vec TgOnGuide, PrevTgOnGuide;
0117   gp_Pnt PtOnGuide;
0118   hguide->D1(parprec, PtOnGuide, TgOnGuide);
0119   PrevTgOnGuide = TgOnGuide;
0120 
0121   if (sens*(parprec - Bound) >= -tolgui) {
0122     return;
0123   }
0124   Blend_Status State = Blend_OnRst12;
0125   TopAbs_State situ1 =TopAbs_IN,situ2=TopAbs_IN;
0126   Standard_Real w1,w2;
0127   Standard_Integer Index1 = 0, Index2 = 0, nbarc;
0128   Standard_Boolean Arrive,recad1,recad2, control;
0129   Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False, echecrecad;
0130   gp_Pnt2d p2d;
0131   math_Vector tolerance(1,4),infbound(1,4),supbound(1,4),parinit(1,4);
0132   math_Vector solrst1(1,4),solrst2(1,4);
0133   TheVertex Vtx1,Vtx2;
0134   TheExtremity Ext1,Ext2;
0135 
0136   //IntSurf_Transition Tline,Tarc;
0137 
0138   Func.GetTolerance(tolerance,tolpoint3d);
0139   Func.GetBounds(infbound,supbound);
0140 
0141   math_FunctionSetRoot rsnld(Func,tolerance,30);
0142   parinit = sol;
0143 
0144   Arrive = Standard_False;
0145   param = parprec + sens*stepw;
0146   if(sens *(param - Bound) > 0.) {
0147     stepw = sens*(Bound - parprec)*0.5;
0148     param = parprec + sens*stepw;
0149   }
0150 
0151   evalpinit(parinit,previousP,parprec,param,
0152             infbound,supbound, clasonS1, clasonS2);
0153 
0154   while (!Arrive) {
0155 
0156 #ifdef OCCT_DEBUG
0157     sectioncalculee = 0;
0158     nbcomputedsection++;
0159 #endif
0160 
0161     hguide->D1(param, PtOnGuide, TgOnGuide);
0162     //Check deflection on guide
0163     Cosi = PrevTgOnGuide * TgOnGuide;
0164     if (Cosi < gp::Resolution()) //angle>=pi/2 or null magnitude
0165       Cosi2 = 0.;
0166     else
0167       Cosi2 = Cosi * Cosi / PrevTgOnGuide.SquareMagnitude() / TgOnGuide.SquareMagnitude();
0168     if (Cosi2 < CosRef3D) //angle 3d too great
0169     {
0170       State = Blend_StepTooLarge;
0171       stepw = stepw/2.;
0172       param = parprec + sens*stepw;  // on ne risque pas de depasser Bound.
0173       if (Abs(stepw) < tolgui) {
0174         Ext1.SetValue(previousP.PointOnS1(),
0175                       sol(1),sol(2),
0176                       previousP.Parameter(),tolpoint3d);
0177         Ext2.SetValue(previousP.PointOnS2(),
0178                       sol(3),sol(4),
0179                       previousP.Parameter(),tolpoint3d);
0180         if (!previousP.IsTangencyPoint()) {
0181           Ext1.SetTangent(previousP.TangentOnS1());
0182           Ext2.SetTangent(previousP.TangentOnS2());
0183         }
0184         Arrive = Standard_True;
0185       }
0186       continue;
0187     }
0188     PrevTgOnGuide = TgOnGuide;
0189     //////////////////////////
0190     
0191     Standard_Boolean bonpoint = 1;
0192     Func.Set(param);
0193     rsnld.Perform(Func,parinit,infbound,supbound);
0194 
0195     if (!rsnld.IsDone()) {
0196       State = Blend_StepTooLarge;
0197       bonpoint = 0;
0198     }
0199     else {
0200       rsnld.Root(sol);
0201 
0202       if(clasonS1) situ1 = domain1->Classify(gp_Pnt2d(sol(1),sol(2)),
0203                                              Min(tolerance(1),tolerance(2)),0);
0204       else situ1 = TopAbs_IN;
0205       if(clasonS2) situ2 = domain2->Classify(gp_Pnt2d(sol(3),sol(4)),
0206                                              Min(tolerance(3),tolerance(4)),0);
0207       else situ2 = TopAbs_IN;
0208     }
0209     if(bonpoint && line->NbPoints() == 1 && (situ1 != TopAbs_IN || situ2 != TopAbs_IN)){
0210       State = Blend_StepTooLarge;
0211       bonpoint = 0;
0212     }
0213     if(bonpoint){
0214       w1 = w2 = Bound;
0215       recad1 = Standard_False;
0216       recad2 = Standard_False;
0217       echecrecad = Standard_False;
0218       control = Standard_False;
0219 
0220       if (situ1 == TopAbs_OUT || situ1 == TopAbs_ON) {
0221         // pb inverse sur surf1
0222         //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
0223         //on a pris la mauvaise solution.
0224         recad1 = Recadre(FuncInv,Standard_True,
0225                          sol,solrst1,Index1,Isvtx1,Vtx1);
0226 
0227         if (recad1) {
0228           Standard_Real wtemp;
0229           wtemp  = solrst1(2);
0230           if ((param - wtemp)/sens>= -10*tolgui){
0231             w1 = solrst1(2);
0232             control = Standard_True;
0233           }
0234           else {
0235             echecrecad = Standard_True;
0236             recad1 = Standard_False;
0237             State = Blend_StepTooLarge;
0238             bonpoint = 0;
0239             stepw = stepw/2.;
0240           }
0241         }
0242         else {
0243           echecrecad = Standard_True;
0244         }
0245       }
0246       if (situ2 == TopAbs_OUT || situ2 == TopAbs_ON) {
0247         // pb inverse sur surf2
0248         //Si le recadrage s'effectue dans le sens de la progression a une tolerance pres,
0249         //on a pris la mauvaise solution.
0250         recad2 = Recadre(FuncInv,Standard_False,
0251                          sol,solrst2,Index2,Isvtx2,Vtx2);
0252         
0253         if (recad2) {
0254           Standard_Real wtemp;
0255           wtemp = solrst2(2);
0256           if ((param - wtemp)/sens>= -10*tolgui){
0257             w2 = solrst2(2);
0258             control = Standard_True;
0259           }
0260           else {
0261             echecrecad = Standard_True;
0262             recad2 = Standard_False;
0263             State = Blend_StepTooLarge;
0264             bonpoint = 0;
0265             stepw = stepw/2.;
0266           }
0267         }
0268         else {
0269           echecrecad = Standard_True;
0270         }
0271       }
0272       
0273       // Que faut il controler
0274       if (recad1 && recad2) {
0275           if (Abs(w1-w2) <= 10*tolgui) {
0276           // pas besoin de controler les recadrage
0277           // Le control pouvant se planter (cf model blend10)
0278           // La tolerance est choisie grossse afin, de permetre au 
0279           // cheminement suivant, de poser quelques sections ...
0280           control = Standard_False; 
0281           }
0282           else if (sens*(w1-w2) < 0.) {
0283             //sol sur 1 ?
0284             recad2 = Standard_False;
0285           }
0286           else {
0287             //sol sur 2 ?
0288             recad1 = Standard_False;
0289           }
0290         }
0291 
0292       // Controle effectif des recadrage
0293       if (control) {
0294         TopAbs_State situ;
0295         if (recad1 && clasonS2) {
0296           situ = recdomain2->Classify(gp_Pnt2d(solrst1(3),solrst1(4)),
0297                                       Min(tolerance(3),tolerance(4)));
0298           if (situ == TopAbs_OUT) {
0299             recad1 = Standard_False;
0300             echecrecad = Standard_True;
0301           }
0302         }
0303         else if (recad2 && clasonS1) {
0304           situ = recdomain1->Classify(gp_Pnt2d(solrst2(3),solrst2(4)),
0305                                       Min(tolerance(1),tolerance(1)));
0306           if (situ == TopAbs_OUT) {
0307             recad2 = Standard_False;
0308             echecrecad = Standard_True;
0309           }
0310         }
0311       }
0312 
0313       if(recad1 || recad2) echecrecad = Standard_False;
0314 
0315       if (!echecrecad) {
0316         if (recad1 && recad2) {
0317           //sol sur 1 et 2 a la fois
0318           // On passe par les arcs , pour ne pas avoir de probleme
0319           // avec les surfaces periodiques.
0320           State = Blend_OnRst12;
0321           param =  (w1+w2)/2;
0322           gp_Pnt Pnt1, Pnt2;
0323           p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
0324           sol(1) = p2d.X();
0325           sol(2) = p2d.Y();
0326           Pnt1 = TheSurfaceTool::Value(surf1,sol(1),sol(2));
0327           p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
0328           sol(3) = p2d.X();
0329           sol(4) = p2d.Y();
0330           Pnt2 = TheSurfaceTool::Value(surf2,sol(3),sol(4));
0331           const Standard_Real TolProd = 1.e-5;
0332           Standard_Real SavedParams [2];
0333           Standard_Boolean SameDirs [2] = {Standard_False, Standard_False};
0334           ChFiDS_ElSpine& theElSpine = *hguide;
0335           SavedParams[0] = theElSpine.GetSavedFirstParameter();
0336           SavedParams[1] = theElSpine.GetSavedLastParameter();
0337           for (Standard_Integer ind = 0; ind < 2; ind++)
0338           {
0339             if (!Precision::IsInfinite(SavedParams[ind]))
0340             {
0341               //Check the original first and last parameters of guide curve
0342               //for equality to found parameter <param>:
0343               //check equality of tangent to guide curve and
0344               //normal to plane built on 3 points:
0345               //point on guide curve and points on restrictions of adjacent
0346               //surfaces.
0347               gp_Pnt Pnt0;
0348               gp_Vec Dir0;
0349               hguide->D1(SavedParams[ind], Pnt0, Dir0);
0350               Standard_Real Length = Dir0.Magnitude();
0351               if (Length <= gp::Resolution())
0352                 continue;
0353               Dir0 /= Length;
0354               gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2);
0355               if (!PlaneBuilder.IsDone())
0356                 continue;
0357               gp_Pln thePlane = PlaneBuilder.Value();
0358               gp_Dir DirPlane = thePlane.Axis().Direction();
0359               gp_Vec theProd = Dir0 ^ DirPlane;
0360               Standard_Real ProdMod = theProd.Magnitude();
0361               if (ProdMod <= TolProd)
0362                 SameDirs[ind] = Standard_True;
0363             }
0364           }
0365           Standard_Real theParam = Precision::Infinite();
0366           //Choose the closest parameter
0367           if (SameDirs[0] && SameDirs[1])
0368             theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))?
0369               SavedParams[0] : SavedParams[1];
0370           else if (SameDirs[0])
0371             theParam = SavedParams[0];
0372           else if (SameDirs[1])
0373             theParam = SavedParams[1];
0374 
0375           Standard_Real NewU, NewV, NewParam;
0376           gp_Pnt NewPnt;
0377           Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, Pnt1,
0378                                                                 NewU, NewV, NewPnt, NewParam);
0379           if (Corrected)
0380           {
0381             if (Abs(param - NewParam) < Abs(param - theParam))
0382               theParam = NewParam;
0383           }
0384           
0385           if (!Precision::IsInfinite(theParam))
0386             param = theParam;
0387         }
0388         else if (recad1) {
0389           // sol sur 1
0390           State = Blend_OnRst1;
0391           param = w1;
0392           recdomain1->Init();
0393           nbarc = 1;
0394           while (nbarc < Index1) {
0395             nbarc++;
0396             recdomain1->Next();
0397           }
0398           p2d = TheArcTool::Value(recdomain1->Value(),solrst1(1));
0399           sol(1) = p2d.X();
0400           sol(2) = p2d.Y();
0401           sol(3) = solrst1(3);
0402           sol(4) = solrst1(4);
0403           gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,sol(1),sol(2));
0404           Standard_Real NewU, NewV, NewParam;
0405           gp_Pnt NewPnt;
0406           Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, thePntOnRst,
0407                                                                 NewU, NewV, NewPnt, NewParam);
0408           if (Corrected)
0409           {
0410             param = NewParam;
0411             sol(3) = NewU;
0412             sol(4) = NewV;
0413           }
0414         }
0415         else if (recad2) {
0416           //sol sur 2
0417           State = Blend_OnRst2;
0418           param = w2;
0419           
0420           recdomain2->Init();
0421           nbarc = 1;
0422           while (nbarc < Index2) {
0423             nbarc++;
0424             recdomain2->Next();
0425           }
0426           p2d = TheArcTool::Value(recdomain2->Value(),solrst2(1));
0427           sol(1) = solrst2(3);
0428           sol(2) = solrst2(4);
0429           sol(3) = p2d.X();
0430           sol(4) = p2d.Y();
0431           gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,sol(3),sol(4));
0432           Standard_Real NewU, NewV, NewParam;
0433           gp_Pnt NewPnt;
0434           Standard_Boolean Corrected = CorrectExtremityOnOneRst(2, sol(1), sol(2), param, thePntOnRst,
0435                                                                 NewU, NewV, NewPnt, NewParam);
0436           if (Corrected)
0437           {
0438             param = NewParam;
0439             sol(1) = NewU;
0440             sol(2) = NewV;
0441           }
0442         }
0443         else {
0444           State = Blend_OK;
0445         }
0446 
0447         Standard_Boolean testdefl = 1;
0448 #ifdef OCCT_DEBUG
0449         testdefl = !Blend_GetcontextNOTESTDEFL();
0450 #endif  
0451         if (recad1 || recad2) {
0452           Func.Set(param);
0453           // Il vaut mieux un pas non orthodoxe que pas de recadrage!! PMN
0454           State = TestArret(Func, State, 
0455                             (testdefl && (Abs(stepw) > 3*tolgui)),
0456                             Standard_False, Standard_True);
0457         }
0458         else {
0459           State = TestArret(Func, State, testdefl);
0460         }
0461       }
0462       else { 
0463         // Ou bien le pas max est mal regle. On divise.
0464 //      if(line->NbPoints() == 1) State = Blend_StepTooLarge;
0465         if (stepw > 2*tolgui) State = Blend_StepTooLarge;
0466         // Sinon echec recadrage. On sort avec PointsConfondus
0467         else {
0468 #ifdef OCCT_DEBUG
0469           std::cout << "Echec recadrage" << std::endl;
0470 #endif    
0471           State = Blend_SamePoints;
0472         }
0473       }
0474     }
0475 
0476 #ifdef OCCT_DEBUG
0477     if (Blend_GettraceDRAWSECT()){
0478       Drawsect(surf1,surf2,sol,param,Func, State);
0479     }
0480 #endif
0481     switch (State) {
0482     case Blend_OK :
0483       {  
0484         // Mettre a jour la ligne.
0485         if (sens>0.) {
0486           line->Append(previousP);
0487         }
0488         else {
0489           line->Prepend(previousP);
0490         }
0491 #ifdef DRAW
0492         Standard_Integer nbpts = line->NbPoints();
0493         char name [100];
0494         sprintf(name, "pg%d", nbpts);
0495         DrawTrSurf::Set(name, PtOnGuide);
0496         sprintf(name, "p1_%d", nbpts);
0497         DrawTrSurf::Set(name, previousP.PointOnS1());
0498         sprintf(name, "p2_%d", nbpts);
0499         DrawTrSurf::Set(name, previousP.PointOnS2());
0500 #endif
0501 
0502         parprec = param;
0503 
0504         if (param == Bound) {
0505           Arrive = Standard_True;
0506           Ext1.SetValue(previousP.PointOnS1(),
0507                         sol(1),sol(2),
0508                         previousP.Parameter(), tolpoint3d);
0509           Ext2.SetValue(previousP.PointOnS2(),
0510                         sol(3),sol(4),
0511                         previousP.Parameter(), tolpoint3d);
0512           if (!previousP.IsTangencyPoint()) {
0513             Ext1.SetTangent(previousP.TangentOnS1());
0514             Ext2.SetTangent(previousP.TangentOnS2());
0515           }
0516 
0517           // Indiquer que fin sur Bound.
0518         }
0519         else {
0520           param = param + sens*stepw;
0521           if (sens*(param - Bound) > - tolgui) {
0522             param = Bound;
0523           }
0524         }
0525         evalpinit(parinit,previousP,parprec,param,
0526                   infbound,supbound, clasonS1, clasonS2);
0527       }
0528       break;
0529       
0530     case Blend_StepTooLarge :
0531       {
0532         stepw = stepw/2.;
0533         if (Abs(stepw) < tolgui) {
0534           Ext1.SetValue(previousP.PointOnS1(),
0535                         sol(1),sol(2),
0536                         previousP.Parameter(),tolpoint3d);
0537           Ext2.SetValue(previousP.PointOnS2(),
0538                         sol(3),sol(4),
0539                         previousP.Parameter(),tolpoint3d);
0540           if (!previousP.IsTangencyPoint()) {
0541             Ext1.SetTangent(previousP.TangentOnS1());
0542             Ext2.SetTangent(previousP.TangentOnS2());
0543           }
0544           Arrive = Standard_True;
0545           if (line->NbPoints()>=2) {
0546             // Indiquer qu on s arrete en cours de cheminement
0547           }
0548 //        else {
0549 //          line->Clear();
0550 //        }
0551         }
0552         else {
0553           param = parprec + sens*stepw;  // on ne risque pas de depasser Bound.
0554           evalpinit(parinit,previousP,parprec,param,
0555                     infbound,supbound, clasonS1, clasonS2);
0556         }
0557       }
0558       break;
0559       
0560     case Blend_StepTooSmall :
0561       {
0562         // Mettre a jour la ligne.
0563         if (sens>0.) {
0564           line->Append(previousP);
0565         }
0566         else {
0567           line->Prepend(previousP);
0568         }
0569 #ifdef DRAW
0570         Standard_Integer nbpts = line->NbPoints();
0571         char name [100];
0572         sprintf(name, "pg%d", nbpts);
0573         DrawTrSurf::Set(name, PtOnGuide);
0574         sprintf(name, "p1_%d", nbpts);
0575         DrawTrSurf::Set(name, previousP.PointOnS1());
0576         sprintf(name, "p2_%d", nbpts);
0577         DrawTrSurf::Set(name, previousP.PointOnS2());
0578 #endif
0579 
0580         parprec = param;
0581 
0582         stepw = Min(1.5*stepw,pasmax);
0583         if (param == Bound) {
0584           Arrive = Standard_True;
0585           Ext1.SetValue(previousP.PointOnS1(),
0586                         sol(1),sol(2),
0587                         previousP.Parameter(),tolpoint3d);
0588           Ext2.SetValue(previousP.PointOnS2(),
0589                         sol(3),sol(4), 
0590                         previousP.Parameter(),tolpoint3d);
0591           if (!previousP.IsTangencyPoint()) {
0592             Ext1.SetTangent(previousP.TangentOnS1());
0593             Ext2.SetTangent(previousP.TangentOnS2());
0594           }
0595           // Indiquer que fin sur Bound.
0596         }
0597         else {
0598           param = param + sens*stepw;
0599           if (sens*(param - Bound) > - tolgui) {
0600             param = Bound;
0601           }
0602         }
0603         evalpinit(parinit,previousP,parprec,param,
0604                   infbound,supbound, clasonS1, clasonS2);
0605       }
0606       break;
0607       
0608     case Blend_OnRst1  :
0609       {
0610         if (sens>0.) {
0611           line->Append(previousP);
0612         }
0613         else {
0614           line->Prepend(previousP);
0615         }
0616 #ifdef DRAW
0617         Standard_Integer nbpts = line->NbPoints();
0618         char name [100];
0619         sprintf(name, "pg%d", nbpts);
0620         DrawTrSurf::Set(name, PtOnGuide);
0621         sprintf(name, "p1_%d", nbpts);
0622         DrawTrSurf::Set(name, previousP.PointOnS1());
0623         sprintf(name, "p2_%d", nbpts);
0624         DrawTrSurf::Set(name, previousP.PointOnS2());
0625 #endif
0626 
0627         MakeExtremity(Ext1,Standard_True,Index1,
0628                       solrst1(1),Isvtx1,Vtx1);
0629         // On blinde le cas singulier ou un des recadrage a planter
0630         if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2.0 * tolpoint3d)) {
0631           Ext2.SetValue(previousP.PointOnS1(),
0632                         sol(3),sol(4),tolpoint3d);
0633           if (Isvtx1) MakeSingularExtremity(Ext2, Standard_False, Vtx1);
0634         }
0635         else {
0636           Ext2.SetValue(previousP.PointOnS2(),
0637                         sol(3),sol(4),
0638                         previousP.Parameter(),tolpoint3d);
0639         }
0640         Arrive = Standard_True;
0641       }
0642       break;
0643 
0644     case Blend_OnRst2  :
0645       {
0646         if (sens>0.) {
0647           line->Append(previousP);
0648         }
0649         else {
0650           line->Prepend(previousP);
0651         }
0652 #ifdef DRAW
0653         Standard_Integer nbpts = line->NbPoints();
0654         char name [100];
0655         sprintf(name, "pg%d", nbpts);
0656         DrawTrSurf::Set(name, PtOnGuide);
0657         sprintf(name, "p1_%d", nbpts);
0658         DrawTrSurf::Set(name, previousP.PointOnS1());
0659         sprintf(name, "p2_%d", nbpts);
0660         DrawTrSurf::Set(name, previousP.PointOnS2());
0661 #endif
0662 
0663         // On blinde le cas singulier ou un des recadrage a plante
0664         if (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2.0 * tolpoint3d)) {
0665           Ext1.SetValue(previousP.PointOnS2(),
0666                         sol(1),sol(2),tolpoint3d);
0667           if (Isvtx2) MakeSingularExtremity(Ext1, Standard_True, Vtx2);
0668         }
0669         else {
0670           Ext1.SetValue(previousP.PointOnS1(),
0671                         sol(1),sol(2),
0672                         previousP.Parameter(),tolpoint3d);
0673         }
0674         MakeExtremity(Ext2,Standard_False,Index2,
0675                       solrst2(1),Isvtx2,Vtx2);
0676         Arrive = Standard_True;
0677       }
0678       break;
0679 
0680 
0681     case Blend_OnRst12 :
0682       {
0683         if (sens>0.) {
0684           line->Append(previousP);
0685         }
0686         else {
0687           line->Prepend(previousP);
0688         }
0689 #ifdef DRAW
0690         Standard_Integer nbpts = line->NbPoints();
0691         char name [100];
0692         sprintf(name, "pg%d", nbpts);
0693         DrawTrSurf::Set(name, PtOnGuide);
0694         sprintf(name, "p1_%d", nbpts);
0695         DrawTrSurf::Set(name, previousP.PointOnS1());
0696         sprintf(name, "p2_%d", nbpts);
0697         DrawTrSurf::Set(name, previousP.PointOnS2());
0698 #endif
0699 
0700         if ( (Isvtx1 != Isvtx2) &&
0701             (previousP.PointOnS1().IsEqual(previousP.PointOnS2(), 2.0 * tolpoint3d)) ) {
0702           // On blinde le cas singulier ou un seul recadrage
0703           // est reconnu comme vertex.
0704           if (Isvtx1) {
0705             Isvtx2 = Standard_True;
0706             Vtx2 = Vtx1;
0707           }
0708           else {
0709             Isvtx1 = Standard_True;
0710             Vtx1 = Vtx2;
0711           }
0712         }
0713 
0714         MakeExtremity(Ext1,Standard_True,Index1,
0715                       solrst1(1),Isvtx1,Vtx1);
0716         MakeExtremity(Ext2,Standard_False,Index2,
0717                       solrst2(1),Isvtx2,Vtx2);
0718         Arrive = Standard_True;
0719       }
0720       break;
0721 
0722     case Blend_SamePoints :
0723       {
0724         // On arrete
0725 #ifdef OCCT_DEBUG
0726         std::cout << " Points confondus dans le cheminement" << std::endl;
0727 #endif
0728         Ext1.SetValue(previousP.PointOnS1(),
0729                       sol(1),sol(2),
0730                       previousP.Parameter(),tolpoint3d);
0731         Ext2.SetValue(previousP.PointOnS2(),
0732                       sol(3),sol(4),
0733                       previousP.Parameter(),tolpoint3d);
0734         if (!previousP.IsTangencyPoint()) {
0735           Ext1.SetTangent(previousP.TangentOnS1());
0736           Ext2.SetTangent(previousP.TangentOnS2());
0737         }
0738         Arrive = Standard_True;
0739       }
0740       break;
0741     default:
0742       break;
0743     }
0744     if (Arrive) {
0745       if (sens > 0.) {
0746         line->SetEndPoints(Ext1,Ext2);
0747       }
0748       else {
0749         line->SetStartPoints(Ext1,Ext2);
0750 
0751       }
0752     }
0753 
0754   }
0755 
0756 }
0757 
0758 Standard_Boolean Blend_Walking::CorrectExtremityOnOneRst(const Standard_Integer IndexOfRst,
0759                                                          const Standard_Real theU,
0760                                                          const Standard_Real theV,
0761                                                          const Standard_Real theParam,
0762                                                          const gp_Pnt& thePntOnRst,
0763                                                          Standard_Real& NewU,
0764                                                          Standard_Real& NewV,
0765                                                          gp_Pnt& NewPoint,
0766                                                          Standard_Real& NewParam) const
0767 {
0768   const Standard_Real TolAng = 0.001; //bug OCC25701
0769   
0770   ChFiDS_ElSpine& theElSpine = *hguide;
0771   if (theElSpine.NbVertices() == 0)
0772     return Standard_False;
0773   
0774   Handle(TheTopolTool) DomainOfRst = (IndexOfRst == 1)? recdomain1 : recdomain2;
0775   TheSurface SurfOfRst = (IndexOfRst == 1)? surf1 : surf2;
0776   TheSurface AnotherSurf = (IndexOfRst == 1)? surf2 : surf1;
0777   
0778   //Correct point on surface 2
0779   //First we find right <param>
0780   Standard_Real Ends [2];
0781   Ends[0] = TheArcTool::FirstParameter(DomainOfRst->Value());
0782   Ends[1] = TheArcTool::LastParameter(DomainOfRst->Value());
0783   Standard_Real GlobalMinSqDist = Precision::Infinite();
0784   Standard_Real ParamOnGuide = 0;
0785   gp_Pnt PointOnGuide;
0786   for (Standard_Integer k = 0; k < 2; k++)
0787   {
0788     gp_Pnt2d P2dOnEnd = TheArcTool::Value(DomainOfRst->Value(), Ends[k]);
0789     gp_Pnt PntOnEnd = TheSurfaceTool::Value(SurfOfRst, P2dOnEnd.X(), P2dOnEnd.Y());
0790     Extrema_ExtPC projoncurv(PntOnEnd, theElSpine);
0791     if (!projoncurv.IsDone())
0792       continue;
0793     Standard_Real MinSqDist = Precision::Infinite();
0794     Standard_Integer imin = 0;
0795     for (Standard_Integer ind = 1; ind <= projoncurv.NbExt(); ind++)
0796     {
0797       Standard_Real aSqDist = projoncurv.SquareDistance(ind);
0798       if (aSqDist < MinSqDist)
0799       {
0800         MinSqDist = aSqDist;
0801         imin = ind;
0802       }
0803     }
0804     if (MinSqDist < GlobalMinSqDist)
0805     {
0806       GlobalMinSqDist = MinSqDist;
0807       ParamOnGuide = projoncurv.Point(imin).Parameter();
0808       PointOnGuide = projoncurv.Point(imin).Value();
0809     }
0810   }
0811   NewParam = ParamOnGuide;
0812   if (hguide->IsPeriodic())
0813   {
0814     Standard_Real Period = hguide->Period();
0815     Standard_Real sign = (NewParam < theParam)? 1 : -1;
0816     while (Abs(NewParam - theParam) > Period/2)
0817       NewParam += sign *Period;
0818   }
0819 
0820   //Second we find right point and tangent on guide
0821   GlobalMinSqDist = Precision::Infinite();
0822   gp_Ax1 theAx1;
0823   for (Standard_Integer ind = 1; ind <= theElSpine.NbVertices(); ind++)
0824   {
0825     const gp_Ax1& anAx1 = theElSpine.VertexWithTangent(ind);
0826     gp_Pnt aPnt = anAx1.Location();
0827     Standard_Real aSqDist = PointOnGuide.SquareDistance(aPnt);
0828     if (aSqDist < GlobalMinSqDist)
0829     {
0830       GlobalMinSqDist = aSqDist;
0831       theAx1 = anAx1;
0832     }
0833   }
0834   const gp_Pnt& Pnt0 = theAx1.Location();
0835   const gp_Dir& Dir0 = theAx1.Direction();
0836   //Check new point: is it real solution?
0837   gp_Pnt OldPonGuide = hguide->Value(theParam);
0838   gp_Pnt PntOnSurf2 = TheSurfaceTool::Value(AnotherSurf,theU,theV); //old point
0839   gce_MakePln PlaneBuilder(thePntOnRst, OldPonGuide, PntOnSurf2);
0840   if (!PlaneBuilder.IsDone())
0841     return Standard_False;
0842   gp_Pln OldPlane = PlaneBuilder.Value();
0843   gp_Dir OldDir = OldPlane.Axis().Direction();
0844   Standard_Real Angle = OldDir.Angle(Dir0);
0845   if (Angle > M_PI/2)
0846     Angle = M_PI - Angle;
0847   if (Angle > TolAng)
0848     return Standard_False;
0849   ///////////////////////////////////////
0850   //Project the point(theU,theV) on the plane(Pnt0,Dir0)
0851   gp_Vec aVec(Pnt0, PntOnSurf2);
0852   gp_Vec aTranslation( (aVec.XYZ() * Dir0.XYZ()) * Dir0.XYZ() );
0853   gp_Pnt PntOnPlane = PntOnSurf2.Translated(-aTranslation);
0854 
0855   //Check new point again: does point on restriction belong to the plane?
0856   PlaneBuilder = gce_MakePln(thePntOnRst, Pnt0, PntOnPlane);
0857   if (!PlaneBuilder.IsDone())
0858     return Standard_False;
0859   gp_Pln NewPlane = PlaneBuilder.Value();
0860   const gp_Dir& DirOfNewPlane = NewPlane.Axis().Direction();
0861   Angle = Dir0.Angle(DirOfNewPlane);
0862   if (Angle > M_PI/2)
0863     Angle = M_PI - Angle;
0864   if (Angle > TolAng)
0865     return Standard_False;
0866   ////////////////////////////////////////////////////////////////////////
0867   
0868   //Project the point <PntOnPlane> on the surface 2
0869   Extrema_ExtPS projonsurf(PntOnPlane, *AnotherSurf,
0870                            Precision::PConfusion(), Precision::PConfusion(),
0871                            Extrema_ExtFlag_MIN);
0872   if (projonsurf.IsDone())
0873   {
0874     Standard_Real MinSqDist = Precision::Infinite();
0875     Standard_Integer imin = 0;
0876     for (Standard_Integer ind = 1; ind <= projonsurf.NbExt(); ind++)
0877     {
0878       Standard_Real aSqDist = projonsurf.SquareDistance(ind);
0879       if (aSqDist < MinSqDist)
0880       {
0881         MinSqDist = aSqDist;
0882         imin = ind;
0883       }
0884     }
0885     if (imin)
0886     {
0887       Extrema_POnSurf NewPOnSurf2 = projonsurf.Point(imin);
0888       NewPoint = NewPOnSurf2.Value();
0889       NewPOnSurf2.Parameter(NewU, NewV);
0890       Standard_Real uperiod = (AnotherSurf->IsUPeriodic())? AnotherSurf->UPeriod() : 0.;
0891       Standard_Real vperiod = (AnotherSurf->IsVPeriodic())? AnotherSurf->VPeriod() : 0.;
0892       RecadreIfPeriodic(NewU, NewV, theU, theV,
0893                         uperiod, vperiod);
0894       return Standard_True;
0895     }
0896   }
0897 
0898   return Standard_False;
0899 }