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