0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / BRepAdaptor / BRepAdaptor_CompCurve.cxx
... / ...
CommitLineData
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
45BRepAdaptor_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
57BRepAdaptor_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
72BRepAdaptor_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
204void BRepAdaptor_CompCurve::SetPeriodic(const Standard_Boolean isPeriodic)
205{
206 if (myWire.Closed()) {
207 Periodic = isPeriodic;
208 }
209}
210
211
212const 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
526void 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}