1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <LProp_Status.hxx>
16 #include <LProp_NotDefined.hxx>
17 #include <Standard_OutOfRange.hxx>
19 static const Standard_Real MinStep = 1.0e-7;
23 LProp_CLProps::LProp_CLProps (const Curve& C,
24 const Standard_Real U,
25 const Standard_Integer N,
26 const Standard_Real Resolution)
27 : myCurve(C), myDerOrder(N), myCN(4),
28 myLinTol(Resolution), myTangentStatus (LProp_Undecided)
30 Standard_OutOfRange_Raise_if (N < 0 || N > 3,
31 "LProp_CLProps::LProp_CLProps()");
36 LProp_CLProps::LProp_CLProps (const Curve& C, const Standard_Integer N,
37 const Standard_Real Resolution)
38 : myCurve(C), myU(RealLast()), myDerOrder(N), myCN(4),
39 myLinTol(Resolution), myTangentStatus (LProp_Undecided)
41 Standard_OutOfRange_Raise_if (N < 0 || N > 3,
42 "LProp_CLProps::LProp_CLProps()");
45 LProp_CLProps::LProp_CLProps (const Standard_Integer N,
46 const Standard_Real Resolution)
47 : myU(RealLast()), myDerOrder(N), myCN(0), myLinTol(Resolution),
48 myTangentStatus (LProp_Undecided)
50 Standard_OutOfRange_Raise_if (N < 0 || N > 3, "");
53 void LProp_CLProps::SetParameter(const Standard_Real U)
59 Tool::Value(myCurve, myU, myPnt);
62 Tool::D1(myCurve, myU, myPnt, myDerivArr[0]);
65 Tool::D2(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1]);
68 Tool::D3(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1], myDerivArr[2]);
72 myTangentStatus = LProp_Undecided;
75 void LProp_CLProps::SetCurve(const Curve& C)
78 myCN = 4; // Tool::Continuity(C); RLE
81 const Pnt& LProp_CLProps::Value () const
86 const Vec& LProp_CLProps::D1 ()
91 Tool::D1(myCurve, myU, myPnt, myDerivArr[0]);
97 const Vec& LProp_CLProps::D2 ()
102 Tool::D2(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1]);
105 return myDerivArr[1];
108 const Vec& LProp_CLProps::D3 ()
113 Tool::D3(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1], myDerivArr[2]);
116 return myDerivArr[2];
119 Standard_Boolean LProp_CLProps::IsTangentDefined ()
121 if (myTangentStatus == LProp_Undefined)
122 return Standard_False;
123 else if (myTangentStatus >= LProp_Defined)
124 return Standard_True;
126 // tangentStatus == Lprop_Undecided
127 // we have to calculate the first non null derivative
128 const Standard_Real Tol = myLinTol * myLinTol;
132 Standard_Integer Order = 0;
150 if(V.SquareMagnitude() > Tol)
152 mySignificantFirstDerivativeOrder = Order;
153 myTangentStatus = LProp_Defined;
154 return Standard_True;
155 }//if(V.SquareMagnitude() > Tol)
159 myTangentStatus = LProp_Undefined;
160 return Standard_False;
161 }// else of "if(cn >= Order)" condition
164 return Standard_False;
167 void LProp_CLProps::Tangent (Dir& D)
169 if(!IsTangentDefined())
170 throw LProp_NotDefined();
172 if(mySignificantFirstDerivativeOrder == 1)
173 D = Dir(myDerivArr[0]);
174 else if (mySignificantFirstDerivativeOrder > 1)
176 const Standard_Real DivisionFactor = 1.e-3;
177 const Standard_Real anUsupremum = Tool::LastParameter(myCurve),
178 anUinfium = Tool::FirstParameter(myCurve);
181 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
184 du = anUsupremum-anUinfium;
186 const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
188 Vec V = myDerivArr[mySignificantFirstDerivativeOrder - 1];
192 if(myU-anUinfium < aDelta)
198 Tool::Value(myCurve, Min(myU, u),P1);
199 Tool::Value(myCurve, Max(myU, u),P2);
202 Standard_Real aDirFactor = V.Dot(V1);
208 }//else if (mySignificantFirstDerivativeOrder > 1)
211 Standard_Real LProp_CLProps::Curvature ()
213 Standard_Boolean isDefined = IsTangentDefined();
214 (void)isDefined; // trick to avoid compiler warning on variable unised in Release mode; note that IsTangentDefined() must be called always
215 LProp_NotDefined_Raise_if(!isDefined,
216 "LProp_CLProps::CurvatureNotDefined()");
218 // if the first derivative is null the curvature is infinite.
219 if(mySignificantFirstDerivativeOrder > 1)
222 Standard_Real Tol = myLinTol * myLinTol;
223 Standard_Real DD1 = myDerivArr[0].SquareMagnitude();
224 Standard_Real DD2 = myDerivArr[1].SquareMagnitude();
226 // if the second derivative is null the curvature is null.
233 Standard_Real N = myDerivArr[0].CrossSquareMagnitude(myDerivArr[1]);
234 // if d[0] and d[1] are colinear the curvature is null.
235 Standard_Real t = N/(DD1*DD2);
242 myCurvature = sqrt(N) / (DD1*sqrt(DD1));
249 void LProp_CLProps::Normal (Dir& D)
251 Standard_Real c = Curvature();
252 if(c==RealLast() || Abs(c) <= myLinTol)
254 throw LProp_NotDefined("LProp_CLProps::Normal(...):"
255 "Curvature is null or infinity");
258 // we used here the following vector relation
259 // a ^ (b ^ c) = b(ac) - c(ab)
260 // Norm = d[0] ^ (d[1] ^ d[0])
262 Vec Norm = myDerivArr[1] * (myDerivArr[0] * myDerivArr[0]) - myDerivArr[0] * (myDerivArr[0] * myDerivArr[1]);
266 void LProp_CLProps::CentreOfCurvature (Pnt& P)
268 if(Abs(Curvature()) <= myLinTol)
270 throw LProp_NotDefined();
273 // we used here the following vector relation
274 // a ^ (b ^ c) = b(ac) - c(ab)
275 // Norm = d[0] ^ (d[1] ^ d[0])
277 Vec Norm = myDerivArr[1] * (myDerivArr[0] * myDerivArr[0]) - myDerivArr[0] * (myDerivArr[0] * myDerivArr[1]);
279 Norm.Divide(myCurvature);
280 P= myPnt.Translated(Norm);