0023706: Cannot project point on curve
[occt.git] / src / LProp / LProp_CLProps.gxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2012 OPEN CASCADE SAS
3//
4// The content of this file is subject to the Open CASCADE Technology Public
5// License Version 6.5 (the "License"). You may not use the content of this file
6// except in compliance with the License. Please obtain a copy of the License
7// at http://www.opencascade.org and read it completely before using this file.
8//
9// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11//
12// The Original Code and all software distributed under the License is
13// distributed on an "AS IS" basis, without warranty of any kind, and the
14// Initial Developer hereby disclaims all such warranties, including without
15// limitation, any warranties of merchantability, fitness for a particular
16// purpose or non-infringement. Please see the License for the specific terms
17// and conditions governing the rights and limitations under the License.
18
7fd59977 19#include <LProp_Status.hxx>
20#include <LProp_NotDefined.hxx>
21#include <Standard_OutOfRange.hxx>
22
32ca7a51 23static const Standard_Real MinStep = 1.0e-7;
7fd59977 24
b311480e 25
32ca7a51 26
27LProp_CLProps::LProp_CLProps (const Curve& C,
7fd59977 28 const Standard_Real U,
32ca7a51 29 const Standard_Integer N,
7fd59977 30 const Standard_Real Resolution)
32ca7a51 31 : myCurve(C), myDerOrder(N), myCN(4),
32 myLinTol(Resolution), myTangentStatus (LProp_Undecided)
7fd59977 33{
7fd59977 34 Standard_OutOfRange_Raise_if (N < 0 || N > 3,
32ca7a51 35 "LProp_CLProps::LProp_CLProps()");
36
7fd59977 37 SetParameter(U);
38}
39
32ca7a51 40LProp_CLProps::LProp_CLProps (const Curve& C, const Standard_Integer N,
41 const Standard_Real Resolution)
42 : myCurve(C), myU(RealLast()), myDerOrder(N), myCN(4),
43 myLinTol(Resolution), myTangentStatus (LProp_Undecided)
7fd59977 44{
32ca7a51 45 Standard_OutOfRange_Raise_if (N < 0 || N > 3,
46 "LProp_CLProps::LProp_CLProps()");
7fd59977 47}
48
49LProp_CLProps::LProp_CLProps (const Standard_Integer N,
50 const Standard_Real Resolution)
32ca7a51 51 : myU(RealLast()), myDerOrder(N), myCN(0), myLinTol(Resolution),
52 myTangentStatus (LProp_Undecided)
7fd59977 53{
7fd59977 54 Standard_OutOfRange_Raise_if (N < 0 || N > 3, "");
55}
56
57void LProp_CLProps::SetParameter(const Standard_Real U)
32ca7a51 58{
59 myU = U;
60 switch (myDerOrder)
61 {
7fd59977 62 case 0:
32ca7a51 63 Tool::Value(myCurve, myU, myPnt);
7fd59977 64 break;
65 case 1:
32ca7a51 66 Tool::D1(myCurve, myU, myPnt, myDerivArr[0]);
7fd59977 67 break;
68 case 2:
32ca7a51 69 Tool::D2(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1]);
7fd59977 70 break;
71 case 3:
32ca7a51 72 Tool::D3(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1], myDerivArr[2]);
7fd59977 73 break;
74 }
32ca7a51 75
76 myTangentStatus = LProp_Undecided;
7fd59977 77}
78
32ca7a51 79void LProp_CLProps::SetCurve(const Curve& C)
80{
81 myCurve = C ;
82 myCN = 4; // Tool::Continuity(C); RLE
7fd59977 83}
84
85const Pnt& LProp_CLProps::Value () const
32ca7a51 86{
87 return myPnt;
7fd59977 88}
89
90const Vec& LProp_CLProps::D1 ()
91{
32ca7a51 92 if (myDerOrder < 1)
93 {
94 myDerOrder = 1;
95 Tool::D1(myCurve, myU, myPnt, myDerivArr[0]);
7fd59977 96 }
32ca7a51 97
98 return myDerivArr[0];
7fd59977 99}
100
101const Vec& LProp_CLProps::D2 ()
102{
32ca7a51 103 if (myDerOrder < 2)
104 {
105 myDerOrder = 2;
106 Tool::D2(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1]);
7fd59977 107 }
32ca7a51 108
109 return myDerivArr[1];
7fd59977 110}
111
112const Vec& LProp_CLProps::D3 ()
113{
32ca7a51 114 if (myDerOrder < 3)
115 {
116 myDerOrder = 3;
117 Tool::D3(myCurve, myU, myPnt, myDerivArr[0], myDerivArr[1], myDerivArr[2]);
7fd59977 118 }
32ca7a51 119
120 return myDerivArr[2];
7fd59977 121}
122
123Standard_Boolean LProp_CLProps::IsTangentDefined ()
124{
32ca7a51 125 if (myTangentStatus == LProp_Undefined)
7fd59977 126 return Standard_False;
32ca7a51 127 else if (myTangentStatus >= LProp_Defined)
7fd59977 128 return Standard_True;
7fd59977 129
130 // tangentStatus == Lprop_Undecided
131 // we have to calculate the first non null derivative
32ca7a51 132 const Standard_Real Tol = myLinTol * myLinTol;
133
7fd59977 134 Vec V;
32ca7a51 135
7fd59977 136 Standard_Integer Order = 0;
32ca7a51 137 while (Order++ < 4)
138 {
139 if(myCN >= Order)
140 {
141 switch(Order)
142 {
143 case 1:
144 V = D1();
145 break;
146 case 2:
147 V = D2();
148 break;
149 case 3:
150 V = D3();
151 break;
152 }//switch(Order)
153
154 if(V.SquareMagnitude() > Tol)
155 {
156 mySignificantFirstDerivativeOrder = Order;
157 myTangentStatus = LProp_Defined;
158 return Standard_True;
159 }//if(V.SquareMagnitude() > Tol)
160 }//if(cn >= Order)
161 else
162 {
163 myTangentStatus = LProp_Undefined;
7fd59977 164 return Standard_False;
32ca7a51 165 }// else of "if(cn >= Order)" condition
166 }//while (Order < 4)
167
7fd59977 168 return Standard_False;
169}
170
7fd59977 171void LProp_CLProps::Tangent (Dir& D)
172{
32ca7a51 173 if(!IsTangentDefined())
174 LProp_NotDefined::Raise();
175
176 if(mySignificantFirstDerivativeOrder == 1)
177 D = Dir(myDerivArr[0]);
178 else if (mySignificantFirstDerivativeOrder > 1)
179 {
180 const Standard_Real DivisionFactor = 1.e-3;
181 const Standard_Real anUsupremum = Tool::LastParameter(myCurve),
182 anUinfium = Tool::FirstParameter(myCurve);
183
184 Standard_Real du;
185 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
186 du = 0.0;
187 else
188 du = anUsupremum-anUinfium;
189
190 const Standard_Real aDelta = Max(du*DivisionFactor,MinStep);
191
192 Vec V = myDerivArr[mySignificantFirstDerivativeOrder - 1];
193
194 Standard_Real u;
195
196 if(myU-anUinfium < aDelta)
197 u = myU+aDelta;
198 else
199 u = myU-aDelta;
200
201 Pnt P1, P2;
202 Tool::Value(myCurve, Min(myU, u),P1);
203 Tool::Value(myCurve, Max(myU, u),P2);
204
205 Vec V1(P1,P2);
206 Standard_Real aDirFactor = V.Dot(V1);
207
208 if(aDirFactor < 0.0)
209 V = -V;
210
211 D = Dir(V);
212 }//else if (mySignificantFirstDerivativeOrder > 1)
7fd59977 213}
214
215Standard_Real LProp_CLProps::Curvature ()
216{
217 Standard_Boolean isDefined = IsTangentDefined();
218 LProp_NotDefined_Raise_if(!isDefined,
32ca7a51 219 "LProp_CLProps::CurvatureNotDefined()");
7fd59977 220
221 // if the first derivative is null the curvature is infinite.
32ca7a51 222 if(mySignificantFirstDerivativeOrder > 1)
223 return RealLast();
7fd59977 224
32ca7a51 225 Standard_Real Tol = myLinTol * myLinTol;
226 Standard_Real DD1 = myDerivArr[0].SquareMagnitude();
227 Standard_Real DD2 = myDerivArr[1].SquareMagnitude();
228
7fd59977 229 // if the second derivative is null the curvature is null.
32ca7a51 230 if (DD2 <= Tol)
231 {
232 myCurvature = 0.0;
7fd59977 233 }
32ca7a51 234 else
235 {
236 Standard_Real N = myDerivArr[0].CrossSquareMagnitude(myDerivArr[1]);
7fd59977 237 // if d[0] and d[1] are colinear the curvature is null.
238 Standard_Real t = N/(DD1*DD2);
32ca7a51 239 if (t<=Tol)
240 {
241 myCurvature = 0.0;
7fd59977 242 }
32ca7a51 243 else
244 {
245 myCurvature = sqrt(N) / (DD1*sqrt(DD1));
7fd59977 246 }
247 }
7fd59977 248
32ca7a51 249 return myCurvature;
250}
7fd59977 251
252void LProp_CLProps::Normal (Dir& D)
253{
254 Standard_Real c = Curvature();
32ca7a51 255 if(c==RealLast() || Abs(c) <= myLinTol)
256 {
257 LProp_NotDefined::Raise("LProp_CLProps::Normal(...):"
258 "Curvature is null or infinity");
259 }
7fd59977 260
261 // we used here the following vector relation
262 // a ^ (b ^ c) = b(ac) - c(ab)
263 // Norm = d[0] ^ (d[1] ^ d[0])
32ca7a51 264
265 Vec Norm = myDerivArr[1] * (myDerivArr[0] * myDerivArr[0]) - myDerivArr[0] * (myDerivArr[0] * myDerivArr[1]);
7fd59977 266 D = Dir(Norm);
267}
268
7fd59977 269void LProp_CLProps::CentreOfCurvature (Pnt& P)
270{
32ca7a51 271 if(Abs(Curvature()) <= myLinTol)
272 {
273 LProp_NotDefined::Raise();
274 }
7fd59977 275
276 // we used here the following vector relation
277 // a ^ (b ^ c) = b(ac) - c(ab)
278 // Norm = d[0] ^ (d[1] ^ d[0])
279
32ca7a51 280 Vec Norm = myDerivArr[1] * (myDerivArr[0] * myDerivArr[0]) - myDerivArr[0] * (myDerivArr[0] * myDerivArr[1]);
7fd59977 281 Norm.Normalize();
32ca7a51 282 Norm.Divide(myCurvature);
283 P= myPnt.Translated(Norm);
7fd59977 284}