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