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.
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>
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>
33 #include <gp_Parab.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>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Wire.hxx>
45 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve()
50 Forward (Standard_False),
51 IsbyAC (Standard_False)
55 BRepAdaptor_CompCurve::BRepAdaptor_CompCurve(const TopoDS_Wire& theWire,
56 const Standard_Boolean theIsAC)
62 Forward (Standard_False),
65 Initialize(theWire, theIsAC);
68 BRepAdaptor_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)
78 Forward (Standard_False),
81 Initialize(theWire, theIsAC, theFirst, theLast, theTolerance);
84 void BRepAdaptor_CompCurve::Initialize(const TopoDS_Wire& W,
85 const Standard_Boolean AC)
87 Standard_Integer ii, NbEdge;
88 BRepTools_WireExplorer wexp;
95 for (NbEdge=0, wexp.Init(myWire);
96 wexp.More(); wexp.Next())
97 if (! BRep_Tool::Degenerated(wexp.Current())) NbEdge++;
99 if (NbEdge == 0) return;
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.);
106 for (ii=0, wexp.Init(myWire);
107 wexp.More(); wexp.Next()) {
109 if (! BRep_Tool::Degenerated(E)) {
111 myCurves->ChangeValue(ii).Initialize(E);
113 myKnots->SetValue(ii+1, myKnots->Value(ii));
114 myKnots->ChangeValue(ii+1) +=
115 GCPnts_AbscissaPoint::Length(myCurves->ChangeValue(ii));
117 else myKnots->SetValue(ii+1, (Standard_Real)ii);
121 Forward = Standard_True; // Defaut ; The Reverse Edges are parsed.
122 if((NbEdge > 2) || ((NbEdge==2) && (!myWire.Closed())) ) {
123 TopAbs_Orientation Or = myCurves->Value(1).Edge().Orientation();
124 TopoDS_Vertex VI, VL;
125 TopExp::CommonVertex(myCurves->Value(1).Edge(),
126 myCurves->Value(2).Edge(),
128 VL = TopExp::LastVertex(myCurves->Value(1).Edge());
129 if (VI.IsSame(VL)) { // The direction of parsing is always preserved
130 if (Or == TopAbs_REVERSED)
131 Forward = Standard_False;
133 else {// The direction of parsing is always reversed
134 if (Or != TopAbs_REVERSED)
135 Forward = Standard_False;
140 TLast = myKnots->Value(myKnots->Length());
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)
154 // Trim the extremal curves.
155 Handle (BRepAdaptor_HCurve) HC;
156 Standard_Integer i1, i2;
157 Standard_Real f=TFirst, l=TLast, d;
161 CurIndex = (i1+i2)/2; // Small optimization
164 HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(f, l, PTol));
166 HC = Handle(BRepAdaptor_HCurve)::DownCast(myCurves->Value(i1).Trim(l, f, PTol));
167 myCurves->SetValue(i1, HC->ChangeCurve());
170 const BRepAdaptor_Curve& c1 = myCurves->Value(i1);
171 const BRepAdaptor_Curve& c2 = myCurves->Value(i2);
174 k = c1.LastParameter();
176 HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(f, k, PTol));
178 HC = Handle(BRepAdaptor_HCurve)::DownCast(c1.Trim(k, f, PTol));
179 myCurves->SetValue(i1, HC->ChangeCurve());
181 k = c2.FirstParameter();
183 HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(k, l, PTol));
185 HC = Handle(BRepAdaptor_HCurve)::DownCast(c2.Trim(l, k, PTol));
186 myCurves->SetValue(i2, HC->ChangeCurve());
190 const TopoDS_Wire& BRepAdaptor_CompCurve::Wire() const
195 void BRepAdaptor_CompCurve::Edge(const Standard_Real U,
197 Standard_Real& UonE) const
200 Standard_Integer index = CurIndex;
202 Prepare(UonE, d, index);
203 E = myCurves->Value(index).Edge();
206 Standard_Real BRepAdaptor_CompCurve::FirstParameter() const
211 Standard_Real BRepAdaptor_CompCurve::LastParameter() const
216 GeomAbs_Shape BRepAdaptor_CompCurve::Continuity() const
218 if ( myCurves->Length() > 1) return GeomAbs_C0;
219 return myCurves->Value(1).Continuity();
222 Standard_Integer BRepAdaptor_CompCurve::NbIntervals(const GeomAbs_Shape S) const
224 Standard_Integer NbInt, ii;
225 for (ii=1, NbInt=0; ii<=myCurves->Length(); ii++)
226 NbInt += myCurves->ChangeValue(ii).NbIntervals(S);
231 void BRepAdaptor_CompCurve::Intervals(TColStd_Array1OfReal& T,
232 const GeomAbs_Shape S) const
234 Standard_Integer ii, jj, kk, n;
235 Standard_Real f, F, delta;
237 // First curve (direction of parsing of the edge)
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);
244 // invert the direction of parsing
245 for (kk=1,jj=Ti->Length(); jj>0; kk++, jj--)
246 T(kk) = F + (Ti->Value(jj)-f)*delta;
249 for (kk=1; kk<=Ti->Length(); kk++)
250 T(kk) = F + (Ti->Value(kk)-f)*delta;
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);
261 // invert the direction of parcing
262 for (jj=Ti->Length()-1; jj>0; kk++, jj--)
263 T(kk) = F + (Ti->Value(jj)-f)*delta;
266 for (jj=2; jj<=Ti->Length(); kk++, jj++)
267 T(kk) = F + (Ti->Value(jj)-f)*delta;
272 Handle(Adaptor3d_HCurve) BRepAdaptor_CompCurve::Trim(const Standard_Real First,
273 const Standard_Real Last,
274 const Standard_Real Tol) const
276 BRepAdaptor_CompCurve C(myWire, IsbyAC, First, Last, Tol);
277 Handle(BRepAdaptor_HCompCurve) HC =
278 new (BRepAdaptor_HCompCurve) (C);
282 Standard_Boolean BRepAdaptor_CompCurve::IsClosed() const
284 return myWire.Closed();
287 Standard_Boolean BRepAdaptor_CompCurve::IsPeriodic() const
289 return Standard_False;
293 Standard_Real BRepAdaptor_CompCurve::Period() const
295 return (TLast - TFirst);
298 gp_Pnt BRepAdaptor_CompCurve::Value(const Standard_Real U) const
300 Standard_Real u = U, d;
301 Standard_Integer index = CurIndex;
302 Prepare(u, d, index);
303 return myCurves->Value(index).Value(u);
306 void BRepAdaptor_CompCurve::D0(const Standard_Real U,
309 Standard_Real u = U, d;
310 Standard_Integer index = CurIndex;
311 Prepare(u, d, index);
312 myCurves->Value(index).D0(u, P);
315 void BRepAdaptor_CompCurve::D1(const Standard_Real U,
319 Standard_Real u = U, d;
320 Standard_Integer index = CurIndex;
321 Prepare(u, d, index);
322 myCurves->Value(index).D1(u, P, V);
326 void BRepAdaptor_CompCurve::D2(const Standard_Real U,
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);
339 void BRepAdaptor_CompCurve::D3(const Standard_Real U,
340 gp_Pnt& P,gp_Vec& V1,
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);
353 gp_Vec BRepAdaptor_CompCurve::DN(const Standard_Real U,
354 const Standard_Integer N) const
356 Standard_Real u = U, d;
357 Standard_Integer index = CurIndex;
358 Prepare(u, d, index);
360 return (myCurves->Value(index).DN(u, N) * Pow(d, N));
363 Standard_Real BRepAdaptor_CompCurve::Resolution(const Standard_Real R3d) const
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;
374 GeomAbs_CurveType BRepAdaptor_CompCurve::GetType() const
376 return GeomAbs_OtherCurve; //temporary
377 // if ( myCurves->Length() > 1) return GeomAbs_OtherCurve;
378 // return myCurves->Value(1).GetType();
381 gp_Lin BRepAdaptor_CompCurve::Line() const
383 return myCurves->Value(1).Line();
386 gp_Circ BRepAdaptor_CompCurve::Circle() const
388 return myCurves->Value(1).Circle();
391 gp_Elips BRepAdaptor_CompCurve::Ellipse() const
393 return myCurves->Value(1).Ellipse();
396 gp_Hypr BRepAdaptor_CompCurve::Hyperbola() const
398 return myCurves->Value(1).Hyperbola();
401 gp_Parab BRepAdaptor_CompCurve::Parabola() const
403 return myCurves->Value(1).Parabola();
406 Standard_Integer BRepAdaptor_CompCurve::Degree() const
408 return myCurves->Value(1).Degree();
411 Standard_Boolean BRepAdaptor_CompCurve::IsRational() const
413 return myCurves->Value(1).IsRational();
416 Standard_Integer BRepAdaptor_CompCurve::NbPoles() const
418 return myCurves->Value(1).NbPoles();
421 Standard_Integer BRepAdaptor_CompCurve::NbKnots() const
423 return myCurves->Value(1).NbKnots();
426 Handle(Geom_BezierCurve) BRepAdaptor_CompCurve::Bezier() const
428 return myCurves->Value(1).Bezier();
431 Handle(Geom_BSplineCurve) BRepAdaptor_CompCurve::BSpline() const
433 return myCurves->Value(1).BSpline();
436 //=======================================================================
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.
443 //=======================================================================
445 void BRepAdaptor_CompCurve::Prepare(Standard_Real& W,
446 Standard_Real& Delta,
447 Standard_Integer& theCurIndex) const
449 Standard_Real f,l, Wtest, Eps;
451 if (W-TFirst < TLast-W) { Eps = PTol; }
455 Wtest = W+Eps; //Offset to discriminate the nodes
458 Standard_Boolean Trouve = Standard_False;
459 if (myKnots->Value(theCurIndex) > Wtest) {
460 for (ii=theCurIndex-1; ii>0 && !Trouve; ii--)
461 if (myKnots->Value(ii)<= Wtest) {
463 Trouve = Standard_True;
465 if (!Trouve) theCurIndex = 1; // Out of limits...
468 else if (myKnots->Value(theCurIndex+1) <= Wtest) {
469 for (ii=theCurIndex+1; ii<=myCurves->Length() && !Trouve; ii++)
470 if (myKnots->Value(ii+1)> Wtest) {
472 Trouve = Standard_True;
474 if (!Trouve) theCurIndex = myCurves->Length(); // Out of limits...
478 const TopoDS_Edge& E = myCurves->Value(theCurIndex).Edge();
479 TopAbs_Orientation Or = E.Orientation();
480 Standard_Boolean Reverse;
481 Reverse = (Forward && (Or == TopAbs_REVERSED)) ||
482 (!Forward && (Or != TopAbs_REVERSED));
484 // Calculate the local parameter
485 BRep_Tool::Range(E, f, l);
486 Delta = myKnots->Value(theCurIndex+1) - myKnots->Value(theCurIndex);
487 if (Delta > PTol*1.e-9) Delta = (l-f)/Delta;
491 W = l + (W-myKnots->Value(theCurIndex)) * Delta;
494 W = f + (W-myKnots->Value(theCurIndex)) * Delta;
498 void BRepAdaptor_CompCurve::InvPrepare(const Standard_Integer index,
499 Standard_Real& First,
500 Standard_Real& Delta) const
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));
509 // Calculate the parameters of reparametrisation
510 // such as : T = Ti + (t-First)*Delta
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);