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