0025246: Make methods Intervals and NbIntervals const in Adaptor3d_Curve and it desce...
[occt.git] / src / BRepAdaptor / BRepAdaptor_CompCurve.cxx
1 // Created on: 1998-08-20
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepAdaptor_CompCurve.ixx>
18
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepAdaptor_HCurve.hxx>
21 #include <BRepAdaptor_HCompCurve.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepTools_WireExplorer.hxx>
24 #include <TopAbs_Orientation.hxx>
25
26 #include <GCPnts_AbscissaPoint.hxx>
27 #include <ElCLib.hxx>
28 #include <TopExp.hxx>
29
30 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve()
31 : TFirst  (0.0),
32   TLast   (0.0),
33   PTol    (0.0),
34   myPeriod(0.0),
35   CurIndex(-1),
36   Forward (Standard_False),
37   IsbyAC  (Standard_False),
38   Periodic(Standard_False)
39 {
40 }
41
42 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire&     theWire,
43                                              const Standard_Boolean theIsAC)
44 : myWire  (theWire),
45   TFirst  (0.0),
46   TLast   (0.0),
47   PTol    (0.0),
48   myPeriod(0.0),
49   CurIndex(-1),
50   Forward (Standard_False),
51   IsbyAC  (theIsAC),
52   Periodic(Standard_False)
53 {
54   Initialize(theWire, theIsAC);
55 }
56
57 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire& theWire,
58                                              const Standard_Boolean theIsAC,
59                                              const Standard_Real theFirst,
60                                              const Standard_Real theLast,
61                                              const Standard_Real theTolerance)
62 : myWire  (theWire),
63   TFirst  (theFirst),
64   TLast   (theLast),
65   PTol    (theTolerance),
66   myPeriod(0.0),
67   CurIndex(-1),
68   Forward (Standard_False),
69   IsbyAC  (theIsAC),
70   Periodic(Standard_False)
71 {
72   Initialize(theWire, theIsAC, theFirst, theLast, theTolerance);
73 }
74
75  void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
76                                         const Standard_Boolean AC)
77 {
78   Standard_Integer ii, NbEdge;
79   BRepTools_WireExplorer wexp;
80   TopoDS_Edge E;
81
82   myWire = W;
83   PTol = 0.0;
84   IsbyAC = AC;
85
86   for (NbEdge=0, wexp.Init(myWire);
87        wexp.More(); wexp.Next())
88     if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
89
90   if (NbEdge == 0) return;
91
92   CurIndex = (NbEdge+1)/2;
93   myCurves = new (BRepAdaptor_HArray1OfCurve) (1,NbEdge);
94   myKnots = new (TColStd_HArray1OfReal) (1,NbEdge+1);
95   myKnots->SetValue(1, 0.);
96
97   for (ii=0, wexp.Init(myWire);
98        wexp.More(); wexp.Next()) {
99     E = wexp.Current();
100     if (! BRep_Tool::Degenerated(E)) {
101       ii++;
102       myCurves->ChangeValue(ii).Initialize(E);
103       if (AC) {
104         myKnots->SetValue(ii+1,  myKnots->Value(ii));
105         myKnots->ChangeValue(ii+1) +=
106           GCPnts_AbscissaPoint::Length(myCurves->ChangeValue(ii));
107       }
108       else  myKnots->SetValue(ii+1, (Standard_Real)ii);
109     }
110   }
111
112   Forward = Standard_True; // Defaut ; The Reverse Edges are parsed.
113   if((NbEdge > 2) || ((NbEdge==2) && (!myWire.Closed())) ) {
114     TopAbs_Orientation Or = myCurves->Value(1).Edge().Orientation();
115     TopoDS_Vertex VI, VL;
116     TopExp::CommonVertex(myCurves->Value(1).Edge(),
117                              myCurves->Value(2).Edge(),
118                              VI);
119     VL = TopExp::LastVertex(myCurves->Value(1).Edge());
120     if (VI.IsSame(VL)) { // The direction of parsing is always preserved
121       if (Or == TopAbs_REVERSED)
122          Forward = Standard_False;
123     }
124     else {// The direction of parsing is always reversed
125      if (Or != TopAbs_REVERSED)
126          Forward = Standard_False;
127     }
128   }
129
130   TFirst = 0;
131   TLast = myKnots->Value(myKnots->Length());
132   myPeriod = TLast - TFirst;
133   if (NbEdge == 1)  {
134     Periodic =  myCurves->Value(1).IsPeriodic();
135   }
136   else {
137     Periodic = Standard_False;
138   }
139 }
140
141  void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
142                                         const Standard_Boolean AC,
143                                         const Standard_Real First,
144                                         const Standard_Real Last,
145                                         const Standard_Real Tol)
146 {
147   Initialize(W, AC);
148   TFirst = First;
149   TLast = Last;
150   PTol = Tol;
151
152   // Trim the extremal curves.
153   Handle (BRepAdaptor_HCurve) HC;
154   Standard_Integer i1, i2;
155   Standard_Real f=TFirst, l=TLast, d;
156   i1 = i2 = CurIndex;
157   Prepare(f, d, i1);
158   Prepare(l, d, i2);
159   CurIndex = (i1+i2)/2; // Small optimization
160   if (i1==i2) {
161     if (l > f)
162       HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(f, l, PTol));
163     else
164       HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(l, f, PTol));
165     myCurves->SetValue(i1, HC->ChangeCurve());
166   }
167   else {
168     const BRepAdaptor_Curve& c1 = myCurves->Value(i1);
169     const BRepAdaptor_Curve& c2 = myCurves->Value(i2);
170     Standard_Real k;
171
172     k = c1.LastParameter();
173     if (k>f)
174       HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(f, k, PTol));
175     else
176       HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(k, f, PTol));
177     myCurves->SetValue(i1, HC->ChangeCurve());
178
179     k = c2.FirstParameter();
180     if (k<=l)
181       HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(k, l, PTol));
182     else
183       HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(l, k, PTol));
184     myCurves->SetValue(i2, HC->ChangeCurve());
185   }
186 }
187
188
189 void BRepAdaptor_CompCurve::SetPeriodic(const Standard_Boolean isPeriodic)
190 {
191   if (myWire.Closed()) {
192     Periodic = isPeriodic;
193   }
194 }
195
196
197 const TopoDS_Wire& BRepAdaptor_CompCurve::Wire() const
198 {
199   return myWire;
200 }
201
202  void BRepAdaptor_CompCurve::Edge(const Standard_Real U,
203                                   TopoDS_Edge& E,
204                                   Standard_Real& UonE) const
205 {
206   Standard_Real d;
207   Standard_Integer index = CurIndex;
208   UonE = U;
209   Prepare(UonE, d, index);
210   E = myCurves->Value(index).Edge();
211 }
212
213  Standard_Real BRepAdaptor_CompCurve::FirstParameter() const
214 {
215   return TFirst;
216 }
217
218  Standard_Real BRepAdaptor_CompCurve::LastParameter() const
219 {
220   return TLast;
221 }
222
223  GeomAbs_Shape BRepAdaptor_CompCurve::Continuity() const
224 {
225   if ( myCurves->Length() > 1) return GeomAbs_C0;
226   return myCurves->Value(1).Continuity();
227 }
228
229  Standard_Integer BRepAdaptor_CompCurve::NbIntervals(const GeomAbs_Shape S) const
230 {
231   Standard_Integer NbInt, ii;
232   for (ii=1, NbInt=0; ii<=myCurves->Length(); ii++)
233     NbInt += myCurves->ChangeValue(ii).NbIntervals(S);
234
235   return NbInt;
236 }
237
238  void BRepAdaptor_CompCurve::Intervals(TColStd_Array1OfReal& T,
239                                        const GeomAbs_Shape S) const
240 {
241   Standard_Integer ii, jj, kk, n;
242   Standard_Real f, F, delta;
243
244   // First curve (direction of parsing of the edge)
245   n = myCurves->ChangeValue(1).NbIntervals(S);
246   Handle(TColStd_HArray1OfReal) Ti = new (TColStd_HArray1OfReal) (1, n+1);
247   myCurves->ChangeValue(1).Intervals(Ti->ChangeArray1(), S);
248   InvPrepare(1, f, delta);
249   F = myKnots->Value(1);
250   if (delta < 0) {
251     // invert the direction of parsing
252     for (kk=1,jj=Ti->Length(); jj>0; kk++, jj--)
253       T(kk) = F + (Ti->Value(jj)-f)*delta;
254   }
255   else {
256     for (kk=1; kk<=Ti->Length(); kk++)
257       T(kk) = F + (Ti->Value(kk)-f)*delta;
258   }
259
260   // and the next
261   for (ii=2; ii<=myCurves->Length(); ii++) {
262     n = myCurves->ChangeValue(ii).NbIntervals(S);
263     if (n != Ti->Length()-1) Ti = new (TColStd_HArray1OfReal) (1, n+1);
264     myCurves->ChangeValue(ii).Intervals(Ti->ChangeArray1(), S);
265     InvPrepare(ii, f, delta);
266     F = myKnots->Value(ii);
267     if (delta < 0) {
268       // invert the direction of parcing
269       for (jj=Ti->Length()-1; jj>0; kk++, jj--)
270         T(kk) = F + (Ti->Value(jj)-f)*delta;
271     }
272     else {
273       for (jj=2; jj<=Ti->Length(); kk++, jj++)
274         T(kk) = F + (Ti->Value(jj)-f)*delta;
275     }
276   }
277 }
278
279  Handle(Adaptor3d_HCurve) BRepAdaptor_CompCurve::Trim(const Standard_Real First,
280                                                     const Standard_Real Last,
281                                                     const Standard_Real Tol) const
282 {
283   BRepAdaptor_CompCurve C(myWire, IsbyAC, First, Last, Tol);
284   Handle(BRepAdaptor_HCompCurve) HC =
285     new (BRepAdaptor_HCompCurve) (C);
286   return HC;
287 }
288
289  Standard_Boolean BRepAdaptor_CompCurve::IsClosed() const
290 {
291   return myWire.Closed();
292 }
293
294  Standard_Boolean BRepAdaptor_CompCurve::IsPeriodic() const
295 {
296   return Periodic;
297
298 }
299
300  Standard_Real BRepAdaptor_CompCurve::Period() const
301 {
302   return myPeriod;
303 }
304
305  gp_Pnt BRepAdaptor_CompCurve::Value(const Standard_Real U) const
306 {
307   Standard_Real u = U, d;
308   Standard_Integer index = CurIndex;
309   Prepare(u, d, index);
310   return myCurves->Value(index).Value(u);
311 }
312
313  void BRepAdaptor_CompCurve::D0(const Standard_Real U,
314                                 gp_Pnt& P) const
315 {
316   Standard_Real u = U, d;
317   Standard_Integer index = CurIndex;
318   Prepare(u, d, index);
319   myCurves->Value(index).D0(u, P);
320 }
321
322  void BRepAdaptor_CompCurve::D1(const Standard_Real U,
323                                 gp_Pnt& P,
324                                 gp_Vec& V) const
325 {
326   Standard_Real u = U, d;
327   Standard_Integer index = CurIndex;
328   Prepare(u, d, index);
329   myCurves->Value(index).D1(u, P, V);
330   V*=d;
331 }
332
333  void BRepAdaptor_CompCurve::D2(const Standard_Real U,
334                                 gp_Pnt& P,
335                                 gp_Vec& V1,
336                                 gp_Vec& V2) const
337 {
338   Standard_Real u = U, d;
339   Standard_Integer index = CurIndex;
340   Prepare(u, d, index);
341   myCurves->Value(index).D2(u, P, V1, V2);
342   V1*=d;
343   V2 *= d*d;
344 }
345
346  void BRepAdaptor_CompCurve::D3(const Standard_Real U,
347                                 gp_Pnt& P,gp_Vec& V1,
348                                 gp_Vec& V2,
349                                 gp_Vec& V3) const
350 {
351   Standard_Real u = U, d;
352   Standard_Integer index = CurIndex;
353   Prepare(u, d, index);
354   myCurves->Value(index).D3(u, P, V1, V2, V3);
355   V1*=d;
356   V2 *= d*d;
357   V3 *= d*d*d;
358 }
359
360  gp_Vec BRepAdaptor_CompCurve::DN(const Standard_Real U,
361                                   const Standard_Integer N) const
362 {
363   Standard_Real u = U, d;
364   Standard_Integer index = CurIndex;
365   Prepare(u, d, index);
366
367   return (myCurves->Value(index).DN(u, N) * Pow(d, N));
368 }
369
370  Standard_Real BRepAdaptor_CompCurve::Resolution(const Standard_Real R3d) const
371 {
372   Standard_Real Res = 1.e200, r;
373   Standard_Integer ii, L = myCurves->Length();
374   for (ii=1; ii<=L; ii++) {
375     r = myCurves->Value(ii).Resolution(R3d);
376     if (r < Res) Res = r;
377   }
378   return Res;
379 }
380
381  GeomAbs_CurveType BRepAdaptor_CompCurve::GetType() const
382 {
383   return GeomAbs_OtherCurve; //temporary
384 //  if ( myCurves->Length() > 1) return GeomAbs_OtherCurve;
385 //  return myCurves->Value(1).GetType();
386 }
387
388  gp_Lin BRepAdaptor_CompCurve::Line() const
389 {
390   return myCurves->Value(1).Line();
391 }
392
393  gp_Circ BRepAdaptor_CompCurve::Circle() const
394 {
395   return myCurves->Value(1).Circle();
396 }
397
398  gp_Elips BRepAdaptor_CompCurve::Ellipse() const
399 {
400   return myCurves->Value(1).Ellipse();
401 }
402
403  gp_Hypr BRepAdaptor_CompCurve::Hyperbola() const
404 {
405   return myCurves->Value(1).Hyperbola();
406 }
407
408  gp_Parab BRepAdaptor_CompCurve::Parabola() const
409 {
410   return myCurves->Value(1).Parabola();
411 }
412
413  Standard_Integer BRepAdaptor_CompCurve::Degree() const
414 {
415   return myCurves->Value(1).Degree();
416 }
417
418  Standard_Boolean BRepAdaptor_CompCurve::IsRational() const
419 {
420   return myCurves->Value(1).IsRational();
421 }
422
423  Standard_Integer BRepAdaptor_CompCurve::NbPoles() const
424 {
425   return myCurves->Value(1).NbPoles();
426 }
427
428  Standard_Integer BRepAdaptor_CompCurve::NbKnots() const
429 {
430   return myCurves->Value(1).NbKnots();
431 }
432
433  Handle(Geom_BezierCurve) BRepAdaptor_CompCurve::Bezier() const
434 {
435   return myCurves->Value(1).Bezier();
436 }
437
438  Handle(Geom_BSplineCurve) BRepAdaptor_CompCurve::BSpline() const
439 {
440   return myCurves->Value(1).BSpline();
441 }
442
443 //=======================================================================
444 //function : Prepare
445 //purpose  :
446 // When the parameter is close to "node" the rule is determined
447 // depending on the sign of tol:
448 //   - negative -> Rule preceding to the node.
449 //   - positive -> Rule following after the node.
450 //=======================================================================
451
452  void BRepAdaptor_CompCurve::Prepare(Standard_Real& W,
453                                      Standard_Real& Delta,
454                                      Standard_Integer& theCurIndex) const
455 {
456   Standard_Real f,l, Wtest, Eps;
457   Standard_Integer ii;
458   if (W-TFirst < TLast-W) { Eps = PTol; }
459   else                    { Eps = -PTol;}
460
461
462   Wtest = W+Eps; //Offset to discriminate the nodes
463   if(Periodic){
464     Wtest = ElCLib::InPeriod(Wtest,
465                              0,
466                              myPeriod);
467     W = Wtest-Eps;
468   }
469
470   // Find the index
471   Standard_Boolean Trouve = Standard_False;
472   if (myKnots->Value(theCurIndex) > Wtest) {
473     for (ii=theCurIndex-1; ii>0 && !Trouve; ii--)
474       if (myKnots->Value(ii)<= Wtest) {
475         theCurIndex = ii;
476         Trouve = Standard_True;
477       }
478     if (!Trouve) theCurIndex = 1; // Out of limits...
479   }
480
481   else if (myKnots->Value(theCurIndex+1) <= Wtest) {
482     for (ii=theCurIndex+1; ii<=myCurves->Length() && !Trouve; ii++)
483       if (myKnots->Value(ii+1)> Wtest) {
484         theCurIndex = ii;
485         Trouve = Standard_True;
486       }
487     if (!Trouve) theCurIndex = myCurves->Length(); // Out of limits...
488   }
489
490   // Invert ?
491   const TopoDS_Edge& E = myCurves->Value(theCurIndex).Edge();
492   TopAbs_Orientation Or = E.Orientation();
493   Standard_Boolean Reverse;
494   Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
495             (!Forward && (Or != TopAbs_REVERSED));
496
497   // Calculate the local parameter
498   BRep_Tool::Range(E, f, l);
499   Delta = myKnots->Value(theCurIndex+1) - myKnots->Value(theCurIndex);
500   if (Delta > PTol*1.e-9) Delta = (l-f)/Delta;
501
502   if (Reverse) {
503     Delta *= -1;
504     W = l + (W-myKnots->Value(theCurIndex)) * Delta;
505   }
506   else {
507     W = f + (W-myKnots->Value(theCurIndex)) * Delta;
508   }
509 }
510
511 void  BRepAdaptor_CompCurve::InvPrepare(const Standard_Integer index,
512                                         Standard_Real& First,
513                                         Standard_Real& Delta) const
514 {
515   // Invert?
516   const TopoDS_Edge& E = myCurves->Value(index).Edge();
517   TopAbs_Orientation Or = E.Orientation();
518   Standard_Boolean Reverse;
519   Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
520             (!Forward && (Or != TopAbs_REVERSED));
521
522   // Calculate the parameters of reparametrisation
523   // such as : T = Ti + (t-First)*Delta
524   Standard_Real f, l;
525   BRep_Tool::Range(E, f, l);
526   Delta = myKnots->Value(index+1) - myKnots->Value(index);
527   if (l-f > PTol*1.e-9) Delta /= (l-f);
528
529   if (Reverse) {
530     Delta *= -1;
531     First = l;
532   }
533   else {
534     First = f;
535   }
536 }