Warning, /include/opencascade/LProp_SLProps.gxx is written in an unsupported language. File is not indexed.
0001 // Copyright (c) 1995-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014
0015 #include <LProp_Status.hxx>
0016 #include <LProp_NotDefined.hxx>
0017 #include <Standard_OutOfRange.hxx>
0018 #include <Standard_DomainError.hxx>
0019 #include <CSLib.hxx>
0020 #include <CSLib_DerivativeStatus.hxx>
0021 #include <CSLib_NormalStatus.hxx>
0022 #include <TColgp_Array2OfVec.hxx>
0023 #include <math_DirectPolynomialRoots.hxx>
0024
0025 static const Standard_Real MinStep = 1.0e-7;
0026
0027 static Standard_Boolean IsTangentDefined (LProp_SLProps& SProp,
0028 const Standard_Integer cn,
0029 const Standard_Real linTol,
0030 const Standard_Integer Derivative,
0031 Standard_Integer& Order,
0032 LProp_Status& theStatus)
0033 {
0034 Standard_Real Tol = linTol * linTol;
0035 gp_Vec V[2];
0036 Order = 0;
0037
0038 while (Order < 3)
0039 {
0040 Order++;
0041 if(cn >= Order)
0042 {
0043 switch(Order)
0044 {
0045 case 1:
0046 V[0] = SProp.D1U();
0047 V[1] = SProp.D1V();
0048 break;
0049 case 2:
0050 V[0] = SProp.D2U();
0051 V[1] = SProp.D2V();
0052 break;
0053 }//switch(Order)
0054
0055 if(V[Derivative].SquareMagnitude() > Tol)
0056 {
0057 theStatus = LProp_Defined;
0058 return Standard_True;
0059 }
0060 }//if(cn >= Order)
0061 else
0062 {
0063 theStatus = LProp_Undefined;
0064 return Standard_False;
0065 }
0066 }
0067
0068 return Standard_False;
0069 }
0070
0071 LProp_SLProps::LProp_SLProps (const Surface& S,
0072 const Standard_Real U,
0073 const Standard_Real V,
0074 const Standard_Integer N,
0075 const Standard_Real Resolution)
0076 : mySurf(S),myDerOrder(N), myCN(4), // (Tool::Continuity(S)),
0077 myLinTol(Resolution)
0078 {
0079 Standard_OutOfRange_Raise_if(N < 0 || N > 2,
0080 "LProp_SLProps::LProp_SLProps()");
0081
0082 SetParameters(U, V);
0083 }
0084
0085 LProp_SLProps::LProp_SLProps (const Surface& S,
0086 const Standard_Integer N,
0087 const Standard_Real Resolution)
0088 : mySurf(S), myU(RealLast()), myV(RealLast()), myDerOrder(N),
0089 myCN(4), // (Tool::Continuity(S))
0090 myLinTol(Resolution),
0091 myUTangentStatus (LProp_Undecided),
0092 myVTangentStatus (LProp_Undecided),
0093 myNormalStatus (LProp_Undecided),
0094 myCurvatureStatus(LProp_Undecided)
0095 {
0096 Standard_OutOfRange_Raise_if(N < 0 || N > 2,
0097 "LProp_SLProps::LProp_SLProps()");
0098 }
0099
0100 LProp_SLProps::LProp_SLProps (const Standard_Integer N,
0101 const Standard_Real Resolution)
0102 : myU(RealLast()), myV(RealLast()), myDerOrder(N), myCN(0),
0103 myLinTol(Resolution),
0104 myUTangentStatus (LProp_Undecided),
0105 myVTangentStatus (LProp_Undecided),
0106 myNormalStatus (LProp_Undecided),
0107 myCurvatureStatus(LProp_Undecided)
0108 {
0109 Standard_OutOfRange_Raise_if(N < 0 || N > 2,
0110 "LProp_SLProps::LProp_SLProps() bad level");
0111 }
0112
0113 void LProp_SLProps::SetSurface (const Surface& S )
0114 {
0115 mySurf = S;
0116 myCN = 4; // =Tool::Continuity(S);
0117 }
0118
0119 void LProp_SLProps::SetParameters (const Standard_Real U,
0120 const Standard_Real V)
0121 {
0122 myU = U;
0123 myV = V;
0124 switch (myDerOrder)
0125 {
0126 case 0:
0127 Tool::Value(mySurf, myU, myV, myPnt);
0128 break;
0129 case 1:
0130 Tool::D1(mySurf, myU, myV, myPnt, myD1u, myD1v);
0131 break;
0132 case 2:
0133 Tool::D2(mySurf, myU, myV, myPnt, myD1u, myD1v, myD2u, myD2v, myDuv);
0134 break;
0135 }
0136
0137 myUTangentStatus = LProp_Undecided;
0138 myVTangentStatus = LProp_Undecided;
0139 myNormalStatus = LProp_Undecided;
0140 myCurvatureStatus = LProp_Undecided;
0141 }
0142
0143 const gp_Pnt& LProp_SLProps::Value() const
0144 {
0145 return myPnt;
0146 }
0147
0148 const gp_Vec& LProp_SLProps::D1U()
0149 {
0150 if (myDerOrder < 1)
0151 {
0152 myDerOrder =1;
0153 Tool::D1(mySurf,myU,myV,myPnt,myD1u,myD1v);
0154 }
0155
0156 return myD1u;
0157 }
0158
0159 const gp_Vec& LProp_SLProps::D1V()
0160 {
0161 if (myDerOrder < 1)
0162 {
0163 myDerOrder =1;
0164 Tool::D1(mySurf,myU,myV,myPnt,myD1u,myD1v);
0165 }
0166
0167 return myD1v;
0168 }
0169
0170 const gp_Vec& LProp_SLProps::D2U()
0171 {
0172 if (myDerOrder < 2)
0173 {
0174 myDerOrder =2;
0175 Tool::D2(mySurf,myU,myV,myPnt,myD1u,myD1v,myD2u,myD2v,myDuv);
0176 }
0177
0178 return myD2u;
0179 }
0180
0181 const gp_Vec& LProp_SLProps::D2V()
0182 {
0183 if (myDerOrder < 2)
0184 {
0185 myDerOrder =2;
0186 Tool::D2(mySurf,myU,myV,myPnt,myD1u,myD1v,myD2u,myD2v,myDuv);
0187 }
0188
0189 return myD2v;
0190 }
0191
0192 const gp_Vec& LProp_SLProps::DUV()
0193 {
0194 if (myDerOrder < 2)
0195 {
0196 myDerOrder =2;
0197 Tool::D2(mySurf,myU,myV,myPnt,myD1u,myD1v,myD2u,myD2v,myDuv);
0198 }
0199
0200 return myDuv;
0201 }
0202
0203 Standard_Boolean LProp_SLProps::IsTangentUDefined ()
0204 {
0205 if (myUTangentStatus == LProp_Undefined)
0206 return Standard_False;
0207 else if (myUTangentStatus >= LProp_Defined)
0208 return Standard_True;
0209
0210 // uTangentStatus == Lprop_Undecided
0211 // we have to calculate the first non null U derivative
0212 return IsTangentDefined(*this, myCN, myLinTol, 0,
0213 mySignificantFirstDerivativeOrderU, myUTangentStatus);
0214 }
0215
0216 void LProp_SLProps::TangentU (gp_Dir& D)
0217 {
0218 if(!IsTangentUDefined())
0219 throw LProp_NotDefined();
0220
0221 if(mySignificantFirstDerivativeOrderU == 1)
0222 D = gp_Dir(myD1u);
0223 else
0224 {
0225 const Standard_Real DivisionFactor = 1.e-3;
0226 Standard_Real anUsupremum, anUinfium;
0227 Standard_Real anVsupremum, anVinfium;
0228 Tool::Bounds(mySurf,anUinfium,anVinfium,anUsupremum,anVsupremum);
0229 Standard_Real du;
0230 if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst()))
0231 du = 0.0;
0232 else
0233 du = anUsupremum-anUinfium;
0234
0235 const Standard_Real aDeltaU = Max(du*DivisionFactor,MinStep);
0236
0237 gp_Vec V = myD2u;
0238
0239 Standard_Real u;
0240
0241 if(myU-anUinfium < aDeltaU)
0242 u = myU+aDeltaU;
0243 else
0244 u = myU-aDeltaU;
0245
0246 gp_Pnt P1, P2;
0247 Tool::Value(mySurf, Min(myU, u),myV,P1);
0248 Tool::Value(mySurf, Max(myU, u),myV,P2);
0249
0250 gp_Vec V1(P1,P2);
0251 Standard_Real aDirFactor = V.Dot(V1);
0252
0253 if(aDirFactor < 0.0)
0254 V = -V;
0255
0256 D = gp_Dir(V);
0257 }
0258 }
0259
0260 Standard_Boolean LProp_SLProps::IsTangentVDefined ()
0261 {
0262 if (myVTangentStatus == LProp_Undefined)
0263 return Standard_False;
0264 else if (myVTangentStatus >= LProp_Defined)
0265 return Standard_True;
0266
0267 // vTangentStatus == Lprop_Undecided
0268 // we have to calculate the first non null V derivative
0269 return IsTangentDefined(*this, myCN, myLinTol, 1,
0270 mySignificantFirstDerivativeOrderV, myVTangentStatus);
0271 }
0272
0273 void LProp_SLProps::TangentV (gp_Dir& D)
0274 {
0275 if(!IsTangentVDefined())
0276 throw LProp_NotDefined();
0277
0278 if(mySignificantFirstDerivativeOrderV == 1)
0279 D = gp_Dir(myD1v);
0280 else
0281 {
0282 const Standard_Real DivisionFactor = 1.e-3;
0283 Standard_Real anUsupremum, anUinfium;
0284 Standard_Real anVsupremum, anVinfium;
0285 Tool::Bounds(mySurf,anUinfium,anVinfium,anUsupremum,anVsupremum);
0286
0287 Standard_Real dv;
0288 if((anVsupremum >= RealLast()) || (anVinfium <= RealFirst()))
0289 dv = 0.0;
0290 else
0291 dv = anVsupremum-anVinfium;
0292
0293 const Standard_Real aDeltaV = Max(dv*DivisionFactor,MinStep);
0294
0295 gp_Vec V = myD2v;
0296
0297 Standard_Real v;
0298
0299 if(myV-anVinfium < aDeltaV)
0300 v = myV+aDeltaV;
0301 else
0302 v = myV-aDeltaV;
0303
0304 gp_Pnt P1, P2;
0305 Tool::Value(mySurf, myU, Min(myV, v),P1);
0306 Tool::Value(mySurf, myU, Max(myV, v),P2);
0307
0308 gp_Vec V1(P1,P2);
0309 Standard_Real aDirFactor = V.Dot(V1);
0310
0311 if(aDirFactor < 0.0)
0312 V = -V;
0313
0314 D = gp_Dir(V);
0315 }
0316 }
0317
0318 Standard_Boolean LProp_SLProps::IsNormalDefined()
0319 {
0320 if (myNormalStatus == LProp_Undefined)
0321 return Standard_False;
0322 else if (myNormalStatus >= LProp_Defined)
0323 return Standard_True;
0324
0325 // status = UnDecided
0326 // first try the standard computation of the normal.
0327 CSLib_DerivativeStatus aStatus = CSLib_Done;
0328 CSLib::Normal(myD1u, myD1v, myLinTol, aStatus, myNormal);
0329 if (aStatus == CSLib_Done)
0330 {
0331 myNormalStatus = LProp_Computed;
0332 return Standard_True;
0333 }
0334
0335 // else solve the degenerated case only if continuity >= 2
0336
0337 myNormalStatus = LProp_Undefined;
0338 return Standard_False;
0339 }
0340
0341 const gp_Dir& LProp_SLProps::Normal ()
0342 {
0343 if(!IsNormalDefined())
0344 {
0345 throw LProp_NotDefined();
0346 }
0347
0348 return myNormal;
0349 }
0350
0351
0352 Standard_Boolean LProp_SLProps::IsCurvatureDefined ()
0353 {
0354 if (myCurvatureStatus == LProp_Undefined)
0355 return Standard_False;
0356 else if (myCurvatureStatus >= LProp_Defined)
0357 return Standard_True;
0358
0359 if(myCN < 2)
0360 {
0361 myCurvatureStatus = LProp_Undefined;
0362 return Standard_False;
0363 }
0364
0365 // status = UnDecided
0366 if (!IsNormalDefined())
0367 {
0368 myCurvatureStatus = LProp_Undefined;
0369 return Standard_False;
0370 }
0371
0372 // pour eviter un plantage dans le cas du caro pointu
0373 // en fait on doit pouvoir calculer les courbure
0374 // avoir
0375 if(!IsTangentUDefined() || !IsTangentVDefined())
0376 {
0377 myCurvatureStatus = LProp_Undefined;
0378 return Standard_False;
0379 }
0380
0381 // here we compute the curvature features of the surface
0382
0383 gp_Vec Norm (myNormal);
0384
0385 Standard_Real E = myD1u.SquareMagnitude();
0386 Standard_Real F = myD1u.Dot(myD1v);
0387 Standard_Real G = myD1v.SquareMagnitude();
0388
0389 if(myDerOrder < 2)
0390 this->D2U();
0391
0392 Standard_Real L = Norm.Dot(myD2u);
0393 Standard_Real M = Norm.Dot(myDuv);
0394 Standard_Real N = Norm.Dot(myD2v);
0395
0396 Standard_Real A = E * M - F * L;
0397 Standard_Real B = E * N - G * L;
0398 Standard_Real C = F * N - G * M;
0399
0400 Standard_Real MaxABC = Max(Max(Abs(A),Abs(B)),Abs(C));
0401 if (MaxABC < RealEpsilon()) // ombilic
0402 {
0403 myMinCurv = N / G;
0404 myMaxCurv = myMinCurv;
0405 myDirMinCurv = gp_Dir (myD1u);
0406 myDirMaxCurv = gp_Dir (myD1u.Crossed(Norm));
0407 myMeanCurv = myMinCurv; // (Cmin + Cmax) / 2.
0408 myGausCurv = myMinCurv * myMinCurv; // (Cmin * Cmax)
0409 myCurvatureStatus = LProp_Computed;
0410 return Standard_True;
0411 }
0412
0413 A = A / MaxABC;
0414 B = B / MaxABC;
0415 C = C / MaxABC;
0416 Standard_Real Curv1, Curv2, Root1, Root2;
0417 gp_Vec VectCurv1, VectCurv2;
0418
0419 if (Abs(A) > RealEpsilon())
0420 {
0421 math_DirectPolynomialRoots Root (A, B, C);
0422 if(Root.NbSolutions() != 2)
0423 {
0424 myCurvatureStatus = LProp_Undefined;
0425 return Standard_False;
0426 }
0427 else
0428 {
0429 Root1 = Root.Value(1);
0430 Root2 = Root.Value(2);
0431 Curv1 = ((L * Root1 + 2. * M) * Root1 + N) /
0432 ((E * Root1 + 2. * F) * Root1 + G);
0433 Curv2 = ((L * Root2 + 2. * M) * Root2 + N) /
0434 ((E * Root2 + 2. * F) * Root2 + G);
0435 VectCurv1 = Root1 * myD1u + myD1v;
0436 VectCurv2 = Root2 * myD1u + myD1v;
0437 }
0438 }
0439 else if (Abs(C) > RealEpsilon())
0440 {
0441 math_DirectPolynomialRoots Root(C, B, A);
0442
0443 if((Root.NbSolutions() != 2))
0444 {
0445 myCurvatureStatus = LProp_Undefined;
0446 return Standard_False;
0447 }
0448 else
0449 {
0450 Root1 = Root.Value(1);
0451 Root2 = Root.Value(2);
0452 Curv1 = ((N * Root1 + 2. * M) * Root1 + L) /
0453 ((G * Root1 + 2. * F) * Root1 + E);
0454 Curv2 = ((N * Root2 + 2. * M) * Root2 + L) /
0455 ((G * Root2 + 2. * F) * Root2 + E);
0456 VectCurv1 = myD1u + Root1 * myD1v;
0457 VectCurv2 = myD1u + Root2 * myD1v;
0458 }
0459 }
0460 else
0461 {
0462 Curv1 = L / E;
0463 Curv2 = N / G;
0464 VectCurv1 = myD1u;
0465 VectCurv2 = myD1v;
0466 }
0467
0468 if (Curv1 < Curv2)
0469 {
0470 myMinCurv = Curv1;
0471 myMaxCurv = Curv2;
0472 myDirMinCurv = gp_Dir (VectCurv1);
0473 myDirMaxCurv = gp_Dir (VectCurv2);
0474 }
0475 else
0476 {
0477 myMinCurv = Curv2;
0478 myMaxCurv = Curv1;
0479 myDirMinCurv = gp_Dir (VectCurv2);
0480 myDirMaxCurv = gp_Dir (VectCurv1);
0481 }
0482
0483 myMeanCurv = ((N * E) - (2. * M * F) + (L * G)) // voir Farin p.282
0484 / (2. * ((E * G) - (F * F)));
0485 myGausCurv = ((L * N) - (M * M))
0486 / ((E * G) - (F * F));
0487 myCurvatureStatus = LProp_Computed;
0488 return Standard_True;
0489 }
0490
0491 Standard_Boolean LProp_SLProps::IsUmbilic ()
0492 {
0493 if(!IsCurvatureDefined())
0494 throw LProp_NotDefined();
0495
0496 return Abs(myMaxCurv - myMinCurv) < Abs(Epsilon(myMaxCurv));
0497 }
0498
0499 Standard_Real LProp_SLProps::MaxCurvature ()
0500 {
0501 if(!IsCurvatureDefined())
0502 throw LProp_NotDefined();
0503
0504 return myMaxCurv;
0505 }
0506
0507 Standard_Real LProp_SLProps::MinCurvature ()
0508 {
0509 if(!IsCurvatureDefined())
0510 throw LProp_NotDefined();
0511
0512 return myMinCurv;
0513 }
0514
0515 void LProp_SLProps::CurvatureDirections(gp_Dir& Max, gp_Dir& Min)
0516 {
0517 if(!IsCurvatureDefined())
0518 throw LProp_NotDefined();
0519
0520 Max = myDirMaxCurv;
0521 Min = myDirMinCurv;
0522 }
0523
0524 Standard_Real LProp_SLProps::MeanCurvature ()
0525 {
0526 if(!IsCurvatureDefined())
0527 throw LProp_NotDefined();
0528
0529 return myMeanCurv;
0530 }
0531
0532 Standard_Real LProp_SLProps::GaussianCurvature ()
0533 {
0534 if(!IsCurvatureDefined())
0535 throw LProp_NotDefined();
0536
0537 return myGausCurv;
0538 }