0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[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
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17
42cf5bc1 18#include <Adaptor3d_HCurve.hxx>
19#include <BRep_Tool.hxx>
20#include <BRepAdaptor_CompCurve.hxx>
7fd59977 21#include <BRepAdaptor_Curve.hxx>
7fd59977 22#include <BRepAdaptor_HCompCurve.hxx>
42cf5bc1 23#include <BRepAdaptor_HCurve.hxx>
7fd59977 24#include <BRepTools_WireExplorer.hxx>
7fd59977 25#include <ElCLib.hxx>
42cf5bc1 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>
7fd59977 41#include <TopExp.hxx>
42cf5bc1 42#include <TopoDS_Edge.hxx>
43#include <TopoDS_Wire.hxx>
7fd59977 44
45BRepAdaptor_CompCurve::BRepAdaptor_CompCurve()
cbff1e55 46: TFirst (0.0),
47 TLast (0.0),
48 PTol (0.0),
cbff1e55 49 CurIndex(-1),
50 Forward (Standard_False),
f24150b8 51 IsbyAC (Standard_False)
7fd59977 52{
53}
54
cbff1e55 55BRepAdaptor_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),
cbff1e55 61 CurIndex(-1),
62 Forward (Standard_False),
f24150b8 63 IsbyAC (theIsAC)
7fd59977 64{
cbff1e55 65 Initialize(theWire, theIsAC);
7fd59977 66}
67
cbff1e55 68BRepAdaptor_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),
cbff1e55 77 CurIndex(-1),
78 Forward (Standard_False),
f24150b8 79 IsbyAC (theIsAC)
7fd59977 80{
cbff1e55 81 Initialize(theWire, theIsAC, theFirst, theLast, theTolerance);
7fd59977 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
0d969553 121 Forward = Standard_True; // Defaut ; The Reverse Edges are parsed.
7fd59977 122 if((NbEdge > 2) || ((NbEdge==2) && (!myWire.Closed())) ) {
123 TopAbs_Orientation Or = myCurves->Value(1).Edge().Orientation();
7fd59977 124 TopoDS_Vertex VI, VL;
96a95605 125 TopExp::CommonVertex(myCurves->Value(1).Edge(),
7fd59977 126 myCurves->Value(2).Edge(),
127 VI);
128 VL = TopExp::LastVertex(myCurves->Value(1).Edge());
0d969553 129 if (VI.IsSame(VL)) { // The direction of parsing is always preserved
7fd59977 130 if (Or == TopAbs_REVERSED)
131 Forward = Standard_False;
132 }
0d969553 133 else {// The direction of parsing is always reversed
7fd59977 134 if (Or != TopAbs_REVERSED)
135 Forward = Standard_False;
136 }
137 }
138
139 TFirst = 0;
140 TLast = myKnots->Value(myKnots->Length());
7fd59977 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
0d969553 154 // Trim the extremal curves.
7fd59977 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);
0d969553 161 CurIndex = (i1+i2)/2; // Small optimization
7fd59977 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
7fd59977 190const 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
31b1749c 222 Standard_Integer BRepAdaptor_CompCurve::NbIntervals(const GeomAbs_Shape S) const
7fd59977 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,
31b1749c 232 const GeomAbs_Shape S) const
7fd59977 233{
234 Standard_Integer ii, jj, kk, n;
235 Standard_Real f, F, delta;
236
0d969553 237 // First curve (direction of parsing of the edge)
7fd59977 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) {
0d969553 244 // invert the direction of parsing
7fd59977 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
0d969553 253 // and the next
7fd59977 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) {
0d969553 261 // invert the direction of parcing
7fd59977 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{
f24150b8 289 return Standard_False;
7fd59977 290
291}
292
293 Standard_Real BRepAdaptor_CompCurve::Period() const
294{
f24150b8 295 return (TLast - TFirst);
7fd59977 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{
0d969553 376 return GeomAbs_OtherCurve; //temporary
7fd59977 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 :
0d969553
Y
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.
7fd59977 443//=======================================================================
444
445 void BRepAdaptor_CompCurve::Prepare(Standard_Real& W,
446 Standard_Real& Delta,
75259fc5 447 Standard_Integer& theCurIndex) const
7fd59977 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
0d969553 455 Wtest = W+Eps; //Offset to discriminate the nodes
7fd59977 456
0d969553 457 // Find the index
7fd59977 458 Standard_Boolean Trouve = Standard_False;
75259fc5 459 if (myKnots->Value(theCurIndex) > Wtest) {
460 for (ii=theCurIndex-1; ii>0 && !Trouve; ii--)
7fd59977 461 if (myKnots->Value(ii)<= Wtest) {
75259fc5 462 theCurIndex = ii;
7fd59977 463 Trouve = Standard_True;
464 }
75259fc5 465 if (!Trouve) theCurIndex = 1; // Out of limits...
7fd59977 466 }
467
75259fc5 468 else if (myKnots->Value(theCurIndex+1) <= Wtest) {
469 for (ii=theCurIndex+1; ii<=myCurves->Length() && !Trouve; ii++)
7fd59977 470 if (myKnots->Value(ii+1)> Wtest) {
75259fc5 471 theCurIndex = ii;
7fd59977 472 Trouve = Standard_True;
473 }
75259fc5 474 if (!Trouve) theCurIndex = myCurves->Length(); // Out of limits...
7fd59977 475 }
476
0d969553 477 // Invert ?
75259fc5 478 const TopoDS_Edge& E = myCurves->Value(theCurIndex).Edge();
7fd59977 479 TopAbs_Orientation Or = E.Orientation();
480 Standard_Boolean Reverse;
481 Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
482 (!Forward && (Or != TopAbs_REVERSED));
483
0d969553 484 // Calculate the local parameter
7fd59977 485 BRep_Tool::Range(E, f, l);
75259fc5 486 Delta = myKnots->Value(theCurIndex+1) - myKnots->Value(theCurIndex);
7fd59977 487 if (Delta > PTol*1.e-9) Delta = (l-f)/Delta;
488
489 if (Reverse) {
490 Delta *= -1;
75259fc5 491 W = l + (W-myKnots->Value(theCurIndex)) * Delta;
7fd59977 492 }
493 else {
75259fc5 494 W = f + (W-myKnots->Value(theCurIndex)) * Delta;
7fd59977 495 }
496}
497
498void BRepAdaptor_CompCurve::InvPrepare(const Standard_Integer index,
499 Standard_Real& First,
500 Standard_Real& Delta) const
501{
0d969553 502 // Invert?
7fd59977 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
0d969553
Y
509 // Calculate the parameters of reparametrisation
510 // such as : T = Ti + (t-First)*Delta
7fd59977 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}