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
9 // under the terms of the GNU Lesser General Public 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()
34 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire& W,
35 const Standard_Boolean AC)
40 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire& W,
41 const Standard_Boolean AC,
42 const Standard_Real First,
43 const Standard_Real Last,
44 const Standard_Real Tol)
46 Initialize(W, AC, First, Last, Tol);
49 void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
50 const Standard_Boolean AC)
52 Standard_Integer ii, NbEdge;
53 BRepTools_WireExplorer wexp;
60 for (NbEdge=0, wexp.Init(myWire);
61 wexp.More(); wexp.Next())
62 if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
64 if (NbEdge == 0) return;
66 CurIndex = (NbEdge+1)/2;
67 myCurves = new (BRepAdaptor_HArray1OfCurve) (1,NbEdge);
68 myKnots = new (TColStd_HArray1OfReal) (1,NbEdge+1);
69 myKnots->SetValue(1, 0.);
71 for (ii=0, wexp.Init(myWire);
72 wexp.More(); wexp.Next()) {
74 if (! BRep_Tool::Degenerated(E)) {
76 myCurves->ChangeValue(ii).Initialize(E);
78 myKnots->SetValue(ii+1, myKnots->Value(ii));
79 myKnots->ChangeValue(ii+1) +=
80 GCPnts_AbscissaPoint::Length(myCurves->ChangeValue(ii));
82 else myKnots->SetValue(ii+1, (Standard_Real)ii);
86 Forward = Standard_True; // Defaut ; The Reverse Edges are parsed.
87 if((NbEdge > 2) || ((NbEdge==2) && (!myWire.Closed())) ) {
88 TopAbs_Orientation Or = myCurves->Value(1).Edge().Orientation();
90 TopExp::CommonVertex(myCurves->Value(1).Edge(),
91 myCurves->Value(2).Edge(),
93 VL = TopExp::LastVertex(myCurves->Value(1).Edge());
94 if (VI.IsSame(VL)) { // The direction of parsing is always preserved
95 if (Or == TopAbs_REVERSED)
96 Forward = Standard_False;
98 else {// The direction of parsing is always reversed
99 if (Or != TopAbs_REVERSED)
100 Forward = Standard_False;
105 TLast = myKnots->Value(myKnots->Length());
106 myPeriod = TLast - TFirst;
108 Periodic = myCurves->Value(1).IsPeriodic();
111 Periodic = Standard_False;
115 void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
116 const Standard_Boolean AC,
117 const Standard_Real First,
118 const Standard_Real Last,
119 const Standard_Real Tol)
126 // Trim the extremal curves.
127 Handle (BRepAdaptor_HCurve) HC;
128 Standard_Integer i1, i2;
129 Standard_Real f=TFirst, l=TLast, d;
133 CurIndex = (i1+i2)/2; // Small optimization
136 HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(f, l, PTol));
138 HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(l, f, PTol));
139 myCurves->SetValue(i1, HC->ChangeCurve());
142 const BRepAdaptor_Curve& c1 = myCurves->Value(i1);
143 const BRepAdaptor_Curve& c2 = myCurves->Value(i2);
146 k = c1.LastParameter();
148 HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(f, k, PTol));
150 HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(k, f, PTol));
151 myCurves->SetValue(i1, HC->ChangeCurve());
153 k = c2.FirstParameter();
155 HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(k, l, PTol));
157 HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(l, k, PTol));
158 myCurves->SetValue(i2, HC->ChangeCurve());
163 void BRepAdaptor_CompCurve::SetPeriodic(const Standard_Boolean isPeriodic)
165 if (myWire.Closed()) {
166 Periodic = isPeriodic;
171 const TopoDS_Wire& BRepAdaptor_CompCurve::Wire() const
176 void BRepAdaptor_CompCurve::Edge(const Standard_Real U,
178 Standard_Real& UonE) const
181 Standard_Integer index = CurIndex;
183 Prepare(UonE, d, index);
184 E = myCurves->Value(index).Edge();
187 Standard_Real BRepAdaptor_CompCurve::FirstParameter() const
192 Standard_Real BRepAdaptor_CompCurve::LastParameter() const
197 GeomAbs_Shape BRepAdaptor_CompCurve::Continuity() const
199 if ( myCurves->Length() > 1) return GeomAbs_C0;
200 return myCurves->Value(1).Continuity();
203 Standard_Integer BRepAdaptor_CompCurve::NbIntervals(const GeomAbs_Shape S)
205 Standard_Integer NbInt, ii;
206 for (ii=1, NbInt=0; ii<=myCurves->Length(); ii++)
207 NbInt += myCurves->ChangeValue(ii).NbIntervals(S);
212 void BRepAdaptor_CompCurve::Intervals(TColStd_Array1OfReal& T,
213 const GeomAbs_Shape S)
215 Standard_Integer ii, jj, kk, n;
216 Standard_Real f, F, delta;
218 // First curve (direction of parsing of the edge)
219 n = myCurves->ChangeValue(1).NbIntervals(S);
220 Handle(TColStd_HArray1OfReal) Ti = new (TColStd_HArray1OfReal) (1, n+1);
221 myCurves->ChangeValue(1).Intervals(Ti->ChangeArray1(), S);
222 InvPrepare(1, f, delta);
223 F = myKnots->Value(1);
225 // invert the direction of parsing
226 for (kk=1,jj=Ti->Length(); jj>0; kk++, jj--)
227 T(kk) = F + (Ti->Value(jj)-f)*delta;
230 for (kk=1; kk<=Ti->Length(); kk++)
231 T(kk) = F + (Ti->Value(kk)-f)*delta;
235 for (ii=2; ii<=myCurves->Length(); ii++) {
236 n = myCurves->ChangeValue(ii).NbIntervals(S);
237 if (n != Ti->Length()-1) Ti = new (TColStd_HArray1OfReal) (1, n+1);
238 myCurves->ChangeValue(ii).Intervals(Ti->ChangeArray1(), S);
239 InvPrepare(ii, f, delta);
240 F = myKnots->Value(ii);
242 // invert the direction of parcing
243 for (jj=Ti->Length()-1; jj>0; kk++, jj--)
244 T(kk) = F + (Ti->Value(jj)-f)*delta;
247 for (jj=2; jj<=Ti->Length(); kk++, jj++)
248 T(kk) = F + (Ti->Value(jj)-f)*delta;
253 Handle(Adaptor3d_HCurve) BRepAdaptor_CompCurve::Trim(const Standard_Real First,
254 const Standard_Real Last,
255 const Standard_Real Tol) const
257 BRepAdaptor_CompCurve C(myWire, IsbyAC, First, Last, Tol);
258 Handle(BRepAdaptor_HCompCurve) HC =
259 new (BRepAdaptor_HCompCurve) (C);
263 Standard_Boolean BRepAdaptor_CompCurve::IsClosed() const
265 return myWire.Closed();
268 Standard_Boolean BRepAdaptor_CompCurve::IsPeriodic() const
274 Standard_Real BRepAdaptor_CompCurve::Period() const
279 gp_Pnt BRepAdaptor_CompCurve::Value(const Standard_Real U) const
281 Standard_Real u = U, d;
282 Standard_Integer index = CurIndex;
283 Prepare(u, d, index);
284 return myCurves->Value(index).Value(u);
287 void BRepAdaptor_CompCurve::D0(const Standard_Real U,
290 Standard_Real u = U, d;
291 Standard_Integer index = CurIndex;
292 Prepare(u, d, index);
293 myCurves->Value(index).D0(u, P);
296 void BRepAdaptor_CompCurve::D1(const Standard_Real U,
300 Standard_Real u = U, d;
301 Standard_Integer index = CurIndex;
302 Prepare(u, d, index);
303 myCurves->Value(index).D1(u, P, V);
307 void BRepAdaptor_CompCurve::D2(const Standard_Real U,
312 Standard_Real u = U, d;
313 Standard_Integer index = CurIndex;
314 Prepare(u, d, index);
315 myCurves->Value(index).D2(u, P, V1, V2);
320 void BRepAdaptor_CompCurve::D3(const Standard_Real U,
321 gp_Pnt& P,gp_Vec& V1,
325 Standard_Real u = U, d;
326 Standard_Integer index = CurIndex;
327 Prepare(u, d, index);
328 myCurves->Value(index).D3(u, P, V1, V2, V3);
334 gp_Vec BRepAdaptor_CompCurve::DN(const Standard_Real U,
335 const Standard_Integer N) const
337 Standard_Real u = U, d;
338 Standard_Integer index = CurIndex;
339 Prepare(u, d, index);
341 return (myCurves->Value(index).DN(u, N) * Pow(d, N));
344 Standard_Real BRepAdaptor_CompCurve::Resolution(const Standard_Real R3d) const
346 Standard_Real Res = 1.e200, r;
347 Standard_Integer ii, L = myCurves->Length();
348 for (ii=1; ii<=L; ii++) {
349 r = myCurves->Value(ii).Resolution(R3d);
350 if (r < Res) Res = r;
355 GeomAbs_CurveType BRepAdaptor_CompCurve::GetType() const
357 return GeomAbs_OtherCurve; //temporary
358 // if ( myCurves->Length() > 1) return GeomAbs_OtherCurve;
359 // return myCurves->Value(1).GetType();
362 gp_Lin BRepAdaptor_CompCurve::Line() const
364 return myCurves->Value(1).Line();
367 gp_Circ BRepAdaptor_CompCurve::Circle() const
369 return myCurves->Value(1).Circle();
372 gp_Elips BRepAdaptor_CompCurve::Ellipse() const
374 return myCurves->Value(1).Ellipse();
377 gp_Hypr BRepAdaptor_CompCurve::Hyperbola() const
379 return myCurves->Value(1).Hyperbola();
382 gp_Parab BRepAdaptor_CompCurve::Parabola() const
384 return myCurves->Value(1).Parabola();
387 Standard_Integer BRepAdaptor_CompCurve::Degree() const
389 return myCurves->Value(1).Degree();
392 Standard_Boolean BRepAdaptor_CompCurve::IsRational() const
394 return myCurves->Value(1).IsRational();
397 Standard_Integer BRepAdaptor_CompCurve::NbPoles() const
399 return myCurves->Value(1).NbPoles();
402 Standard_Integer BRepAdaptor_CompCurve::NbKnots() const
404 return myCurves->Value(1).NbKnots();
407 Handle(Geom_BezierCurve) BRepAdaptor_CompCurve::Bezier() const
409 return myCurves->Value(1).Bezier();
412 Handle(Geom_BSplineCurve) BRepAdaptor_CompCurve::BSpline() const
414 return myCurves->Value(1).BSpline();
417 //=======================================================================
420 // When the parameter is close to "node" the rule is determined
421 // depending on the sign of tol:
422 // - negative -> Rule preceding to the node.
423 // - positive -> Rule following after the node.
424 //=======================================================================
426 void BRepAdaptor_CompCurve::Prepare(Standard_Real& W,
427 Standard_Real& Delta,
428 Standard_Integer& theCurIndex) const
430 Standard_Real f,l, Wtest, Eps;
432 if (W-TFirst < TLast-W) { Eps = PTol; }
436 Wtest = W+Eps; //Offset to discriminate the nodes
438 Wtest = ElCLib::InPeriod(Wtest,
445 Standard_Boolean Trouve = Standard_False;
446 if (myKnots->Value(theCurIndex) > Wtest) {
447 for (ii=theCurIndex-1; ii>0 && !Trouve; ii--)
448 if (myKnots->Value(ii)<= Wtest) {
450 Trouve = Standard_True;
452 if (!Trouve) theCurIndex = 1; // Out of limits...
455 else if (myKnots->Value(theCurIndex+1) <= Wtest) {
456 for (ii=theCurIndex+1; ii<=myCurves->Length() && !Trouve; ii++)
457 if (myKnots->Value(ii+1)> Wtest) {
459 Trouve = Standard_True;
461 if (!Trouve) theCurIndex = myCurves->Length(); // Out of limits...
465 const TopoDS_Edge& E = myCurves->Value(theCurIndex).Edge();
466 TopAbs_Orientation Or = E.Orientation();
467 Standard_Boolean Reverse;
468 Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
469 (!Forward && (Or != TopAbs_REVERSED));
471 // Calculate the local parameter
472 BRep_Tool::Range(E, f, l);
473 Delta = myKnots->Value(theCurIndex+1) - myKnots->Value(theCurIndex);
474 if (Delta > PTol*1.e-9) Delta = (l-f)/Delta;
478 W = l + (W-myKnots->Value(theCurIndex)) * Delta;
481 W = f + (W-myKnots->Value(theCurIndex)) * Delta;
485 void BRepAdaptor_CompCurve::InvPrepare(const Standard_Integer index,
486 Standard_Real& First,
487 Standard_Real& Delta) const
490 const TopoDS_Edge& E = myCurves->Value(index).Edge();
491 TopAbs_Orientation Or = E.Orientation();
492 Standard_Boolean Reverse;
493 Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
494 (!Forward && (Or != TopAbs_REVERSED));
496 // Calculate the parameters of reparametrisation
497 // such as : T = Ti + (t-First)*Delta
499 BRep_Tool::Range(E, f, l);
500 Delta = myKnots->Value(index+1) - myKnots->Value(index);
501 if (l-f > PTol*1.e-9) Delta /= (l-f);