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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepAdaptor_CompCurve.ixx>
19 #include <BRepAdaptor_Curve.hxx>
20 #include <BRepAdaptor_HCurve.hxx>
21 #include <BRepAdaptor_HCompCurve.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepTools_WireExplorer.hxx>
24 #include <TopAbs_Orientation.hxx>
26 #include <GCPnts_AbscissaPoint.hxx>
30 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve()
36 Forward (Standard_False),
37 IsbyAC (Standard_False),
38 Periodic(Standard_False)
42 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire& theWire,
43 const Standard_Boolean theIsAC)
50 Forward (Standard_False),
52 Periodic(Standard_False)
54 Initialize(theWire, theIsAC);
57 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire& theWire,
58 const Standard_Boolean theIsAC,
59 const Standard_Real theFirst,
60 const Standard_Real theLast,
61 const Standard_Real theTolerance)
68 Forward (Standard_False),
70 Periodic(Standard_False)
72 Initialize(theWire, theIsAC, theFirst, theLast, theTolerance);
75 void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
76 const Standard_Boolean AC)
78 Standard_Integer ii, NbEdge;
79 BRepTools_WireExplorer wexp;
86 for (NbEdge=0, wexp.Init(myWire);
87 wexp.More(); wexp.Next())
88 if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
90 if (NbEdge == 0) return;
92 CurIndex = (NbEdge+1)/2;
93 myCurves = new (BRepAdaptor_HArray1OfCurve) (1,NbEdge);
94 myKnots = new (TColStd_HArray1OfReal) (1,NbEdge+1);
95 myKnots->SetValue(1, 0.);
97 for (ii=0, wexp.Init(myWire);
98 wexp.More(); wexp.Next()) {
100 if (! BRep_Tool::Degenerated(E)) {
102 myCurves->ChangeValue(ii).Initialize(E);
104 myKnots->SetValue(ii+1, myKnots->Value(ii));
105 myKnots->ChangeValue(ii+1) +=
106 GCPnts_AbscissaPoint::Length(myCurves->ChangeValue(ii));
108 else myKnots->SetValue(ii+1, (Standard_Real)ii);
112 Forward = Standard_True; // Defaut ; The Reverse Edges are parsed.
113 if((NbEdge > 2) || ((NbEdge==2) && (!myWire.Closed())) ) {
114 TopAbs_Orientation Or = myCurves->Value(1).Edge().Orientation();
115 TopoDS_Vertex VI, VL;
116 TopExp::CommonVertex(myCurves->Value(1).Edge(),
117 myCurves->Value(2).Edge(),
119 VL = TopExp::LastVertex(myCurves->Value(1).Edge());
120 if (VI.IsSame(VL)) { // The direction of parsing is always preserved
121 if (Or == TopAbs_REVERSED)
122 Forward = Standard_False;
124 else {// The direction of parsing is always reversed
125 if (Or != TopAbs_REVERSED)
126 Forward = Standard_False;
131 TLast = myKnots->Value(myKnots->Length());
132 myPeriod = TLast - TFirst;
134 Periodic = myCurves->Value(1).IsPeriodic();
137 Periodic = Standard_False;
141 void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
142 const Standard_Boolean AC,
143 const Standard_Real First,
144 const Standard_Real Last,
145 const Standard_Real Tol)
152 // Trim the extremal curves.
153 Handle (BRepAdaptor_HCurve) HC;
154 Standard_Integer i1, i2;
155 Standard_Real f=TFirst, l=TLast, d;
159 CurIndex = (i1+i2)/2; // Small optimization
162 HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(f, l, PTol));
164 HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(l, f, PTol));
165 myCurves->SetValue(i1, HC->ChangeCurve());
168 const BRepAdaptor_Curve& c1 = myCurves->Value(i1);
169 const BRepAdaptor_Curve& c2 = myCurves->Value(i2);
172 k = c1.LastParameter();
174 HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(f, k, PTol));
176 HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(k, f, PTol));
177 myCurves->SetValue(i1, HC->ChangeCurve());
179 k = c2.FirstParameter();
181 HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(k, l, PTol));
183 HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(l, k, PTol));
184 myCurves->SetValue(i2, HC->ChangeCurve());
189 void BRepAdaptor_CompCurve::SetPeriodic(const Standard_Boolean isPeriodic)
191 if (myWire.Closed()) {
192 Periodic = isPeriodic;
197 const TopoDS_Wire& BRepAdaptor_CompCurve::Wire() const
202 void BRepAdaptor_CompCurve::Edge(const Standard_Real U,
204 Standard_Real& UonE) const
207 Standard_Integer index = CurIndex;
209 Prepare(UonE, d, index);
210 E = myCurves->Value(index).Edge();
213 Standard_Real BRepAdaptor_CompCurve::FirstParameter() const
218 Standard_Real BRepAdaptor_CompCurve::LastParameter() const
223 GeomAbs_Shape BRepAdaptor_CompCurve::Continuity() const
225 if ( myCurves->Length() > 1) return GeomAbs_C0;
226 return myCurves->Value(1).Continuity();
229 Standard_Integer BRepAdaptor_CompCurve::NbIntervals(const GeomAbs_Shape S)
231 Standard_Integer NbInt, ii;
232 for (ii=1, NbInt=0; ii<=myCurves->Length(); ii++)
233 NbInt += myCurves->ChangeValue(ii).NbIntervals(S);
238 void BRepAdaptor_CompCurve::Intervals(TColStd_Array1OfReal& T,
239 const GeomAbs_Shape S)
241 Standard_Integer ii, jj, kk, n;
242 Standard_Real f, F, delta;
244 // First curve (direction of parsing of the edge)
245 n = myCurves->ChangeValue(1).NbIntervals(S);
246 Handle(TColStd_HArray1OfReal) Ti = new (TColStd_HArray1OfReal) (1, n+1);
247 myCurves->ChangeValue(1).Intervals(Ti->ChangeArray1(), S);
248 InvPrepare(1, f, delta);
249 F = myKnots->Value(1);
251 // invert the direction of parsing
252 for (kk=1,jj=Ti->Length(); jj>0; kk++, jj--)
253 T(kk) = F + (Ti->Value(jj)-f)*delta;
256 for (kk=1; kk<=Ti->Length(); kk++)
257 T(kk) = F + (Ti->Value(kk)-f)*delta;
261 for (ii=2; ii<=myCurves->Length(); ii++) {
262 n = myCurves->ChangeValue(ii).NbIntervals(S);
263 if (n != Ti->Length()-1) Ti = new (TColStd_HArray1OfReal) (1, n+1);
264 myCurves->ChangeValue(ii).Intervals(Ti->ChangeArray1(), S);
265 InvPrepare(ii, f, delta);
266 F = myKnots->Value(ii);
268 // invert the direction of parcing
269 for (jj=Ti->Length()-1; jj>0; kk++, jj--)
270 T(kk) = F + (Ti->Value(jj)-f)*delta;
273 for (jj=2; jj<=Ti->Length(); kk++, jj++)
274 T(kk) = F + (Ti->Value(jj)-f)*delta;
279 Handle(Adaptor3d_HCurve) BRepAdaptor_CompCurve::Trim(const Standard_Real First,
280 const Standard_Real Last,
281 const Standard_Real Tol) const
283 BRepAdaptor_CompCurve C(myWire, IsbyAC, First, Last, Tol);
284 Handle(BRepAdaptor_HCompCurve) HC =
285 new (BRepAdaptor_HCompCurve) (C);
289 Standard_Boolean BRepAdaptor_CompCurve::IsClosed() const
291 return myWire.Closed();
294 Standard_Boolean BRepAdaptor_CompCurve::IsPeriodic() const
300 Standard_Real BRepAdaptor_CompCurve::Period() const
305 gp_Pnt BRepAdaptor_CompCurve::Value(const Standard_Real U) const
307 Standard_Real u = U, d;
308 Standard_Integer index = CurIndex;
309 Prepare(u, d, index);
310 return myCurves->Value(index).Value(u);
313 void BRepAdaptor_CompCurve::D0(const Standard_Real U,
316 Standard_Real u = U, d;
317 Standard_Integer index = CurIndex;
318 Prepare(u, d, index);
319 myCurves->Value(index).D0(u, P);
322 void BRepAdaptor_CompCurve::D1(const Standard_Real U,
326 Standard_Real u = U, d;
327 Standard_Integer index = CurIndex;
328 Prepare(u, d, index);
329 myCurves->Value(index).D1(u, P, V);
333 void BRepAdaptor_CompCurve::D2(const Standard_Real U,
338 Standard_Real u = U, d;
339 Standard_Integer index = CurIndex;
340 Prepare(u, d, index);
341 myCurves->Value(index).D2(u, P, V1, V2);
346 void BRepAdaptor_CompCurve::D3(const Standard_Real U,
347 gp_Pnt& P,gp_Vec& V1,
351 Standard_Real u = U, d;
352 Standard_Integer index = CurIndex;
353 Prepare(u, d, index);
354 myCurves->Value(index).D3(u, P, V1, V2, V3);
360 gp_Vec BRepAdaptor_CompCurve::DN(const Standard_Real U,
361 const Standard_Integer N) const
363 Standard_Real u = U, d;
364 Standard_Integer index = CurIndex;
365 Prepare(u, d, index);
367 return (myCurves->Value(index).DN(u, N) * Pow(d, N));
370 Standard_Real BRepAdaptor_CompCurve::Resolution(const Standard_Real R3d) const
372 Standard_Real Res = 1.e200, r;
373 Standard_Integer ii, L = myCurves->Length();
374 for (ii=1; ii<=L; ii++) {
375 r = myCurves->Value(ii).Resolution(R3d);
376 if (r < Res) Res = r;
381 GeomAbs_CurveType BRepAdaptor_CompCurve::GetType() const
383 return GeomAbs_OtherCurve; //temporary
384 // if ( myCurves->Length() > 1) return GeomAbs_OtherCurve;
385 // return myCurves->Value(1).GetType();
388 gp_Lin BRepAdaptor_CompCurve::Line() const
390 return myCurves->Value(1).Line();
393 gp_Circ BRepAdaptor_CompCurve::Circle() const
395 return myCurves->Value(1).Circle();
398 gp_Elips BRepAdaptor_CompCurve::Ellipse() const
400 return myCurves->Value(1).Ellipse();
403 gp_Hypr BRepAdaptor_CompCurve::Hyperbola() const
405 return myCurves->Value(1).Hyperbola();
408 gp_Parab BRepAdaptor_CompCurve::Parabola() const
410 return myCurves->Value(1).Parabola();
413 Standard_Integer BRepAdaptor_CompCurve::Degree() const
415 return myCurves->Value(1).Degree();
418 Standard_Boolean BRepAdaptor_CompCurve::IsRational() const
420 return myCurves->Value(1).IsRational();
423 Standard_Integer BRepAdaptor_CompCurve::NbPoles() const
425 return myCurves->Value(1).NbPoles();
428 Standard_Integer BRepAdaptor_CompCurve::NbKnots() const
430 return myCurves->Value(1).NbKnots();
433 Handle(Geom_BezierCurve) BRepAdaptor_CompCurve::Bezier() const
435 return myCurves->Value(1).Bezier();
438 Handle(Geom_BSplineCurve) BRepAdaptor_CompCurve::BSpline() const
440 return myCurves->Value(1).BSpline();
443 //=======================================================================
446 // When the parameter is close to "node" the rule is determined
447 // depending on the sign of tol:
448 // - negative -> Rule preceding to the node.
449 // - positive -> Rule following after the node.
450 //=======================================================================
452 void BRepAdaptor_CompCurve::Prepare(Standard_Real& W,
453 Standard_Real& Delta,
454 Standard_Integer& theCurIndex) const
456 Standard_Real f,l, Wtest, Eps;
458 if (W-TFirst < TLast-W) { Eps = PTol; }
462 Wtest = W+Eps; //Offset to discriminate the nodes
464 Wtest = ElCLib::InPeriod(Wtest,
471 Standard_Boolean Trouve = Standard_False;
472 if (myKnots->Value(theCurIndex) > Wtest) {
473 for (ii=theCurIndex-1; ii>0 && !Trouve; ii--)
474 if (myKnots->Value(ii)<= Wtest) {
476 Trouve = Standard_True;
478 if (!Trouve) theCurIndex = 1; // Out of limits...
481 else if (myKnots->Value(theCurIndex+1) <= Wtest) {
482 for (ii=theCurIndex+1; ii<=myCurves->Length() && !Trouve; ii++)
483 if (myKnots->Value(ii+1)> Wtest) {
485 Trouve = Standard_True;
487 if (!Trouve) theCurIndex = myCurves->Length(); // Out of limits...
491 const TopoDS_Edge& E = myCurves->Value(theCurIndex).Edge();
492 TopAbs_Orientation Or = E.Orientation();
493 Standard_Boolean Reverse;
494 Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
495 (!Forward && (Or != TopAbs_REVERSED));
497 // Calculate the local parameter
498 BRep_Tool::Range(E, f, l);
499 Delta = myKnots->Value(theCurIndex+1) - myKnots->Value(theCurIndex);
500 if (Delta > PTol*1.e-9) Delta = (l-f)/Delta;
504 W = l + (W-myKnots->Value(theCurIndex)) * Delta;
507 W = f + (W-myKnots->Value(theCurIndex)) * Delta;
511 void BRepAdaptor_CompCurve::InvPrepare(const Standard_Integer index,
512 Standard_Real& First,
513 Standard_Real& Delta) const
516 const TopoDS_Edge& E = myCurves->Value(index).Edge();
517 TopAbs_Orientation Or = E.Orientation();
518 Standard_Boolean Reverse;
519 Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
520 (!Forward && (Or != TopAbs_REVERSED));
522 // Calculate the parameters of reparametrisation
523 // such as : T = Ti + (t-First)*Delta
525 BRep_Tool::Range(E, f, l);
526 Delta = myKnots->Value(index+1) - myKnots->Value(index);
527 if (l-f > PTol*1.e-9) Delta /= (l-f);