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