Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/opencascade/Approx_ComputeCLine.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 //  modified by Edward AGAPOV (eap) Tue Apr 2 2002 (occ265)
0016 //  -- stop cutting an interval to approximate if next decisions
0017 //  -- get worse on and on
0018 
0019 
0020 
0021 #include <Approx_ParametrizationType.hxx>
0022 #include <AppCont_LeastSquare.hxx>
0023 #include <TColStd_Array1OfReal.hxx>
0024 #include <AppParCurves_Constraint.hxx>
0025 #include <Approx_Status.hxx>
0026 #include <Precision.hxx>
0027 
0028 const static Standard_Integer MAXSEGM = 1000;
0029 
0030 //=======================================================================
0031 //function : Approx_ComputeCLine
0032 //purpose  : The MultiLine <Line> will be approximated until tolerances
0033 //           will be reached.
0034 //           The approximation will be done from degreemin to degreemax
0035 //           with a cutting if the corresponding boolean is True.
0036 //=======================================================================
0037 
0038 Approx_ComputeCLine::Approx_ComputeCLine
0039 (const MultiLine& Line,
0040 const Standard_Integer degreemin,
0041 const Standard_Integer degreemax,
0042 const Standard_Real Tolerance3d,
0043 const Standard_Real Tolerance2d,
0044 const Standard_Boolean cutting,
0045 const AppParCurves_Constraint FirstC,
0046 const AppParCurves_Constraint LastC)
0047 {
0048   mydegremin = degreemin;
0049   mydegremax = degreemax;
0050   mytol3d = Tolerance3d;
0051   mytol2d = Tolerance2d;
0052   mycut = cutting;
0053   myfirstC = FirstC;
0054   mylastC = LastC;
0055   myMaxSegments = MAXSEGM;
0056   myInvOrder = Standard_True;
0057   myHangChecking = Standard_True;
0058   alldone = Standard_False;
0059   tolreached = Standard_False;
0060   currenttol3d = 0.0;
0061   currenttol2d = 0.0;
0062   Perform(Line);
0063 }
0064 
0065 //=======================================================================
0066 //function : Approx_ComputeCLine
0067 //purpose  : Initializes the fields of the algorithm.
0068 //=======================================================================
0069 
0070 Approx_ComputeCLine::Approx_ComputeCLine
0071 (const Standard_Integer degreemin,
0072 const Standard_Integer degreemax,
0073 const Standard_Real Tolerance3d,
0074 const Standard_Real Tolerance2d,
0075 const Standard_Boolean cutting,
0076 const AppParCurves_Constraint FirstC,
0077 const AppParCurves_Constraint LastC)
0078 {
0079   alldone = Standard_False;
0080   mydegremin = degreemin;
0081   mydegremax = degreemax;
0082   mytol3d = Tolerance3d;
0083   mytol2d = Tolerance2d;
0084   mycut = cutting;
0085   myfirstC = FirstC;
0086   mylastC = LastC;
0087   myMaxSegments = MAXSEGM;
0088   myInvOrder = Standard_True;
0089   myHangChecking = Standard_True;
0090   tolreached = Standard_False;
0091   currenttol3d = 0.0;
0092   currenttol2d = 0.0;
0093 }
0094 
0095 //=======================================================================
0096 //function : Perform
0097 //purpose  : runs the algorithm after having initialized the fields.
0098 //=======================================================================
0099 
0100 void Approx_ComputeCLine::Perform(const MultiLine& Line)
0101 {
0102   Standard_Real UFirst, ULast;
0103   Standard_Boolean Finish = Standard_False,
0104     begin = Standard_True, Ok = Standard_False;
0105   Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion();
0106   UFirst = Line.FirstParameter();
0107   ULast = Line.LastParameter();
0108   Standard_Real TolU = 0.;
0109   if (myHangChecking)
0110   {
0111     TolU = Max((ULast - UFirst)*1.e-03, Precision::Confusion());
0112   }
0113   else
0114   {
0115     TolU = Max((ULast - UFirst)*1.e-05, Precision::PApproximation());
0116   }
0117   Standard_Real myfirstU = UFirst;
0118   Standard_Real mylastU = ULast;
0119   Standard_Integer aMaxSegments = 0;
0120   Standard_Integer aMaxSegments1 = myMaxSegments - 1;
0121   Standard_Integer aNbCut = 0, aNbImp = 0, aNbComp = 10;
0122 
0123   if (!mycut)
0124   {
0125     alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d);
0126     if (!alldone)
0127     {
0128       tolreached = Standard_False;
0129       myfirstparam.Append(UFirst);
0130       mylastparam.Append(ULast);
0131       myMultiCurves.Append(TheMultiCurve);
0132       Tolers3d.Append(currenttol3d);
0133       Tolers2d.Append(currenttol2d);
0134     }
0135   }
0136   else
0137   {
0138 
0139     // previous decision to be taken if we get worse with next cut (eap)
0140     AppParCurves_MultiCurve KeptMultiCurve;
0141     Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.;
0142 
0143     while (!Finish)
0144     {
0145 
0146       // Gestion du decoupage de la multiline pour approximer:
0147       if (!begin)
0148       {
0149         if (Ok)
0150         {
0151           // Calcul de la partie a approximer.
0152           myfirstU = mylastU;
0153           mylastU = ULast;
0154           aNbCut = 0;
0155           aNbImp = 0;
0156           if (Abs(ULast - myfirstU) <= RealEpsilon()
0157               || aMaxSegments >= myMaxSegments)
0158           {
0159             Finish = Standard_True;
0160             alldone = Standard_True;
0161             return;
0162           }
0163           KeptT3d = RealLast(); KeptT2d = 0;
0164           KeptUfirst = myfirstU;
0165           KeptUlast = mylastU;
0166         }
0167         else
0168         {
0169           // keep best decision
0170           if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
0171           {
0172             KeptMultiCurve = TheMultiCurve;
0173             KeptUfirst = myfirstU;
0174             KeptUlast = mylastU;
0175             KeptT3d = thetol3d;
0176             KeptT2d = thetol2d;
0177             aNbImp++;
0178           }
0179 
0180           // cut an interval
0181           mylastU = (myfirstU + mylastU) / 2;
0182           aNbCut++;
0183         }
0184       }
0185 
0186       // Calcul des parametres sur ce nouvel intervalle.
0187       Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d);
0188       if (Ok)
0189       {
0190         aMaxSegments++;
0191       }
0192 
0193       //cout << myfirstU << " - " << mylastU << "  tol : " << thetol3d << " " << thetol2d << endl;
0194       Standard_Boolean aStopCutting = Standard_False;
0195       if (myHangChecking && aNbCut >= aNbComp)
0196       {
0197         if (aNbCut > aNbImp + 1)
0198         {
0199           aStopCutting = Standard_True;
0200         }
0201         aNbCut = 0;
0202         aNbImp = 0;
0203       }
0204       // is new decision better?
0205       if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting ))
0206       {
0207         Ok = Standard_True; // stop interval cutting, approx the rest part
0208 
0209         if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d))
0210         {
0211           KeptMultiCurve = TheMultiCurve;
0212           KeptUfirst = myfirstU;
0213           KeptUlast = mylastU;
0214           KeptT3d = thetol3d;
0215           KeptT2d = thetol2d;
0216         }
0217 
0218         mylastU = KeptUlast;
0219 
0220         tolreached = Standard_False; // helas
0221         myMultiCurves.Append(KeptMultiCurve);
0222         aMaxSegments++;
0223         Tolers3d.Append(KeptT3d);
0224         Tolers2d.Append(KeptT2d);
0225         myfirstparam.Append(KeptUfirst);
0226         mylastparam.Append(KeptUlast);
0227       }
0228 
0229       begin = Standard_False;
0230     } // while (!Finish)
0231   }
0232 }
0233 
0234 //=======================================================================
0235 //function : NbMultiCurves
0236 //purpose  : Returns the number of MultiCurve doing the approximation
0237 //           of the MultiLine.
0238 //=======================================================================
0239 
0240 Standard_Integer Approx_ComputeCLine::NbMultiCurves()const
0241 {
0242   return myMultiCurves.Length();
0243 }
0244 
0245 //=======================================================================
0246 //function : Value
0247 //purpose  : returns the approximation MultiCurve of range <Index>.
0248 //=======================================================================
0249 
0250 AppParCurves_MultiCurve Approx_ComputeCLine::Value(const Standard_Integer Index)
0251 const
0252 {
0253   return myMultiCurves.Value(Index);
0254 }
0255 
0256 //=======================================================================
0257 //function : Compute
0258 //purpose  : is internally used by the algorithms.
0259 //=======================================================================
0260 
0261 Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line,
0262   const Standard_Real Ufirst,
0263   const Standard_Real Ulast,
0264   Standard_Real&   TheTol3d,
0265   Standard_Real&   TheTol2d)
0266 {
0267 
0268 
0269   const Standard_Integer NbPointsMax = 24;
0270   const Standard_Real aMinRatio = 0.05;
0271   const Standard_Integer aMaxDeg = 8;
0272   //
0273   Standard_Integer deg, NbPoints;
0274   Standard_Boolean mydone;
0275   Standard_Real Fv;
0276 
0277   AppParCurves_MultiCurve aPrevCurve;
0278   Standard_Real aPrevTol3d = RealLast(), aPrevTol2d = RealLast();
0279   Standard_Boolean aPrevIsOk = Standard_False;
0280   Standard_Boolean anInvOrder = myInvOrder;
0281   if (anInvOrder && mydegremax > aMaxDeg)
0282   {
0283     if ((Ulast - Ufirst) / (Line.LastParameter() - Line.FirstParameter()) < aMinRatio)
0284     {
0285       anInvOrder = Standard_False;
0286     }
0287   }
0288   if (anInvOrder)
0289   {
0290     for (deg = mydegremax; deg >= mydegremin; deg--) {
0291       NbPoints = Min(2 * deg + 1, NbPointsMax);
0292       AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
0293       mydone = LSquare.IsDone();
0294       if (mydone)
0295       {
0296         LSquare.Error(Fv, TheTol3d, TheTol2d);
0297         if (TheTol3d <= mytol3d && TheTol2d <= mytol2d)
0298         {
0299           if (deg == mydegremin)
0300           {
0301             // Stockage de la multicurve approximee.
0302             tolreached = Standard_True;
0303             myMultiCurves.Append(LSquare.Value());
0304             myfirstparam.Append(Ufirst);
0305             mylastparam.Append(Ulast);
0306             Tolers3d.Append(TheTol3d);
0307             Tolers2d.Append(TheTol2d);
0308             return Standard_True;
0309           }
0310           aPrevTol3d = TheTol3d;
0311           aPrevTol2d = TheTol2d;
0312           aPrevCurve = LSquare.Value();
0313           aPrevIsOk = Standard_True;
0314           continue;
0315         }
0316         else if (aPrevIsOk)
0317         {
0318           // Stockage de la multicurve approximee.
0319           tolreached = Standard_True;
0320           TheTol3d = aPrevTol3d;
0321           TheTol2d = aPrevTol2d;
0322           myMultiCurves.Append(aPrevCurve);
0323           myfirstparam.Append(Ufirst);
0324           mylastparam.Append(Ulast);
0325           Tolers3d.Append(aPrevTol3d);
0326           Tolers2d.Append(aPrevTol2d);
0327           return Standard_True;
0328         }
0329       }
0330       else if (aPrevIsOk)
0331       {
0332         // Stockage de la multicurve approximee.
0333         tolreached = Standard_True;
0334         TheTol3d = aPrevTol3d;
0335         TheTol2d = aPrevTol2d;
0336         myMultiCurves.Append(aPrevCurve);
0337         myfirstparam.Append(Ufirst);
0338         mylastparam.Append(Ulast);
0339         Tolers3d.Append(aPrevTol3d);
0340         Tolers2d.Append(aPrevTol2d);
0341         return Standard_True;
0342       }
0343       if (!aPrevIsOk && deg == mydegremax)
0344       {
0345         TheMultiCurve = LSquare.Value();
0346         currenttol3d = TheTol3d;
0347         currenttol2d = TheTol2d;
0348         aPrevTol3d = TheTol3d;
0349         aPrevTol2d = TheTol2d;
0350         aPrevCurve = TheMultiCurve;
0351         break;
0352       }
0353     }
0354   }
0355   else
0356   {
0357     for (deg = mydegremin; deg <= mydegremax; deg++) {
0358       NbPoints = Min(2 * deg + 1, NbPointsMax);
0359       AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints);
0360       mydone = LSquare.IsDone();
0361       if (mydone) {
0362         LSquare.Error(Fv, TheTol3d, TheTol2d);
0363         if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
0364           // Stockage de la multicurve approximee.
0365           tolreached = Standard_True;
0366           myMultiCurves.Append(LSquare.Value());
0367           myfirstparam.Append(Ufirst);
0368           mylastparam.Append(Ulast);
0369           Tolers3d.Append(TheTol3d);
0370           Tolers2d.Append(TheTol2d);
0371           return Standard_True;
0372         }
0373       }
0374       if (deg == mydegremax) {
0375         TheMultiCurve = LSquare.Value();
0376         currenttol3d = TheTol3d;
0377         currenttol2d = TheTol2d;
0378       }
0379     }
0380   }
0381   return Standard_False;
0382 }
0383 
0384 //=======================================================================
0385 //function : Parameters
0386 //purpose  : returns the first and last parameters of the 
0387 //           <Index> MultiCurve.
0388 //=======================================================================
0389 
0390 void Approx_ComputeCLine::Parameters(const Standard_Integer Index,
0391   Standard_Real& firstpar,
0392   Standard_Real& lastpar) const
0393 {
0394   firstpar = myfirstparam.Value(Index);
0395   lastpar = mylastparam.Value(Index);
0396 }
0397 
0398 //=======================================================================
0399 //function : SetDegrees
0400 //purpose  : changes the degrees of the approximation.
0401 //=======================================================================
0402 
0403 void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin,
0404   const Standard_Integer degreemax)
0405 {
0406   mydegremin = degreemin;
0407   mydegremax = degreemax;
0408 }
0409 
0410 //=======================================================================
0411 //function : SetTolerances
0412 //purpose  : Changes the tolerances of the approximation.
0413 //=======================================================================
0414 
0415 void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d,
0416   const Standard_Real Tolerance2d)
0417 {
0418   mytol3d = Tolerance3d;
0419   mytol2d = Tolerance2d;
0420 }
0421 
0422 //=======================================================================
0423 //function : SetConstraints
0424 //purpose  : Changes the constraints of the approximation.
0425 //=======================================================================
0426 
0427 void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC,
0428   const AppParCurves_Constraint LastC)
0429 {
0430   myfirstC = FirstC;
0431   mylastC = LastC;
0432 }
0433 
0434 //=======================================================================
0435 //function : SetMaxSegments
0436 //purpose  : Changes the max number of segments, which is allowed for cutting.
0437 //=======================================================================
0438 
0439 void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments)
0440 {
0441   myMaxSegments = theMaxSegments;
0442 }
0443 
0444 //=======================================================================
0445 //function : SetInvOrder
0446 //purpose  : 
0447 //=======================================================================
0448 void Approx_ComputeCLine::SetInvOrder(const Standard_Boolean theInvOrder)
0449 {
0450   myInvOrder = theInvOrder;
0451 }
0452 
0453 //=======================================================================
0454 //function : SetHangChecking
0455 //purpose  : 
0456 //=======================================================================
0457 void Approx_ComputeCLine::SetHangChecking(const Standard_Boolean theHangChecking)
0458 {
0459   myHangChecking = theHangChecking;
0460 }
0461 
0462 //=======================================================================
0463 //function : IsAllApproximated
0464 //purpose  : returns False if at a moment of the approximation,
0465 //           the status NoApproximation has been sent by the user
0466 //           when more points were needed.
0467 //=======================================================================
0468 
0469 Standard_Boolean Approx_ComputeCLine::IsAllApproximated()
0470 const {
0471   return alldone;
0472 }
0473 
0474 //=======================================================================
0475 //function : IsToleranceReached
0476 //purpose  : returns False if the status NoPointsAdded has been sent.
0477 //=======================================================================
0478 
0479 Standard_Boolean Approx_ComputeCLine::IsToleranceReached()
0480 const {
0481   return tolreached;
0482 }
0483 
0484 //=======================================================================
0485 //function : Error
0486 //purpose  : returns the tolerances 2d and 3d of the <Index> MultiCurve.
0487 //=======================================================================
0488 
0489 void Approx_ComputeCLine::Error(const Standard_Integer Index,
0490   Standard_Real& tol3d,
0491   Standard_Real& tol2d) const
0492 {
0493   tol3d = Tolers3d.Value(Index);
0494   tol2d = Tolers2d.Value(Index);
0495 }