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