BRepAdaptor_CompCurve2.cxx

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2007                                                    *
00003  *   Joachim Zettler <Joachim.Zettler@gmx.de>                              *
00004  *   Adapted by Joachim Zettler to use with a WireExplorer made            *
00005  *       by Stephane Routelous                                                 *
00006  *                                                                         *
00007  *   This file is part of the FreeCAD CAx development system.              *
00008  *                                                                         *
00009  *   This library is free software; you can redistribute it and/or         *
00010  *   modify it under the terms of the GNU Library General Public           *
00011  *   License as published by the Free Software Foundation; either          *
00012  *   version 2 of the License, or (at your option) any later version.      *
00013  *                                                                         *
00014  *   This library  is distributed in the hope that it will be useful,      *
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017  *   GNU Library General Public License for more details.                  *
00018  *                                                                         *
00019  *   You should have received a copy of the GNU Library General Public     *
00020  *   License along with this library; see the file COPYING.LIB. If not,    *
00021  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00022  *   Suite 330, Boston, MA  02111-1307, USA                                *
00023  *                                                                         *
00024  ***************************************************************************/
00025 
00026 //
00027 
00028 #include "PreCompiled.h"
00029 
00030 #include "BRepAdaptor_CompCurve2.h"
00031 #include <BRepAdaptor_Curve.hxx>
00032 #include <BRepAdaptor_HCurve.hxx>
00033 #include <BRepAdaptor_HCompCurve.hxx>
00034 #include <BRepAdaptor_HArray1OfCurve.hxx>
00035 #include <TColStd_HArray1OfReal.hxx>
00036 #include <BRep_Tool.hxx>
00037 
00038 #include <TopAbs_Orientation.hxx>
00039 
00040 #include <GCPnts_AbscissaPoint.hxx>
00041 #include <ElCLib.hxx>
00042 #include <TopExp.hxx>
00043 #include <TopoDS_Vertex.hxx>
00044 #include "WireExplorer.h"
00045 
00046 BRepAdaptor_CompCurve2::BRepAdaptor_CompCurve2()
00047 {
00048 }
00049 
00050 BRepAdaptor_CompCurve2::BRepAdaptor_CompCurve2(const TopoDS_Wire& W,
00051                                              const Standard_Boolean AC)
00052 {
00053   Initialize(W, AC);
00054 }
00055 
00056 BRepAdaptor_CompCurve2::BRepAdaptor_CompCurve2(const TopoDS_Wire& W,
00057                                              const Standard_Boolean AC,
00058                                              const Standard_Real First,
00059                                              const Standard_Real Last,
00060                                              const Standard_Real Tol)
00061 {
00062   Initialize(W, AC, First, Last, Tol);
00063 }
00064 
00065  void BRepAdaptor_CompCurve2::Initialize(const TopoDS_Wire& W,
00066                                         const Standard_Boolean AC)
00067 {
00068   Standard_Integer ii, NbEdge;
00069   
00070   TopoDS_Edge E;
00071 
00072   myWire = W;
00073   WireExplorer wexp(myWire);
00074   PTol = 0.0;
00075   IsbyAC = AC;
00076 
00077   for (NbEdge=0, wexp.Init();wexp.More(); wexp.Next())
00078     if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
00079 
00080   if (NbEdge == 0) return;
00081 
00082   CurIndex = (NbEdge+1)/2;
00083   myCurves = new BRepAdaptor_HArray1OfCurve(1,NbEdge);
00084   myKnots = new (TColStd_HArray1OfReal) (1,NbEdge+1);
00085   myKnots->SetValue(1, 0.);
00086 
00087   for (ii=0, wexp.Init();wexp.More(); wexp.Next()) {
00088     E = wexp.Current();
00089     if (! BRep_Tool::Degenerated(E)) {
00090       ii++;
00091       myCurves->ChangeValue(ii).Initialize(E);
00092       if (AC) {
00093         myKnots->SetValue(ii+1,  myKnots->Value(ii));
00094         myKnots->ChangeValue(ii+1) +=
00095           GCPnts_AbscissaPoint::Length(myCurves->ChangeValue(ii));
00096       }
00097       else  myKnots->SetValue(ii+1, (Standard_Real)ii);
00098     }
00099   }
00100 
00101   Forward = Standard_True; // Defaut ; Les Edge Reverse seront parcourue
00102                            // a rebourt.
00103   if((NbEdge > 2) || ((NbEdge==2) && (!myWire.Closed())) ) {
00104     TopAbs_Orientation Or = myCurves->Value(1).Edge().Orientation();
00105     Standard_Boolean B;
00106     TopoDS_Vertex VI, VL;
00107     B = TopExp::CommonVertex(myCurves->Value(1).Edge(),
00108                              myCurves->Value(2).Edge(),
00109                              VI);
00110     VL = TopExp::LastVertex(myCurves->Value(1).Edge());
00111     if (VI.IsSame(VL)) { // On Garde toujours le sens de parcout
00112       if (Or == TopAbs_REVERSED)
00113          Forward = Standard_False;
00114     }
00115     else {// On renverse toujours le sens de parcout
00116      if (Or != TopAbs_REVERSED)
00117          Forward = Standard_False;
00118     }
00119   }
00120 
00121   TFirst = 0;
00122   TLast = myKnots->Value(myKnots->Length());
00123   myPeriod = TLast - TFirst;
00124   if (NbEdge == 1)  {
00125     Periodic =  myCurves->Value(1).IsPeriodic();
00126   }
00127   else {
00128     Periodic = Standard_False;
00129   }
00130 }
00131 
00132  void BRepAdaptor_CompCurve2::Initialize(const TopoDS_Wire& W,
00133                                         const Standard_Boolean AC,
00134                                         const Standard_Real First,
00135                                         const Standard_Real Last,
00136                                         const Standard_Real Tol)
00137 {
00138   Initialize(W, AC);
00139   TFirst = First;
00140   TLast = Last;
00141   PTol = Tol;
00142 
00143   // Trim des courbes extremes.
00144   Handle (BRepAdaptor_HCurve) HC;
00145   Standard_Integer i1, i2;
00146   Standard_Real f=TFirst, l=TLast, d;
00147   i1 = i2 = CurIndex;
00148   Prepare(f, d, i1);
00149   Prepare(l, d, i2);
00150   CurIndex = (i1+i2)/2; // Petite optimisation
00151   if (i1==i2) {
00152     if (l > f)
00153       HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(f, l, PTol));
00154     else
00155       HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(l, f, PTol));
00156     myCurves->SetValue(i1, HC->ChangeCurve());
00157   }
00158   else {
00159     const BRepAdaptor_Curve& c1 = myCurves->Value(i1);
00160     const BRepAdaptor_Curve& c2 = myCurves->Value(i2);
00161     Standard_Real k;
00162 
00163     k = c1.LastParameter();
00164     if (k>f)
00165       HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(f, k, PTol));
00166     else
00167       HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(k, f, PTol));
00168     myCurves->SetValue(i1, HC->ChangeCurve());
00169 
00170     k = c2.FirstParameter();
00171     if (k<=l)
00172       HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(k, l, PTol));
00173     else
00174       HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(l, k, PTol));
00175     myCurves->SetValue(i2, HC->ChangeCurve());
00176   }
00177 }
00178 
00179 
00180 void BRepAdaptor_CompCurve2::SetPeriodic(const Standard_Boolean isPeriodic)
00181 {
00182   if (myWire.Closed()) {
00183     Periodic = isPeriodic;
00184   }
00185 }
00186 
00187 
00188 const TopoDS_Wire& BRepAdaptor_CompCurve2::Wire() const
00189 {
00190   return myWire;
00191 }
00192 
00193  void BRepAdaptor_CompCurve2::Edge(const Standard_Real U,
00194                                   TopoDS_Edge& E,
00195                                   Standard_Real& UonE) const
00196 {
00197   Standard_Real d;
00198   Standard_Integer index = CurIndex;
00199   UonE = U;
00200   Prepare(UonE, d, index);
00201   E = myCurves->Value(index).Edge();
00202 }
00203 
00204  Standard_Real BRepAdaptor_CompCurve2::FirstParameter() const
00205 {
00206   return TFirst;
00207 }
00208 
00209  Standard_Real BRepAdaptor_CompCurve2::LastParameter() const
00210 {
00211   return TLast;
00212 }
00213 
00214  GeomAbs_Shape BRepAdaptor_CompCurve2::Continuity() const
00215 {
00216   if ( myCurves->Length() > 1) return GeomAbs_C0;
00217   return myCurves->Value(1).Continuity();
00218 }
00219 
00220  Standard_Integer BRepAdaptor_CompCurve2::NbIntervals(const GeomAbs_Shape S)
00221 {
00222   Standard_Integer NbInt, ii;
00223   for (ii=1, NbInt=0; ii<=myCurves->Length(); ii++)
00224     NbInt += myCurves->ChangeValue(ii).NbIntervals(S);
00225 
00226   return NbInt;
00227 }
00228 
00229  void BRepAdaptor_CompCurve2::Intervals(TColStd_Array1OfReal& T,
00230                                        const GeomAbs_Shape S)
00231 {
00232   Standard_Integer ii, jj, kk, n;
00233   Standard_Real f, F, delta;
00234 
00235   // Premiere courbe (sens de parcourt de le edge)
00236   n = myCurves->ChangeValue(1).NbIntervals(S);
00237   Handle(TColStd_HArray1OfReal) Ti = new (TColStd_HArray1OfReal) (1, n+1);
00238   myCurves->ChangeValue(1).Intervals(Ti->ChangeArray1(), S);
00239   InvPrepare(1, f, delta);
00240   F = myKnots->Value(1);
00241   if (delta < 0) {
00242     //sens de parcourt inverser
00243     for (kk=1,jj=Ti->Length(); jj>0; kk++, jj--)
00244       T(kk) = F + (Ti->Value(jj)-f)*delta;
00245   }
00246   else {
00247     for (kk=1; kk<=Ti->Length(); kk++)
00248       T(kk) = F + (Ti->Value(kk)-f)*delta;
00249   }
00250 
00251   // et les suivante
00252   for (ii=2; ii<=myCurves->Length(); ii++) {
00253     n = myCurves->ChangeValue(ii).NbIntervals(S);
00254     if (n != Ti->Length()-1) Ti = new (TColStd_HArray1OfReal) (1, n+1);
00255     myCurves->ChangeValue(ii).Intervals(Ti->ChangeArray1(), S);
00256     InvPrepare(ii, f, delta);
00257     F = myKnots->Value(ii);
00258     if (delta < 0) {
00259       //sens de parcourt inverser
00260       for (jj=Ti->Length()-1; jj>0; kk++, jj--)
00261         T(kk) = F + (Ti->Value(jj)-f)*delta;
00262     }
00263     else {
00264       for (jj=2; jj<=Ti->Length(); kk++, jj++)
00265         T(kk) = F + (Ti->Value(jj)-f)*delta;
00266     }
00267   }
00268 }
00269 
00270 
00271 
00272  Standard_Boolean BRepAdaptor_CompCurve2::IsClosed() const
00273 {
00274   return myWire.Closed();
00275 }
00276 
00277  Standard_Boolean BRepAdaptor_CompCurve2::IsPeriodic() const
00278 {
00279   return Periodic;
00280 
00281 }
00282 
00283  Standard_Real BRepAdaptor_CompCurve2::Period() const
00284 {
00285   return myPeriod;
00286 }
00287 
00288  gp_Pnt BRepAdaptor_CompCurve2::Value(const Standard_Real U) const
00289 {
00290   Standard_Real u = U, d;
00291   Standard_Integer index = CurIndex;
00292   Prepare(u, d, index);
00293   return myCurves->Value(index).Value(u);
00294 }
00295 
00296  void BRepAdaptor_CompCurve2::D0(const Standard_Real U,
00297                                 gp_Pnt& P) const
00298 {
00299   Standard_Real u = U, d;
00300   Standard_Integer index = CurIndex;
00301   Prepare(u, d, index);
00302   myCurves->Value(index).D0(u, P);
00303 }
00304 
00305  void BRepAdaptor_CompCurve2::D1(const Standard_Real U,
00306                                 gp_Pnt& P,
00307                                 gp_Vec& V) const
00308 {
00309   Standard_Real u = U, d;
00310   Standard_Integer index = CurIndex;
00311   Prepare(u, d, index);
00312   myCurves->Value(index).D1(u, P, V);
00313   V*=d;
00314 }
00315 
00316  void BRepAdaptor_CompCurve2::D2(const Standard_Real U,
00317                                 gp_Pnt& P,
00318                                 gp_Vec& V1,
00319                                 gp_Vec& V2) const
00320 {
00321   Standard_Real u = U, d;
00322   Standard_Integer index = CurIndex;
00323   Prepare(u, d, index);
00324   myCurves->Value(index).D2(u, P, V1, V2);
00325   V1*=d;
00326   V2 *= d*d;
00327 }
00328 
00329  void BRepAdaptor_CompCurve2::D3(const Standard_Real U,
00330                                 gp_Pnt& P,gp_Vec& V1,
00331                                 gp_Vec& V2,
00332                                 gp_Vec& V3) const
00333 {
00334   Standard_Real u = U, d;
00335   Standard_Integer index = CurIndex;
00336   Prepare(u, d, index);
00337   myCurves->Value(index).D3(u, P, V1, V2, V3);
00338   V1*=d;
00339   V2 *= d*d;
00340   V3 *= d*d*d;
00341 }
00342 
00343  gp_Vec BRepAdaptor_CompCurve2::DN(const Standard_Real U,
00344                                   const Standard_Integer N) const
00345 {
00346   Standard_Real u = U, d;
00347   Standard_Integer index = CurIndex;
00348   Prepare(u, d, index);
00349 
00350   return (myCurves->Value(index).DN(u, N) * Pow(d, N));
00351 }
00352 
00353  Standard_Real BRepAdaptor_CompCurve2::Resolution(const Standard_Real R3d) const
00354 {
00355   Standard_Real Res = 1.e200, r;
00356   Standard_Integer ii, L = myCurves->Length();
00357   for (ii=1; ii<=L; ii++) {
00358     r = myCurves->Value(ii).Resolution(R3d);
00359     if (r < Res) Res = r;
00360   }
00361   return Res;
00362 }
00363 
00364  GeomAbs_CurveType BRepAdaptor_CompCurve2::GetType() const
00365 {
00366   return GeomAbs_OtherCurve; //temporaire
00367 //  if ( myCurves->Length() > 1) return GeomAbs_OtherCurve;
00368 //  return myCurves->Value(1).GetType();
00369 }
00370 
00371  gp_Lin BRepAdaptor_CompCurve2::Line() const
00372 {
00373   return myCurves->Value(1).Line();
00374 }
00375 
00376  gp_Circ BRepAdaptor_CompCurve2::Circle() const
00377 {
00378   return myCurves->Value(1).Circle();
00379 }
00380 
00381  gp_Elips BRepAdaptor_CompCurve2::Ellipse() const
00382 {
00383   return myCurves->Value(1).Ellipse();
00384 }
00385 
00386  gp_Hypr BRepAdaptor_CompCurve2::Hyperbola() const
00387 {
00388   return myCurves->Value(1).Hyperbola();
00389 }
00390 
00391  gp_Parab BRepAdaptor_CompCurve2::Parabola() const
00392 {
00393   return myCurves->Value(1).Parabola();
00394 }
00395 
00396  Standard_Integer BRepAdaptor_CompCurve2::Degree() const
00397 {
00398   return myCurves->Value(1).Degree();
00399 }
00400 
00401  Standard_Boolean BRepAdaptor_CompCurve2::IsRational() const
00402 {
00403   return myCurves->Value(1).IsRational();
00404 }
00405 
00406  Standard_Integer BRepAdaptor_CompCurve2::NbPoles() const
00407 {
00408   return myCurves->Value(1).NbPoles();
00409 }
00410 
00411  Standard_Integer BRepAdaptor_CompCurve2::NbKnots() const
00412 {
00413   return myCurves->Value(1).NbKnots();
00414 }
00415 
00416  Handle(Geom_BezierCurve) BRepAdaptor_CompCurve2::Bezier() const
00417 {
00418   return myCurves->Value(1).Bezier();
00419 }
00420 
00421  Handle(Geom_BSplineCurve) BRepAdaptor_CompCurve2::BSpline() const
00422 {
00423   return myCurves->Value(1).BSpline();
00424 }
00425 
00426 //=======================================================================
00427 //function : Prepare
00428 //purpose  :
00429 // Lorsque le parametre est pres de un "noeud" on determine la loi en
00430 // fonction du signe de tol:
00431 //   - negatif -> Loi precedente au noeud.
00432 //   - positif -> Loi consecutive au noeud.
00433 //=======================================================================
00434 
00435  void BRepAdaptor_CompCurve2::Prepare(Standard_Real& W,
00436                                      Standard_Real& Delta,
00437                                      Standard_Integer& CurIndex) const
00438 {
00439   Standard_Real f,l, Wtest, Eps;
00440   Standard_Integer ii;
00441   if (W-TFirst < TLast-W) { Eps = PTol; }
00442   else                    { Eps = -PTol;}
00443 
00444 
00445   Wtest = W+Eps; //Decalage pour discriminer les noeuds
00446   if(Periodic){
00447     Wtest = ElCLib::InPeriod(Wtest,
00448                              0,
00449                              myPeriod);
00450     W = Wtest-Eps;
00451   }
00452 
00453   // Recheche de le index
00454   Standard_Boolean Trouve = Standard_False;
00455   if (myKnots->Value(CurIndex) > Wtest) {
00456     for (ii=CurIndex-1; ii>0 && !Trouve; ii--)
00457       if (myKnots->Value(ii)<= Wtest) {
00458         CurIndex = ii;
00459         Trouve = Standard_True;
00460       }
00461     if (!Trouve) CurIndex = 1; // En dehors des bornes ...
00462   }
00463 
00464   else if (myKnots->Value(CurIndex+1) <= Wtest) {
00465     for (ii=CurIndex+1; ii<=myCurves->Length() && !Trouve; ii++)
00466       if (myKnots->Value(ii+1)> Wtest) {
00467         CurIndex = ii;
00468         Trouve = Standard_True;
00469       }
00470     if (!Trouve) CurIndex = myCurves->Length(); // En dehors des bornes ...
00471   }
00472 
00473   // Reverse ?
00474   const TopoDS_Edge& E = myCurves->Value(CurIndex).Edge();
00475   TopAbs_Orientation Or = E.Orientation();
00476   Standard_Boolean Reverse;
00477   Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
00478             (!Forward && (Or != TopAbs_REVERSED));
00479 
00480   // Calcul du parametre local
00481   BRep_Tool::Range(E, f, l);
00482   Delta = myKnots->Value(CurIndex+1) - myKnots->Value(CurIndex);
00483   if (Delta > PTol*1.e-9) Delta = (l-f)/Delta;
00484 
00485   if (Reverse) {
00486     Delta *= -1;
00487     W = l + (W-myKnots->Value(CurIndex)) * Delta;
00488   }
00489   else {
00490     W = f + (W-myKnots->Value(CurIndex)) * Delta;
00491   }
00492 }
00493 
00494 void  BRepAdaptor_CompCurve2::InvPrepare(const Standard_Integer index,
00495                                         Standard_Real& First,
00496                                         Standard_Real& Delta) const
00497 {
00498   // Reverse ?
00499   const TopoDS_Edge& E = myCurves->Value(index).Edge();
00500   TopAbs_Orientation Or = E.Orientation();
00501   Standard_Boolean Reverse;
00502   Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
00503             (!Forward && (Or != TopAbs_REVERSED));
00504 
00505   // Calcul des parametres de reparametrisation
00506   // tel que : T = Ti + (t-First)*Delta
00507   Standard_Real f, l;
00508   BRep_Tool::Range(E, f, l);
00509   Delta = myKnots->Value(index+1) - myKnots->Value(index);
00510   if (l-f > PTol*1.e-9) Delta /= (l-f);
00511 
00512   if (Reverse) {
00513     Delta *= -1;
00514     First = l;
00515   }
00516   else {
00517     First = f;
00518   }
00519 }

Generated on Wed Nov 23 18:59:59 2011 for FreeCAD by  doxygen 1.6.1