Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/opencascade/Approx_ComputeLine.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 <Approx_ParametrizationType.hxx>
0016 #include <TColStd_Array1OfReal.hxx>
0017 #include <TColgp_Array1OfPnt.hxx>
0018 #include <TColgp_Array1OfPnt2d.hxx>
0019 #include <gp_Pnt.hxx>
0020 #include <gp_Pnt2d.hxx>
0021 #include <gp_Vec.hxx>
0022 #include <gp_Vec2d.hxx>
0023 #include <TColgp_Array1OfVec.hxx>
0024 #include <TColgp_Array1OfVec2d.hxx>
0025 #include <AppParCurves_Constraint.hxx>
0026 #include <AppParCurves_HArray1OfConstraintCouple.hxx>
0027 #include <AppParCurves_MultiPoint.hxx>
0028 #include <Precision.hxx>
0029 #include <math_IntegerVector.hxx>
0030 #include <math_Gauss.hxx>
0031 #include <math_Uzawa.hxx>
0032 #include <Approx_MCurvesToBSpCurve.hxx>
0033 #include <AppParCurves_ConstraintCouple.hxx>
0034 
0035 #include <stdio.h>
0036 
0037 #ifdef OCCT_DEBUG
0038 static Standard_Boolean mydebug = Standard_False;
0039 
0040 #include <Geom_BezierCurve.hxx>
0041 #include <Geom2d_BezierCurve.hxx>
0042 #ifdef DRAW
0043 #include <DrawTrSurf.hxx>
0044 #include <Draw.hxx>
0045 #include <Draw_Appli.hxx>
0046 #endif
0047 
0048 static void DUMP(const MultiLine& Line)
0049 {
0050   Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
0051   gp_Pnt P1;
0052   gp_Pnt2d P12d;
0053 
0054   firstP = LineTool::FirstPoint(Line);
0055   lastP  = LineTool::LastPoint(Line);
0056 
0057   nbP3d = LineTool::NbP3d(Line);
0058   nbP2d = LineTool::NbP2d(Line);
0059   Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0060   if (nbP3d == 0) mynbP3d = 1;
0061   if (nbP2d == 0) mynbP2d = 1;
0062   
0063   TColgp_Array1OfPnt tabP(1, mynbP3d);
0064   TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
0065   
0066   std::cout <<"DUMP de la MultiLine entre "<<firstP <<" et "<<lastP<<": "<<std::endl;
0067   for (i = firstP; i <= lastP; i++) {
0068     if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d);
0069     else if (nbP2d != 0)          LineTool::Value(Line, i, tabP2d);
0070     else if (nbP3d != 0)          LineTool::Value(Line, i, tabP);
0071     
0072     std::cout << "point "<<i<<":"<< std::endl;
0073     for (j = 1; j <= nbP3d; j++) {
0074       P1 = tabP(j);
0075       std::cout <<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<std::endl;
0076     }
0077     for (j = 1; j <= nbP2d; j++) {
0078       P12d = tabP2d(j);
0079       std::cout <<P12d.X()<<" "<<P12d.Y()<<std::endl;
0080     }
0081   }
0082 
0083 }
0084 
0085 static void DUMP(const AppParCurves_MultiCurve& C) {
0086   static Standard_Integer nbappel = 0;
0087   Standard_Integer i;
0088   Standard_Integer nbpoles = C.NbPoles();
0089 
0090   Handle(Geom_BezierCurve) BSp;
0091   Handle(Geom2d_BezierCurve) BSp2d;
0092 
0093   TColgp_Array1OfPnt tabPoles(1, nbpoles);
0094   TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
0095   char solname[100];
0096 
0097   nbappel++;
0098   for (i = 1; i <= C.NbCurves(); i++) {
0099     if (C.Dimension(i) == 3) {
0100       C.Curve(i, tabPoles);
0101       BSp = new Geom_BezierCurve(tabPoles);
0102       sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
0103 #ifdef DRAW
0104       char* Temp = solname;
0105       DrawTrSurf::Set(Temp, BSp);
0106 //      DrawTrSurf::Set(solname, BSp);
0107 #endif
0108     }
0109     else {
0110       C.Curve(i, tabPoles2d);
0111       BSp2d = new Geom2d_BezierCurve(tabPoles2d);
0112       sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
0113 #ifdef DRAW
0114       char* Temp = solname;
0115       DrawTrSurf::Set(Temp, BSp2d);
0116 //      DrawTrSurf::Set(solname, BSp2d);
0117 #endif
0118     }
0119   }
0120 #ifdef DRAW
0121   dout.Flush();
0122 #endif
0123 }
0124 
0125 #endif
0126 
0127 static Standard_Boolean CheckMultiCurve(const AppParCurves_MultiCurve& theMultiCurve,
0128                                         const MultiLine& theLine,
0129                                         const Standard_Integer theIndfirst,
0130                                         const Standard_Integer theIndlast,
0131                                         Standard_Integer& theIndbad)
0132 {
0133   const Standard_Integer nbp3d = LineTool::NbP3d(theLine);
0134   const Standard_Integer nbp2d = LineTool::NbP2d(theLine);
0135 
0136   const Standard_Real coeff = 4.; //2*2
0137   
0138   if (nbp3d > 1) //only simple cases are analysed
0139     return Standard_True;
0140 
0141   const Standard_Real MinScalProd = -0.9;
0142   const Standard_Real SqTol3d = Precision::SquareConfusion();
0143 
0144   theIndbad = 0;
0145   Standard_Integer indbads [4];
0146   indbads[1] = indbads[2] = indbads[3] = 0;
0147   
0148   Standard_Integer NbCur = theMultiCurve.NbCurves();
0149   Standard_Boolean LoopFound = Standard_False;
0150 
0151   Standard_Integer aNbP3d = Max(nbp3d, 1);
0152   Standard_Integer aNbP2d = Max(nbp2d, 1);
0153   
0154   TColgp_Array1OfPnt tabP(1, aNbP3d);
0155   TColgp_Array1OfPnt2d tabP2d(1, aNbP2d);
0156   
0157 #ifdef DRAW
0158   char* name = new char[100];
0159   Standard_Integer nbbc = 1;
0160   Standard_Integer indc = 1;
0161 #endif
0162   if (theMultiCurve.Dimension(1) == 3 /*myNbP3d == 1*/)
0163   {
0164     TColgp_Array1OfPnt aPoles(1, theMultiCurve.NbPoles());
0165     theMultiCurve.Curve(1, aPoles);
0166 #ifdef DRAW
0167     Handle(Geom_Curve) theBezier = new Geom_BezierCurve(aPoles);
0168     sprintf(name, "bc3d_%d_%d", indc, nbbc);
0169     DrawTrSurf::Set(name, theBezier);
0170 #endif
0171     gp_Vec FirstVec, SecondVec;
0172     Standard_Integer indp = 2;
0173     while (indp <= aPoles.Upper())
0174     {
0175       FirstVec = gp_Vec(aPoles(1), aPoles(indp++));
0176       Standard_Real aLength = FirstVec.Magnitude();
0177       if (aLength > gp::Resolution())
0178       {
0179         FirstVec /= aLength;
0180         break;
0181       }
0182     }
0183     gp_Pnt MidPnt = aPoles(indp-1);
0184     //for (Standard_Integer k = 3; k <= aPoles.Upper(); k++)
0185     while (indp <= aPoles.Upper())
0186     {
0187       SecondVec = gp_Vec(MidPnt, aPoles(indp));
0188       Standard_Real aLength = SecondVec.Magnitude();
0189       if (aLength <= gp::Resolution())
0190       {
0191         indp++;
0192         continue;
0193       }
0194       SecondVec /= aLength;
0195       Standard_Real ScalProd = FirstVec * SecondVec;
0196       if (ScalProd < MinScalProd)
0197       {
0198 #ifdef DRAW
0199         std::cout<<"ScalProd("<<indp-2<<","<<indp-1<<")-("<<indp-1<<","<<indp<<") = "<<ScalProd<<std::endl;
0200 #endif
0201         LoopFound = Standard_True;
0202         break;
0203       }
0204       FirstVec = SecondVec;
0205       MidPnt = aPoles(indp);
0206       indp++;
0207     }
0208     //Check: may be it is a real loop
0209     if (LoopFound)
0210     {
0211 #ifdef DRAW
0212       for (Standard_Integer ipoint = theIndfirst; ipoint <= theIndlast; ipoint++)
0213       {
0214         LineTool::Value(theLine, ipoint, tabP);
0215         gp_Pnt aPnt = tabP(1);
0216         sprintf(name, "p%d", ipoint);
0217         DrawTrSurf::Set(name, aPnt);
0218       }
0219 #endif
0220       for (Standard_Integer FirstInd = theIndfirst;
0221            FirstInd <= theIndlast - 2; FirstInd++)
0222       {
0223         LineTool::Value(theLine, FirstInd, tabP);
0224         gp_Pnt FirstPnt = tabP(1);
0225         for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
0226         {
0227           LineTool::Value(theLine, k, tabP);
0228           gp_Pnt Pnt1 = tabP(1);
0229           LineTool::Value(theLine, k+1, tabP);
0230           gp_Pnt Pnt2 = tabP(1);
0231           if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
0232               FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
0233           {
0234             LoopFound = Standard_False;
0235             break;
0236           }
0237           gp_Vec Vec1(FirstPnt, Pnt1);
0238           Vec1.Normalize();
0239           gp_Vec Vec2(FirstPnt, Pnt2);
0240           Vec2.Normalize();
0241           Standard_Real ScalProd = Vec1 * Vec2;
0242           if (ScalProd < MinScalProd)
0243           {
0244             LoopFound = Standard_False;
0245             break;
0246           }
0247         }
0248         if (LoopFound == Standard_False)
0249           break;
0250       }
0251     }
0252     if (LoopFound)
0253     {
0254       //search <indbad>
0255       Standard_Real MaxSqDist = 0.;
0256       Standard_Real MinSqDist = RealLast();
0257       for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
0258       {
0259         LineTool::Value(theLine, k-1, tabP);
0260         gp_Pnt PrevPnt = tabP(1);
0261         LineTool::Value(theLine, k, tabP);
0262         gp_Pnt CurPnt  = tabP(1);
0263         Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
0264         if (aSqDist > MaxSqDist)
0265         {
0266           MaxSqDist = aSqDist;
0267           indbads[1] = k;
0268         }
0269         if (aSqDist > gp::Resolution() &&
0270             aSqDist < MinSqDist)
0271           MinSqDist = aSqDist;
0272       }
0273       Standard_Real Relation = MaxSqDist / MinSqDist;
0274       if (Relation < coeff)
0275         LoopFound = Standard_False;
0276       else
0277         for (Standard_Integer indcur = 2; indcur <= NbCur; indcur++)
0278         {
0279           MaxSqDist = 0.;
0280           for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
0281           {
0282             LineTool::Value(theLine, k-1, tabP2d);
0283             gp_Pnt2d PrevPnt = tabP2d(indcur-1);
0284             LineTool::Value(theLine, k, tabP2d);
0285             gp_Pnt2d CurPnt  = tabP2d(indcur-1);
0286             Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
0287             if (aSqDist > MaxSqDist)
0288             {
0289               MaxSqDist = aSqDist;
0290               indbads[indcur] = k;
0291             }
0292           }
0293         }
0294     }
0295   } //if (myNbP3d == 1)
0296   else //2d case
0297   {
0298     TColgp_Array1OfPnt2d aPoles2d(1, theMultiCurve.NbPoles());
0299     theMultiCurve.Curve(1, aPoles2d);
0300 #ifdef DRAW
0301     Handle(Geom2d_Curve) theBezier2d = new Geom2d_BezierCurve(aPoles2d);
0302     sprintf(name, "bc2d_%d_%d", indc, nbbc);
0303     DrawTrSurf::Set(name, theBezier2d);
0304 #endif
0305     const Standard_Real aSqNormToler = Epsilon(1.0)*Epsilon(1.0);
0306     gp_Vec2d FirstVec(aPoles2d(1), aPoles2d(2)), SecondVec;
0307     Standard_Real aVecSqNorm = FirstVec.SquareMagnitude();
0308     if (aVecSqNorm < aSqNormToler)
0309     {
0310       theIndbad = theIndfirst + 1;
0311       return Standard_False;
0312     }
0313 
0314     FirstVec /= Sqrt(aSqNormToler);
0315     gp_Pnt2d MidPnt = aPoles2d(2);
0316     for (Standard_Integer k = 3; k <= aPoles2d.Upper(); k++)
0317     {
0318       SecondVec.SetXY(aPoles2d(k).XY() - MidPnt.XY());
0319       aVecSqNorm = SecondVec.SquareMagnitude();
0320       if (aVecSqNorm < aSqNormToler)
0321       {
0322         theIndbad = theIndfirst + k - 1;
0323         return Standard_False;
0324       }
0325 
0326       SecondVec /= Sqrt(aVecSqNorm);
0327       Standard_Real ScalProd = FirstVec * SecondVec;
0328       if (ScalProd < MinScalProd)
0329       {
0330 #ifdef DRAW
0331         std::cout<<"ScalProd("<<k-2<<","<<k-1<<")-("<<k-1<<","<<k<<") = "<<ScalProd<<std::endl;
0332 #endif
0333         LoopFound = Standard_True;
0334         break;
0335       }
0336       FirstVec = SecondVec;
0337       MidPnt = aPoles2d(k);
0338     }
0339     //Check: may be it is a real loop
0340     if (LoopFound)
0341     {
0342 #ifdef DRAW
0343       for (Standard_Integer ipoint = theIndfirst; ipoint <= theIndlast; ipoint++)
0344       {
0345         LineTool::Value(theLine, ipoint, tabP2d);
0346         gp_Pnt2d aPnt2d = tabP2d(1);
0347         sprintf(name, "p%d", ipoint);
0348         DrawTrSurf::Set(name, aPnt2d);
0349       }
0350 #endif
0351       for (Standard_Integer FirstInd = theIndfirst;
0352            FirstInd <= theIndlast - 2; FirstInd++)
0353       {
0354         LineTool::Value(theLine, FirstInd, tabP2d);
0355         gp_Pnt2d FirstPnt = tabP2d(1);
0356         for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
0357         {
0358           LineTool::Value(theLine, k, tabP2d);
0359           gp_Pnt2d Pnt1 = tabP2d(1);
0360           LineTool::Value(theLine, k+1, tabP2d);
0361           gp_Pnt2d Pnt2 = tabP2d(1);
0362           if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
0363               FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
0364           {
0365             LoopFound = Standard_False;
0366             break;
0367           }
0368           gp_Vec2d Vec1(FirstPnt, Pnt1);
0369           Vec1.Normalize();
0370           gp_Vec2d Vec2(FirstPnt, Pnt2);
0371           Vec2.Normalize();
0372           Standard_Real ScalProd = Vec1 * Vec2;
0373           if (ScalProd < MinScalProd)
0374           {
0375             LoopFound = Standard_False;
0376             break;
0377           }
0378         }
0379         if (LoopFound == Standard_False)
0380           break;
0381       }
0382     }
0383     if (LoopFound)
0384     {
0385       //search <indbad>
0386       for (Standard_Integer indcur = 1; indcur <= NbCur; indcur++)
0387       {
0388         Standard_Real MaxSqDist = 0.;
0389         Standard_Real MinSqDist = RealLast();
0390         for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
0391         {
0392           LineTool::Value(theLine, k-1, tabP2d);
0393           gp_Pnt2d PrevPnt = tabP2d(indcur);
0394           LineTool::Value(theLine, k, tabP2d);
0395           gp_Pnt2d CurPnt  = tabP2d(indcur);
0396           Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
0397           if (aSqDist > MaxSqDist)
0398           {
0399             MaxSqDist = aSqDist;
0400             indbads[indcur] = k;
0401           }
0402           if (aSqDist > gp::Resolution() &&
0403               aSqDist < MinSqDist)
0404             MinSqDist = aSqDist;
0405         }
0406         Standard_Real Relation = MaxSqDist / MinSqDist;
0407         if (Relation < coeff)
0408           LoopFound = Standard_False;
0409       }
0410     }
0411   }
0412 
0413   //Define <indbad>
0414   for (Standard_Integer i = 1; i <= 3; i++)
0415     if (indbads[i] != 0)
0416     {
0417       theIndbad = indbads[i];
0418       break;
0419     }
0420 
0421   if (!LoopFound)
0422     theIndbad = 0;
0423   
0424   return (!LoopFound);
0425 }
0426 
0427 void Approx_ComputeLine::FirstTangencyVector(const MultiLine&       Line,
0428                                              const Standard_Integer index,
0429                                              math_Vector&           V) const 
0430 {
0431 
0432   Standard_Integer i, j, nbP2d, nbP3d;
0433   nbP3d = LineTool::NbP3d(Line);
0434   nbP2d = LineTool::NbP2d(Line);
0435   Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0436   if (nbP3d == 0) mynbP3d = 1;
0437   if (nbP2d == 0) mynbP2d = 1;
0438   Standard_Boolean Ok=Standard_False;
0439   TColgp_Array1OfVec TabV(1, mynbP3d);
0440   TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
0441  
0442   if (nbP3d != 0 && nbP2d != 0)
0443     Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
0444   else if (nbP2d != 0)
0445     Ok = LineTool::Tangency(Line, index, TabV2d);
0446   else if (nbP3d != 0)
0447     Ok = LineTool::Tangency(Line, index, TabV);
0448 
0449   if (Ok) {
0450     if (nbP3d != 0) {
0451       j = 1;
0452       for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
0453         V(j)   = TabV(i).X();
0454         V(j+1) = TabV(i).Y();
0455         V(j+2) = TabV(i).Z();
0456         j += 3;
0457       }
0458     }
0459     if (nbP2d != 0) {
0460       j = nbP3d*3+1;
0461       for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
0462         V(j)   = TabV2d(i).X();
0463         V(j+1) = TabV2d(i).Y();
0464         j += 2;
0465       }
0466     }
0467   }
0468   else {
0469 
0470     // recherche d un vecteur tangent par construction d une parabole:
0471     AppParCurves_Constraint firstC, lastC;
0472     firstC = lastC = AppParCurves_PassPoint;
0473     Standard_Integer nbpoles = 3;
0474     math_Vector mypar(index, index+2);
0475     Parameters(Line, index, index+2, mypar);
0476     Approx_ParLeastSquareOfMyGradient 
0477       LSQ(Line, index, index+2, firstC, lastC, mypar, nbpoles);
0478     AppParCurves_MultiCurve C = LSQ.BezierValue();
0479     
0480     gp_Pnt myP;
0481     gp_Vec myV;
0482     gp_Pnt2d myP2d;
0483     gp_Vec2d myV2d;
0484     j = 1;
0485     for (i = 1; i <= nbP3d; i++) {
0486       C.D1(i, 0.0, myP, myV);
0487       V(j)   = myV.X();
0488       V(j+1) = myV.Y();
0489       V(j+2) = myV.Z();
0490       j += 3;
0491     }
0492     j = nbP3d*3+1;
0493     for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
0494       C.D1(i, 0.0, myP2d, myV2d);
0495       V(j)   = myV2d.X();
0496       V(j+1) = myV2d.Y();
0497       j += 2;
0498     }
0499   }
0500 }
0501 
0502 
0503 void Approx_ComputeLine::LastTangencyVector(const MultiLine&       Line,
0504                                             const Standard_Integer index,
0505                                             math_Vector&           V) const
0506 {
0507   Standard_Integer i, j, nbP2d, nbP3d;
0508   nbP3d = LineTool::NbP3d(Line);
0509   nbP2d = LineTool::NbP2d(Line);
0510   Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0511   if (nbP3d == 0) mynbP3d = 1;
0512   if (nbP2d == 0) mynbP2d = 1;
0513   Standard_Boolean Ok=Standard_False;
0514   TColgp_Array1OfVec TabV(1, mynbP3d);
0515   TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
0516 
0517  
0518   if (nbP3d != 0 && nbP2d != 0)
0519     Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
0520   else if (nbP2d != 0)
0521     Ok = LineTool::Tangency(Line, index, TabV2d);
0522   else if (nbP3d != 0)
0523     Ok = LineTool::Tangency(Line, index, TabV);
0524 
0525   if (Ok) {
0526     if (nbP3d != 0) {
0527       j = 1;
0528       for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
0529         V(j)   = TabV(i).X();
0530         V(j+1) = TabV(i).Y();
0531         V(j+2) = TabV(i).Z();
0532         j += 3;
0533       }
0534     }
0535     if (nbP2d != 0) {
0536       j = nbP3d*3+1;
0537       for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
0538         V(j)   = TabV2d(i).X();
0539         V(j+1) = TabV2d(i).Y();
0540         j += 2;
0541       }
0542     }
0543   }
0544   else {
0545 
0546     // recherche d un vecteur tangent par construction d une parabole:
0547     AppParCurves_Constraint firstC, lastC;
0548     firstC = lastC = AppParCurves_PassPoint;
0549     Standard_Integer nbpoles = 3;
0550     math_Vector mypar(index-2, index);
0551     Parameters(Line, index-2, index, mypar);
0552     Approx_ParLeastSquareOfMyGradient 
0553       LSQ(Line, index-2, index, firstC, lastC, mypar, nbpoles);
0554     AppParCurves_MultiCurve C = LSQ.BezierValue();
0555     
0556     gp_Pnt myP;
0557     gp_Vec myV;
0558     gp_Pnt2d myP2d;
0559     gp_Vec2d myV2d;
0560     j = 1;
0561     for (i = 1; i <= nbP3d; i++) {
0562       C.D1(i, 1.0, myP, myV);
0563       V(j)   = myV.X();
0564       V(j+1) = myV.Y();
0565       V(j+2) = myV.Z();
0566       j += 3;
0567     }
0568     j = nbP3d*3+1;
0569     for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
0570       C.D1(i, 1.0, myP2d, myV2d);
0571       V(j)   = myV2d.X();
0572       V(j+1) = myV2d.Y();
0573       j += 2;
0574     }
0575   }
0576 
0577 }
0578 
0579 
0580 
0581 Standard_Real Approx_ComputeLine::
0582   SearchFirstLambda(const MultiLine&            Line, 
0583                     const math_Vector&          TheParam,
0584                     const math_Vector&          V,
0585                     const Standard_Integer      index) const 
0586 {
0587 
0588   // dq/dw = lambda* V = (p2-p1)/(u2-u1)
0589   
0590   Standard_Integer nbP2d, nbP3d;
0591   gp_Pnt P1, P2;
0592   gp_Pnt2d P12d, P22d;
0593   nbP3d = LineTool::NbP3d(Line);
0594   nbP2d = LineTool::NbP2d(Line);
0595   Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0596   if (nbP3d == 0) mynbP3d = 1;
0597   if (nbP2d == 0) mynbP2d = 1;
0598   TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
0599   TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
0600  
0601 
0602   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
0603   else if (nbP2d != 0)          LineTool::Value(Line, index, tabP12d);
0604   else if (nbP3d != 0)          LineTool::Value(Line, index, tabP1);
0605 
0606   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index+1, tabP2, tabP22d);
0607   else if (nbP2d != 0)          LineTool::Value(Line, index+1, tabP22d);
0608   else if (nbP3d != 0)          LineTool::Value(Line, index+1, tabP2);
0609                                      
0610 
0611   Standard_Real U1 = TheParam(index), U2 = TheParam(index+1);
0612   Standard_Real lambda, S;                                        
0613   Standard_Integer low = V.Lower();
0614  
0615   if (nbP3d != 0) {
0616     P1 = tabP1(1);
0617     P2 = tabP2(1);
0618     gp_Vec P1P2(P1, P2), myV;
0619     myV.SetCoord(V(low), V(low+1), V(low+2));
0620     lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0621     S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0622   }
0623   else {
0624     P12d = tabP12d(1);
0625     P22d = tabP22d(1);
0626     gp_Vec2d P1P2(P12d, P22d), myV;
0627     myV.SetCoord(V(low), V(low+1));
0628     lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0629     S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0630   }
0631   return (S*lambda);
0632 
0633 }
0634 
0635 
0636 Standard_Real Approx_ComputeLine::
0637  SearchLastLambda(const MultiLine&            Line, 
0638                   const math_Vector&          TheParam,
0639                   const math_Vector&          V,
0640                   const Standard_Integer      index) const
0641 {
0642   // dq/dw = lambda* V = (p2-p1)/(u2-u1)
0643   
0644   Standard_Integer nbP2d, nbP3d;
0645   gp_Pnt P1, P2;
0646   gp_Pnt2d P12d, P22d;
0647   nbP3d = LineTool::NbP3d(Line);
0648   nbP2d = LineTool::NbP2d(Line);
0649   Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0650   if (nbP3d == 0) mynbP3d = 1;
0651   if (nbP2d == 0) mynbP2d = 1;
0652   TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
0653   TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
0654  
0655   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index-1, tabP, tabP2d);
0656   else if (nbP2d != 0)          LineTool::Value(Line, index-1, tabP2d);
0657   else if (nbP3d != 0)          LineTool::Value(Line, index-1, tabP);
0658 
0659   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
0660   else if (nbP2d != 0)          LineTool::Value(Line, index, tabP22d);
0661   else if (nbP3d != 0)          LineTool::Value(Line, index, tabP2);
0662 
0663 
0664   Standard_Real U1 = TheParam(index-1), U2 = TheParam(index);
0665   Standard_Real lambda, S;
0666   Standard_Integer low = V.Lower();
0667 
0668   if (nbP3d != 0) {
0669     P1 = tabP(1);
0670     P2 = tabP2(1);
0671     gp_Vec P1P2(P1, P2), myV;
0672     myV.SetCoord(V(low), V(low+1), V(low+2));
0673     lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0674     S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0675   }
0676   else {
0677     P12d = tabP2d(1);
0678     P22d = tabP22d(1);
0679     gp_Vec2d P1P2(P12d, P22d), myV;
0680     myV.SetCoord(V(low), V(low+1));
0681     lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
0682     S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
0683   }
0684 
0685   return (S*lambda);
0686 }
0687 
0688 
0689 
0690 Approx_ComputeLine::Approx_ComputeLine
0691                     (const MultiLine& Line,
0692                      const math_Vector& Parameters,
0693                      const Standard_Integer degreemin,
0694                      const Standard_Integer degreemax,
0695                      const Standard_Real Tolerance3d,
0696                      const Standard_Real Tolerance2d,
0697                      const Standard_Integer NbIterations,
0698                      const Standard_Boolean cutting,
0699                      const Standard_Boolean Squares)
0700 : myMultiLineNb (0),
0701   myIsClear (Standard_False)
0702 {
0703   myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(), 
0704                                            Parameters.Upper());
0705   for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
0706     myfirstParam->SetValue(i, Parameters(i));
0707   }
0708   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0709   Par = Approx_IsoParametric;
0710   mydegremin = degreemin;
0711   mydegremax = degreemax;
0712   mytol3d = Tolerance3d;
0713   mytol2d = Tolerance2d;
0714   mysquares = Squares;
0715   mycut = cutting;
0716   myitermax = NbIterations;
0717   alldone = Standard_False;
0718   myfirstC = AppParCurves_TangencyPoint;
0719   mylastC = AppParCurves_TangencyPoint;
0720   Perform(Line);
0721 }
0722 
0723 
0724 Approx_ComputeLine::Approx_ComputeLine
0725                     (const math_Vector& Parameters,
0726                      const Standard_Integer degreemin,
0727                      const Standard_Integer degreemax,
0728                      const Standard_Real Tolerance3d,
0729                      const Standard_Real Tolerance2d,
0730                      const Standard_Integer NbIterations,
0731                      const Standard_Boolean cutting,
0732                      const Standard_Boolean Squares)
0733 : myMultiLineNb (0),
0734   myIsClear (Standard_False)
0735 {
0736   myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(), 
0737                                            Parameters.Upper());
0738   for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
0739     myfirstParam->SetValue(i, Parameters(i));
0740   }
0741   myfirstC = AppParCurves_TangencyPoint;
0742   mylastC = AppParCurves_TangencyPoint;
0743   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0744   Par = Approx_IsoParametric;
0745   mydegremin = degreemin;
0746   mydegremax = degreemax;
0747   mytol3d = Tolerance3d;
0748   mytol2d = Tolerance2d;
0749   mysquares = Squares;
0750   mycut = cutting;
0751   myitermax = NbIterations;
0752   alldone = Standard_False;
0753 }
0754 
0755 Approx_ComputeLine::Approx_ComputeLine
0756                     (const Standard_Integer degreemin,
0757                      const Standard_Integer degreemax,
0758                      const Standard_Real Tolerance3d,
0759                      const Standard_Real Tolerance2d,
0760                      const Standard_Integer NbIterations,
0761                      const Standard_Boolean cutting,
0762                      const Approx_ParametrizationType parametrization,
0763                      const Standard_Boolean Squares)
0764 : myMultiLineNb (0),
0765   myIsClear (Standard_False)
0766 {
0767   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0768   Par = parametrization;
0769   mydegremin = degreemin;
0770   mydegremax = degreemax;
0771   mytol3d = Tolerance3d;
0772   mytol2d = Tolerance2d;
0773   mysquares = Squares;
0774   mycut = cutting;
0775   myitermax = NbIterations;
0776   myfirstC = AppParCurves_TangencyPoint;
0777   mylastC = AppParCurves_TangencyPoint;
0778   alldone = Standard_False;
0779 }
0780 
0781 
0782 Approx_ComputeLine::Approx_ComputeLine
0783                     (const MultiLine& Line,
0784                      const Standard_Integer degreemin,
0785                      const Standard_Integer degreemax,
0786                      const Standard_Real Tolerance3d,
0787                      const Standard_Real Tolerance2d,
0788                      const Standard_Integer NbIterations,
0789                      const Standard_Boolean cutting,
0790                      const Approx_ParametrizationType parametrization,
0791                      const Standard_Boolean Squares)
0792 : myMultiLineNb (0),
0793   myIsClear (Standard_False)
0794 {
0795   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
0796   alldone = Standard_False;
0797   mydegremin = degreemin;
0798   mydegremax = degreemax;
0799   mytol3d = Tolerance3d;
0800   mytol2d = Tolerance2d;
0801   mysquares = Squares;
0802   mycut = cutting;
0803   myitermax = NbIterations;
0804   Par = parametrization;
0805   myfirstC = AppParCurves_TangencyPoint;
0806   mylastC = AppParCurves_TangencyPoint;
0807 
0808   Perform(Line);
0809 }
0810 
0811 
0812 
0813 void Approx_ComputeLine::Perform(const MultiLine& Line)
0814 {
0815 #ifdef OCCT_DEBUG
0816   if (mydebug) DUMP(Line);
0817 #endif
0818   if (!myIsClear)
0819   {
0820     myMultiCurves.Clear();
0821     myPar.Clear();
0822     Tolers3d.Clear();
0823     Tolers2d.Clear();
0824     myMultiLineNb = 0;
0825   }
0826   else myIsClear = Standard_False;
0827 
0828   Standard_Integer i, nbp, Thefirstpt, Thelastpt, oldlastpt;
0829   Standard_Boolean Finish = Standard_False,
0830           begin = Standard_True, Ok = Standard_False, 
0831           GoUp = Standard_False, Interpol;
0832   Standard_Real thetol3d, thetol2d;
0833   Approx_Status MyStatus;
0834 //  gp_Vec V13d, V23d;
0835 //  gp_Vec2d V2d;
0836   Thefirstpt = LineTool::FirstPoint(Line);
0837   Thelastpt  = LineTool::LastPoint(Line);
0838   Standard_Integer myfirstpt = Thefirstpt; 
0839   Standard_Integer mylastpt = Thelastpt;
0840 
0841   AppParCurves_ConstraintCouple myCouple1(myfirstpt, myfirstC);
0842   AppParCurves_ConstraintCouple myCouple2(mylastpt, mylastC);
0843   myConstraints->SetValue(1, myCouple1);
0844   myConstraints->SetValue(2, myCouple2);
0845 
0846   math_Vector TheParam(Thefirstpt, Thelastpt);
0847 
0848 
0849   if (!mycut) {
0850     if(myfirstParam.IsNull()) {
0851       Parameters(Line, Thefirstpt, Thelastpt, TheParam);
0852     }
0853     else {
0854       for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
0855         TheParam(i+Thefirstpt-1) = myfirstParam->Value(i);
0856       }
0857     }
0858     TheMultiCurve = AppParCurves_MultiCurve();
0859     MultiLine anOtherLine0;
0860     Standard_Boolean isOtherLine0Made = Standard_False;
0861     Standard_Integer indbad = 0;
0862     alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d, indbad);
0863     if (indbad != 0)
0864     {
0865       isOtherLine0Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine0);
0866     }
0867     if (isOtherLine0Made)
0868     {
0869       myIsClear = Standard_True;
0870       //++myMultiLineNb;
0871       Perform(anOtherLine0);
0872       alldone = Standard_True;
0873     }
0874     if(!alldone && TheMultiCurve.NbCurves() > 0) {
0875 #ifdef OCCT_DEBUG
0876       if (mydebug) DUMP(TheMultiCurve);
0877 #endif
0878       myMultiCurves.Append(TheMultiCurve);
0879       Tolers3d.Append(currenttol3d);
0880       Tolers2d.Append(currenttol2d);
0881       Standard_Integer mylen = mylastpt-myfirstpt+1;
0882       Standard_Integer myParLen = myParameters->Length();
0883       Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
0884       Handle(TColStd_HArray1OfReal) ThePar =
0885         new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
0886       for (i = 0; i < aLen; i++)
0887         ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
0888       myPar.Append(ThePar);
0889     }
0890   }
0891   else {
0892     while (!Finish) {
0893       oldlastpt = mylastpt;
0894       // Gestion du decoupage de la multiline pour approximer:
0895       if(!begin) {
0896         if (!GoUp) {
0897           if (Ok) {
0898             // Calcul de la partie a approximer.
0899             myfirstpt = mylastpt;
0900             mylastpt  = Thelastpt;
0901             if (myfirstpt == Thelastpt) {
0902               Finish = Standard_True;
0903               alldone = Standard_True;
0904               return;
0905             }
0906           }
0907           else {
0908             nbp = mylastpt - myfirstpt + 1;
0909             MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
0910             if (MyStatus == Approx_NoPointsAdded && nbp <= mydegremax+1) {
0911               Interpol = ComputeCurve(Line, myfirstpt, mylastpt);
0912               if (Interpol) {
0913                 if (mylastpt == Thelastpt) {
0914                   Finish = Standard_True;
0915                   alldone = Standard_True;
0916                   return;
0917                 }
0918               }
0919             }
0920             mylastpt = Standard_Integer((myfirstpt + mylastpt)/2);
0921           }
0922         }
0923         GoUp = Standard_False;
0924       }
0925       
0926       // Verification du nombre de points restants par rapport au degre
0927       // demande.
0928       // ==============================================================
0929       nbp = mylastpt - myfirstpt + 1;
0930       MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
0931       if (nbp <= mydegremax+5 ) {
0932         // Rajout necessaire de points si possible.
0933         // ========================================
0934         GoUp = Standard_False;
0935         Ok = Standard_True;
0936         if (MyStatus == Approx_PointsAdded) {
0937           // Appel recursif du decoupage:
0938           GoUp = Standard_True;
0939 
0940           MultiLine anOtherLine1 = LineTool::MakeMLBetween(Line, myfirstpt, mylastpt, nbp-1);
0941           
0942           Standard_Integer nbpdsotherligne = LineTool::FirstPoint (anOtherLine1) - LineTool::LastPoint (anOtherLine1);
0943 
0944           //-- Si MakeML a echoue   on retourne une ligne vide
0945           if ((nbpdsotherligne == 0) || myMultiLineNb >= 3)
0946           {
0947             //-- cout<<" ** ApproxComputeLine MakeML Echec ** LBR lbr "<<endl;
0948             if (myfirstpt == mylastpt) break;  // Pour etre sur de ne pas 
0949             // planter la station !!
0950             myCouple1.SetIndex(myfirstpt);
0951             myCouple2.SetIndex(mylastpt);
0952             myConstraints->SetValue(1, myCouple1);
0953             myConstraints->SetValue(2, myCouple2);
0954 
0955             math_Vector Param(myfirstpt, mylastpt);
0956             Approx_ParametrizationType SavePar = Par;
0957             Par = Approx_IsoParametric;
0958             Parameters(Line, myfirstpt, mylastpt, Param);
0959             TheMultiCurve = AppParCurves_MultiCurve();
0960             MultiLine anOtherLine2;
0961             Standard_Boolean isOtherLine2Made = Standard_False;
0962             Standard_Integer indbad = 0;
0963             Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
0964             if (indbad != 0)
0965             {
0966               isOtherLine2Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine2);
0967             }
0968             if (isOtherLine2Made)
0969             {
0970               myIsClear = Standard_True;
0971               //++myMultiLineNb;
0972               Par = SavePar;
0973               Perform(anOtherLine2);
0974               Ok = Standard_True;
0975             }
0976 
0977             if (!Ok) {
0978               Standard_Real tt3d = currenttol3d, tt2d = currenttol2d;
0979               Handle(TColStd_HArray1OfReal) saveParameters = myParameters;
0980               AppParCurves_MultiCurve saveMultiCurve = TheMultiCurve;
0981 
0982               if(SavePar != Approx_IsoParametric)
0983                 Par = SavePar;
0984               else
0985                 Par = Approx_ChordLength;
0986 
0987               Parameters(Line, myfirstpt, mylastpt, Param);
0988         isOtherLine2Made = Standard_False;
0989               indbad = 0;
0990               Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
0991               if (indbad != 0)
0992               {
0993                 isOtherLine2Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad, anOtherLine2);
0994               }
0995               if (isOtherLine2Made)
0996               {
0997                 myIsClear = Standard_True;
0998                 //++myMultiLineNb;
0999                 Perform (anOtherLine2);
1000                 Ok = Standard_True;
1001               }
1002               
1003               if (!Ok && tt3d <= currenttol3d && tt2d <= currenttol2d) {
1004                 currenttol3d = tt3d; currenttol2d = tt2d;
1005                 myParameters = saveParameters;
1006                 TheMultiCurve = saveMultiCurve;
1007               }
1008             }
1009             Par = SavePar;
1010             if (myfirstpt == Thelastpt)
1011             {
1012               Finish = Standard_True;
1013               alldone = Standard_True;
1014               return;
1015             }
1016 
1017             oldlastpt = mylastpt;
1018             if (!Ok) {
1019               tolreached = Standard_False;
1020               if (TheMultiCurve.NbCurves() == 0) {
1021                 myMultiCurves.Clear();
1022                 return;
1023               }
1024 #ifdef OCCT_DEBUG
1025               if (mydebug) DUMP(TheMultiCurve);
1026 #endif
1027               MultiLine anOtherLine3;
1028               Standard_Boolean isOtherLine3Made = Standard_False;
1029               Standard_Integer indbad2 = 0;
1030               if (!CheckMultiCurve(TheMultiCurve, Line,
1031                                    myfirstpt, mylastpt,
1032                                    indbad2))
1033               {
1034                 isOtherLine3Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad2, anOtherLine3);
1035               }
1036               if (isOtherLine3Made)
1037               {
1038                 myIsClear = Standard_True;
1039                 //++myMultiLineNb;
1040                 Perform(anOtherLine3);
1041                 myfirstpt = mylastpt;
1042                 mylastpt = Thelastpt;
1043               }
1044               else
1045               {
1046                 myMultiCurves.Append(TheMultiCurve);
1047                 Tolers3d.Append(currenttol3d);
1048                 Tolers2d.Append(currenttol2d);
1049                 Standard_Integer mylen = oldlastpt-myfirstpt+1;
1050                 Standard_Integer myParLen = myParameters->Length();
1051                 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
1052                 Handle(TColStd_HArray1OfReal) ThePar =
1053                   new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
1054                 for (i = 0; i < aLen; i++)
1055                   ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
1056                 myPar.Append(ThePar);
1057               }
1058             } 
1059             myfirstpt = oldlastpt;
1060             mylastpt = Thelastpt;
1061             
1062           }
1063           else
1064           {
1065             myIsClear = Standard_True;
1066             ++myMultiLineNb;
1067             Perform(anOtherLine1);
1068             myfirstpt = mylastpt;
1069             mylastpt = Thelastpt;
1070           }
1071         }
1072         
1073         if  (MyStatus == Approx_NoPointsAdded && !begin) {
1074           // On rend la meilleure approximation obtenue precedemment.
1075           // ========================================================
1076           GoUp = Standard_True;
1077           tolreached = Standard_False;
1078           if (TheMultiCurve.NbCurves() == 0) {
1079             myMultiCurves.Clear();
1080             return;
1081           }
1082 #ifdef OCCT_DEBUG
1083       if (mydebug) DUMP(TheMultiCurve);
1084 #endif
1085           myMultiCurves.Append(TheMultiCurve);
1086           Tolers3d.Append(currenttol3d);
1087           Tolers2d.Append(currenttol2d);
1088           Standard_Integer mylen = oldlastpt-myfirstpt+1;
1089           Standard_Integer myParLen = myParameters->Length();
1090           Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
1091           Handle(TColStd_HArray1OfReal) ThePar =
1092             new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
1093           for (i = 0; i < aLen; i++)
1094             ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
1095           myPar.Append(ThePar);
1096 
1097           myfirstpt = oldlastpt;
1098           mylastpt = Thelastpt;
1099         }
1100         
1101         else if (MyStatus == Approx_NoApproximation) {
1102           // On ne fait pas d approximation entre myfirstpt et mylastpt.
1103           // ===========================================================
1104           // On stocke pour pouvoir en informer l utilisateur.
1105           GoUp = Standard_True;
1106           myfirstpt = mylastpt;
1107           mylastpt = Thelastpt;
1108         }
1109       }
1110       
1111       if (myfirstpt == Thelastpt) {
1112         Finish = Standard_True;
1113         alldone = Standard_True;
1114         return;
1115       }
1116       if (!GoUp) {
1117         if (myfirstpt == mylastpt) break;  // Pour etre sur de ne pas 
1118                                            // planter la station !!
1119         myCouple1.SetIndex(myfirstpt);
1120         myCouple2.SetIndex(mylastpt);
1121         myConstraints->SetValue(1, myCouple1);
1122         myConstraints->SetValue(2, myCouple2);
1123         
1124         // Calcul des parametres sur ce nouvel intervalle.
1125         // On recupere les parametres initiaux lors du decoupage.
1126 
1127         math_Vector Param(myfirstpt, mylastpt);
1128         if (begin) {
1129           if(myfirstParam.IsNull()) {
1130             Parameters(Line, myfirstpt, mylastpt, Param);
1131           }
1132           else {
1133             for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
1134               Param(i) = myfirstParam->Value(i);
1135             }
1136             myfirstParam.Nullify();
1137           }
1138           TheParam = Param;
1139           begin = Standard_False;
1140         }
1141         else {
1142           Standard_Real pfirst = TheParam.Value(myfirstpt);
1143           Standard_Real plast = TheParam.Value(mylastpt);
1144           for (i = myfirstpt; i <= mylastpt; i++) {
1145             Param(i) = (TheParam.Value(i)-pfirst)/(plast-pfirst);
1146           }
1147         }
1148 
1149         TheMultiCurve = AppParCurves_MultiCurve();
1150         Standard_Integer indbad = 0;
1151         Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
1152         if (myfirstpt == Thelastpt)
1153         {
1154           Finish = Standard_True;
1155           alldone = Standard_True;
1156           return;
1157         }
1158       }
1159     }
1160   }
1161 }
1162 
1163 
1164 
1165 const TColStd_Array1OfReal& Approx_ComputeLine::Parameters(const Standard_Integer Index) const
1166 {
1167   return (myPar.Value(Index))->Array1();
1168 }
1169 
1170 
1171 Standard_Integer Approx_ComputeLine::NbMultiCurves()const
1172 {
1173   return myMultiCurves.Length();
1174 }
1175 
1176 AppParCurves_MultiCurve& Approx_ComputeLine::ChangeValue(const Standard_Integer Index)
1177 {
1178   return myMultiCurves.ChangeValue(Index);
1179 }
1180 
1181 
1182 const AppParCurves_MultiCurve& Approx_ComputeLine::Value(const Standard_Integer Index)
1183 const
1184 {
1185   return myMultiCurves.Value(Index);
1186 }
1187 
1188 
1189 const AppParCurves_MultiBSpCurve& Approx_ComputeLine::SplineValue()
1190 {
1191   Approx_MCurvesToBSpCurve Trans;
1192   Trans.Perform(myMultiCurves);
1193   myspline = Trans.Value();
1194   return myspline;
1195 }
1196 
1197 
1198 
1199 
1200 
1201 void Approx_ComputeLine::Parameters(const MultiLine& Line, 
1202                                const Standard_Integer firstP,
1203                                const Standard_Integer lastP,
1204                                math_Vector& TheParameters) const
1205 {
1206   Standard_Integer i, j, nbP2d, nbP3d;
1207   Standard_Real dist;
1208 
1209   if(Par == Approx_ChordLength || Par == Approx_Centripetal)
1210   {
1211     nbP3d = LineTool::NbP3d(Line);
1212     nbP2d = LineTool::NbP2d(Line);
1213     Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
1214     if(nbP3d == 0) mynbP3d = 1;
1215     if(nbP2d == 0) mynbP2d = 1;
1216 
1217     TheParameters(firstP) = 0.0;
1218     dist = 0.0;
1219     TColgp_Array1OfPnt tabP(1, mynbP3d);
1220     TColgp_Array1OfPnt tabPP(1, mynbP3d);
1221     TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
1222     TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
1223 
1224     for(i = firstP + 1; i <= lastP; i++)
1225     {
1226       if(nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i - 1, tabP, tabP2d);
1227       else if(nbP2d != 0)          LineTool::Value(Line, i - 1, tabP2d);
1228       else if(nbP3d != 0)          LineTool::Value(Line, i - 1, tabP);
1229 
1230       if(nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
1231       else if(nbP2d != 0)          LineTool::Value(Line, i, tabPP2d);
1232       else if(nbP3d != 0)          LineTool::Value(Line, i, tabPP);
1233       dist = 0;
1234       for(j = 1; j <= nbP3d; j++)
1235       {
1236         const gp_Pnt &aP1 = tabP(j),
1237                      &aP2 = tabPP(j);
1238         dist += aP2.SquareDistance(aP1);
1239       }
1240       for(j = 1; j <= nbP2d; j++)
1241       {
1242         const gp_Pnt2d &aP12d = tabP2d(j),
1243                        &aP22d = tabPP2d(j);
1244 
1245         dist += aP22d.SquareDistance(aP12d);
1246       }
1247 
1248       dist = Sqrt(dist);
1249       if(Par == Approx_ChordLength)
1250       {
1251         TheParameters(i) = TheParameters(i - 1) + dist;
1252       }
1253       else
1254       {// Par == Approx_Centripetal
1255         TheParameters(i) = TheParameters(i - 1) + Sqrt(dist);
1256       }
1257     }
1258     for(i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
1259   }
1260   else {
1261     for (i = firstP; i <= lastP; i++) {
1262       TheParameters(i) = (Standard_Real(i)-firstP)/
1263                          (Standard_Real(lastP)-Standard_Real(firstP));
1264     }
1265   }
1266 }  
1267 
1268 
1269 Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
1270                                              const Standard_Integer fpt,
1271                                              const Standard_Integer lpt,
1272                                              math_Vector&     Para,
1273                                              Standard_Real&   TheTol3d,
1274                                              Standard_Real&   TheTol2d,
1275                                              Standard_Integer& indbad)
1276 {
1277   indbad = 0;
1278   Standard_Integer deg, i;
1279   Standard_Boolean mydone;
1280   Standard_Real Fv;
1281   Standard_Integer nbp = lpt-fpt+1;
1282 
1283   math_Vector ParSav(Para.Lower(), Para.Upper());
1284   for (i = Para.Lower(); i <= Para.Upper(); i++) {
1285     ParSav(i) = Para(i);
1286   }
1287   Standard_Integer Mdegmax = mydegremax;
1288   if(nbp < Mdegmax+5 && mycut) { 
1289     Mdegmax = nbp - 5;
1290   }
1291   if(Mdegmax < mydegremin)  { 
1292     Mdegmax = mydegremin;
1293   }
1294   
1295   currenttol3d = currenttol2d = RealLast();
1296   for (deg = Min(nbp-1,mydegremin); deg <= Mdegmax; deg++) {
1297     AppParCurves_MultiCurve mySCU(deg+1);
1298     if (mysquares) {
1299       Approx_ParLeastSquareOfMyGradient SQ(Line, fpt, lpt, 
1300                                            myfirstC, mylastC, Para, deg+1);
1301       mydone = SQ.IsDone();
1302       mySCU = SQ.BezierValue();
1303       SQ.Error(Fv, TheTol3d, TheTol2d);
1304     }
1305     else {
1306       Approx_MyGradient GRAD(Line, fpt, lpt, myConstraints, 
1307                              Para, deg, mytol3d, mytol2d, myitermax);
1308       mydone = GRAD.IsDone();
1309       mySCU = GRAD.Value();
1310       if (mySCU.NbCurves() == 0)
1311         continue;
1312       TheTol3d = GRAD.MaxError3d();
1313       TheTol2d = GRAD.MaxError2d();
1314     }      
1315     Standard_Real uu1 = Para(Para.Lower()), uu2;
1316     Standard_Boolean restau = Standard_False;
1317     for ( i = Para.Lower()+1; i <= Para.Upper(); i++) {
1318       uu2 =  Para(i);
1319       if (uu2 <= uu1) {
1320         restau = Standard_True;
1321 //      cout << "restau = Standard_True" << endl;
1322         break;
1323       }
1324       uu1 = uu2;
1325     }
1326     if (restau) {
1327       for (i = Para.Lower(); i <= Para.Upper(); i++) {
1328         Para(i) = ParSav(i);
1329       }
1330     }
1331     if (mydone) {
1332       if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
1333         // Stockage de la multicurve approximee.
1334         tolreached = Standard_True;
1335 #ifdef OCCT_DEBUG
1336         if (mydebug) DUMP(mySCU);
1337 #endif
1338         if (!CheckMultiCurve(mySCU, Line,
1339                              fpt, lpt,
1340                              indbad))
1341         {
1342           return Standard_False;
1343         }
1344         else
1345         {
1346           myMultiCurves.Append(mySCU);
1347           // Stockage des parametres de la partie de MultiLine approximee:
1348           // A ameliorer !! (bq trop de recopies)
1349           Handle(TColStd_HArray1OfReal) ThePar = 
1350             new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1351           for (i = Para.Lower(); i <= Para.Upper(); i++) {
1352             ThePar->SetValue(i, Para(i));
1353           }
1354           myPar.Append(ThePar);
1355           Tolers3d.Append(TheTol3d);
1356           Tolers2d.Append(TheTol2d);
1357           return Standard_True;
1358         }
1359       }
1360     }
1361 
1362     if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
1363       TheMultiCurve = mySCU;
1364       currenttol3d = TheTol3d;
1365       currenttol2d = TheTol2d;
1366       myParameters = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1367       for (i = Para.Lower(); i <= Para.Upper(); i++) {
1368         myParameters->SetValue(i, Para(i));
1369       }
1370     }
1371 
1372   }
1373 
1374   return Standard_False;
1375 }
1376 
1377 
1378 
1379 
1380 Standard_Boolean  Approx_ComputeLine::ComputeCurve(const MultiLine& Line,
1381                                       const Standard_Integer firstpt,
1382                                       const Standard_Integer lastpt)
1383 {
1384   Standard_Integer i, j, nbP3d, nbP2d, deg;
1385   gp_Vec V13d, V23d;
1386   gp_Vec2d V12d, V22d;
1387   gp_Pnt P1, P2;
1388   gp_Pnt2d P12d, P22d;
1389   Standard_Boolean Tangent1, Tangent2, mydone= Standard_False;
1390 #ifdef OCCT_DEBUG
1391   Standard_Boolean Parallel;
1392 #endif
1393   Standard_Integer myfirstpt = firstpt, mylastpt = lastpt;
1394   Standard_Integer nbp = lastpt-firstpt+1;
1395   math_Vector Para(firstpt, lastpt);
1396 
1397   Parameters(Line, firstpt, lastpt, Para);
1398 
1399   nbP3d = LineTool::NbP3d(Line);
1400   nbP2d = LineTool::NbP2d(Line);
1401   Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
1402   if (nbP3d == 0) mynbP3d = 1 ;
1403   if (nbP2d == 0) mynbP2d = 1 ;
1404 
1405 
1406   TColgp_Array1OfVec tabV1(1, mynbP3d), tabV2(1, mynbP3d);
1407   TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d), tabP(1, mynbP3d);
1408   TColgp_Array1OfVec2d tabV12d(1, mynbP2d), tabV22d(1, mynbP2d);
1409   TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d), tabP2d(1, mynbP2d);
1410 
1411   if (nbP3d != 0 && nbP2d != 0) {
1412     LineTool::Value(Line, myfirstpt,tabP1,tabP12d);
1413     LineTool::Value(Line, mylastpt,tabP2,tabP22d);
1414     Tangent1 = LineTool::Tangency(Line, myfirstpt,tabV1,tabV12d);
1415     Tangent2 = LineTool::Tangency(Line, mylastpt,tabV2,tabV22d);
1416   }
1417   else if (nbP2d != 0) {
1418     LineTool::Value(Line, myfirstpt,tabP12d);
1419     LineTool::Value(Line, mylastpt,tabP22d);
1420     Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV12d);
1421     Tangent2 = LineTool::Tangency(Line, mylastpt, tabV22d);
1422   }
1423   else {
1424     LineTool::Value(Line, myfirstpt,tabP1);
1425     LineTool::Value(Line, mylastpt,tabP2);
1426     Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV1);
1427     Tangent2 = LineTool::Tangency(Line, mylastpt, tabV2);
1428   }
1429   if (nbp == 2) {
1430     // S il n y a que 2 points, on verifie quand meme que les tangentes sont 
1431     // alignees.
1432 #ifdef OCCT_DEBUG
1433     Parallel = Standard_True;
1434 #endif
1435     if (Tangent1) {
1436       for (i = 1; i <= nbP3d; i++) {
1437         gp_Vec PVec(tabP1(i), tabP2(i));
1438         V13d = tabV1(i);
1439         if (!PVec.IsParallel(V13d, Precision::Angular())) {
1440 #ifdef OCCT_DEBUG
1441           Parallel = Standard_False;
1442 #endif
1443           break;
1444         }
1445       }
1446       for (i = 1; i <= nbP2d; i++) {
1447         gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1448         V12d = tabV12d(i);
1449         if (!PVec2d.IsParallel(V12d, Precision::Angular())) {
1450 #ifdef OCCT_DEBUG
1451           Parallel = Standard_False;
1452 #endif
1453           break;
1454         }
1455       }
1456     }   
1457 
1458     if (Tangent2) {
1459       for (i = 1; i <= nbP3d; i++) {
1460         gp_Vec PVec(tabP1(i), tabP2(i));
1461         V23d = tabV2(i);
1462         if (!PVec.IsParallel(V23d, Precision::Angular())) {
1463 #ifdef OCCT_DEBUG
1464           Parallel = Standard_False;
1465 #endif
1466           break;
1467         }
1468       }
1469       for (i = 1; i <= nbP2d; i++) {
1470         gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1471         V22d = tabV22d(i);
1472         if (!PVec2d.IsParallel(V22d, Precision::Angular())) {
1473 #ifdef OCCT_DEBUG
1474           Parallel = Standard_False;
1475 #endif
1476           break;
1477         }
1478       }
1479     }
1480 
1481 #ifdef OCCT_DEBUG
1482     if (!Parallel) {
1483       if (mydebug) std::cout <<"droite mais tangentes pas vraiment paralleles!!"<< std::endl;
1484     }
1485 #endif
1486     AppParCurves_MultiCurve mySCU(mydegremin+1);
1487     if (nbP3d != 0 && nbP2d != 0) {
1488       AppParCurves_MultiPoint MPole1(tabP1, tabP12d);
1489       AppParCurves_MultiPoint MPole2(tabP2, tabP22d);
1490       mySCU.SetValue(1, MPole1);
1491       mySCU.SetValue(mydegremin+1, MPole2);
1492       for (i = 2; i <= mydegremin; i++) {
1493         for (j = 1; j<= nbP3d; j++) {
1494           P1 = tabP1(j);
1495           P2 = tabP2(j);
1496           tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1497         }
1498         for (j = 1; j<= nbP2d; j++) {
1499           P12d = tabP12d(j);
1500           P22d = tabP22d(j);
1501           tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1502         }
1503         AppParCurves_MultiPoint MPole(tabP, tabP2d);
1504         mySCU.SetValue(i, MPole);
1505       }
1506 
1507     }
1508     else if (nbP3d != 0) {
1509       AppParCurves_MultiPoint MPole1(tabP1);
1510       AppParCurves_MultiPoint MPole2(tabP2);
1511       mySCU.SetValue(1, MPole1);
1512       mySCU.SetValue(mydegremin+1, MPole2);
1513       for (i = 2; i <= mydegremin; i++) {
1514         for (j = 1; j<= nbP3d; j++) {
1515           P1 = tabP1(j);
1516           P2 = tabP2(j);
1517           tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1518         }
1519         AppParCurves_MultiPoint MPole(tabP);
1520         mySCU.SetValue(i, MPole);
1521       }
1522     }
1523     else if (nbP2d != 0) {
1524       AppParCurves_MultiPoint MPole1(tabP12d);
1525       AppParCurves_MultiPoint MPole2(tabP22d);
1526       mySCU.SetValue(1, MPole1);
1527       mySCU.SetValue(mydegremin+1, MPole2);
1528       for (i = 2; i <= mydegremin; i++) {
1529         for (j = 1; j<= nbP2d; j++) {
1530           P12d = tabP12d(j);
1531           P22d = tabP22d(j);
1532           tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1533         }
1534         AppParCurves_MultiPoint MPole(tabP2d);
1535         mySCU.SetValue(i, MPole);
1536       }
1537     }
1538     mydone = Standard_True;
1539     // Stockage de la multicurve approximee.
1540     tolreached = Standard_True;
1541 #ifdef OCCT_DEBUG
1542       if (mydebug) DUMP(mySCU);
1543 #endif
1544     myMultiCurves.Append(mySCU);
1545     Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1546     for (i = Para.Lower(); i <= Para.Upper(); i++) {
1547       ThePar->SetValue(i, Para(i));
1548     }
1549     myPar.Append(ThePar);
1550     Tolers3d.Append(Precision::Confusion());
1551     Tolers2d.Append(Precision::PConfusion());
1552     return mydone;
1553   }
1554 
1555   // avec les tangentes.
1556   deg = nbp+1;
1557   AppParCurves_MultiCurve mySCU(deg+1);
1558   AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
1559   Standard_Real lambda1, lambda2;
1560   math_Vector V1(1, nbP3d*3+nbP2d*2);
1561   math_Vector V2(1, nbP3d*3+nbP2d*2);
1562   FirstTangencyVector(Line, myfirstpt, V1);
1563   lambda1 = SearchFirstLambda(Line, Para, V1, myfirstpt);
1564   
1565   LastTangencyVector(Line, mylastpt, V2);
1566   lambda2 = SearchLastLambda(Line, Para, V2, mylastpt);
1567   
1568   Approx_ParLeastSquareOfMyGradient 
1569     LSQ(Line, myfirstpt, mylastpt, 
1570         Cons, Cons, Para, deg+1);
1571   
1572   lambda1 = lambda1/deg;
1573   lambda2 = lambda2/deg;
1574   LSQ.Perform(Para, V1, V2, lambda1, lambda2);
1575   mydone = LSQ.IsDone();
1576   mySCU = LSQ.BezierValue();
1577   
1578   if (mydone) {
1579     Standard_Real Fv, TheTol3d, TheTol2d;
1580     LSQ.Error(Fv, TheTol3d, TheTol2d);  
1581 
1582     // Stockage de la multicurve approximee.
1583     tolreached = Standard_True;
1584 #ifdef OCCT_DEBUG
1585       if (mydebug) DUMP(mySCU);
1586 #endif
1587     myMultiCurves.Append(mySCU);
1588     Handle(TColStd_HArray1OfReal) ThePar = 
1589       new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1590     for (i = Para.Lower(); i <= Para.Upper(); i++) {
1591       ThePar->SetValue(i, Para(i));
1592     }
1593     myPar.Append(ThePar);
1594     Tolers3d.Append(TheTol3d);
1595     Tolers2d.Append(TheTol2d);
1596     return Standard_True;
1597   }
1598   return mydone;
1599 }
1600 
1601 
1602 
1603 void Approx_ComputeLine::Init(const Standard_Integer degreemin,
1604                               const Standard_Integer degreemax,
1605                               const Standard_Real Tolerance3d,
1606                               const Standard_Real Tolerance2d,
1607                               const Standard_Integer NbIterations,
1608                               const Standard_Boolean cutting,
1609                               const Approx_ParametrizationType parametrization,
1610                               const Standard_Boolean Squares)
1611 {
1612   mydegremin = degreemin;
1613   mydegremax = degreemax;
1614   mytol3d = Tolerance3d;
1615   mytol2d = Tolerance2d;
1616   Par = parametrization;
1617   mysquares = Squares;
1618   mycut = cutting;
1619   myitermax = NbIterations;
1620 }
1621 
1622 
1623 
1624 void Approx_ComputeLine::SetDegrees(const Standard_Integer degreemin,
1625                                     const Standard_Integer degreemax)
1626 {
1627   mydegremin = degreemin;
1628   mydegremax = degreemax;
1629 }
1630 
1631 
1632 void Approx_ComputeLine::SetTolerances(const Standard_Real Tolerance3d,
1633                                        const Standard_Real Tolerance2d)
1634 {
1635   mytol3d = Tolerance3d;
1636   mytol2d = Tolerance2d;
1637 }
1638 
1639 
1640 void Approx_ComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
1641                                         const AppParCurves_Constraint LastC)
1642 {
1643   myfirstC = FirstC;
1644   mylastC = LastC;
1645 }
1646 
1647 
1648 
1649 Standard_Boolean Approx_ComputeLine::IsAllApproximated()
1650 const {
1651   return alldone;
1652 }
1653 
1654 Standard_Boolean Approx_ComputeLine::IsToleranceReached()
1655 const {
1656   return tolreached;
1657 }
1658 
1659 void Approx_ComputeLine::Error(const Standard_Integer Index,
1660                                Standard_Real& tol3d,
1661                                Standard_Real& tol2d) const
1662 {
1663   tol3d = Tolers3d.Value(Index);
1664   tol2d = Tolers2d.Value(Index);
1665 }
1666 
1667 Approx_ParametrizationType Approx_ComputeLine::Parametrization() const
1668 {
1669   return Par;
1670 }