Warning, /include/opencascade/ApproxInt_ImpPrmSvSurfaces.gxx is written in an unsupported language. File is not indexed.
0001 // Created on: 1993-03-17
0002 // Created by: Laurent BUCHARD
0003 // Copyright (c) 1993-1999 Matra Datavision
0004 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0005 //
0006 // This file is part of Open CASCADE Technology software library.
0007 //
0008 // This library is free software; you can redistribute it and/or modify it under
0009 // the terms of the GNU Lesser General Public License version 2.1 as published
0010 // by the Free Software Foundation, with special exception defined in the file
0011 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0012 // distribution for complete text of the license and disclaimer of any warranty.
0013 //
0014 // Alternatively, this file may be used under the terms of Open CASCADE
0015 // commercial license or contractual agreement.
0016
0017 #include <IntSurf_PntOn2S.hxx>
0018 #include <TColStd_Array1OfReal.hxx>
0019 #include <math_FunctionSetRoot.hxx>
0020 #include <StdFail_NotDone.hxx>
0021 #include <GeomAbs_SurfaceType.hxx>
0022 #include <Precision.hxx>
0023
0024 //=======================================================================
0025 //function : IsSingular
0026 //purpose : Returns TRUE if vectors theDU || theDV or if at least one
0027 // of them has null-magnitude.
0028 // theSqLinTol is square of linear tolerance.
0029 // theAngTol is angular tolerance.
0030 //=======================================================================
0031 static Standard_Boolean IsSingular( const gp_Vec& theDU,
0032 const gp_Vec& theDV,
0033 const Standard_Real theSqLinTol,
0034 const Standard_Real theAngTol)
0035 {
0036 gp_Vec aDU(theDU), aDV(theDV);
0037
0038 const Standard_Real aSqMagnDU = aDU.SquareMagnitude(),
0039 aSqMagnDV = aDV.SquareMagnitude();
0040
0041 if(aSqMagnDU < theSqLinTol)
0042 return Standard_True;
0043
0044 aDU.Divide(sqrt(aSqMagnDU));
0045
0046 if(aSqMagnDV < theSqLinTol)
0047 return Standard_True;
0048
0049 aDV.Divide(sqrt(aSqMagnDV));
0050
0051 //Here aDU and aDV vectors have magnitude 1.0.
0052
0053 if(aDU.Crossed(aDV).SquareMagnitude() < theAngTol*theAngTol)
0054 return Standard_True;
0055
0056 return Standard_False;
0057 }
0058
0059 //=======================================================================
0060 //function : SingularProcessing
0061 //purpose : Computes 2D-representation (in UV-coordinates) of
0062 // theTg3D vector on the surface in case when
0063 // theDU.Crossed(theDV).Magnitude() == 0.0. Stores result in
0064 // theTg2D variable.
0065 // theDU and theDV are vectors of 1st derivative
0066 // (with respect to U and V variables correspondingly).
0067 // If theIsTo3DTgCompute == TRUE then theTg3D has not been
0068 // defined yet (it should be computed).
0069 // theLinTol is SQUARE of the tolerance.
0070 //
0071 //Algorithm:
0072 // Condition
0073 // Tg=theDU*theTg2D.X()+theDV*theTg2D.Y()
0074 // has to be satisfied strictly.
0075 // More over, vector Tg has to be NORMALIZED
0076 // (if theIsTo3DTgCompute == TRUE then new computed vector will
0077 // always have magnitude 1.0).
0078 //=======================================================================
0079 static Standard_Boolean SingularProcessing( const gp_Vec& theDU,
0080 const gp_Vec& theDV,
0081 const Standard_Boolean theIsTo3DTgCompute,
0082 const Standard_Real theLinTol,
0083 const Standard_Real theAngTol,
0084 gp_Vec& theTg3D,
0085 gp_Vec2d& theTg2D)
0086 {
0087 //Attention: @ \sin theAngTol \approx theAngTol @ (for cross-product)
0088
0089 //Really, vector theTg3D has to be normalized (if theIsTo3DTgCompute == FALSE).
0090 const Standard_Real aSQTan = theTg3D.SquareMagnitude();
0091
0092 const Standard_Real aSqMagnDU = theDU.SquareMagnitude(),
0093 aSqMagnDV = theDV.SquareMagnitude();
0094
0095 //There are some reasons of singularity
0096
0097 //1.
0098 if((aSqMagnDU < theLinTol) && (aSqMagnDV < theLinTol))
0099 {
0100 //For future, this case can be processed as same as in case of
0101 //osculating surfaces (expanding in Taylor series). Here,
0102 //we return only.
0103
0104 return Standard_False;
0105 }
0106
0107 //2.
0108 if(aSqMagnDU < theLinTol)
0109 {
0110 //In this case, theTg3D vector will be parallel with theDV.
0111 //Its true direction shall be precised later (the algorithm is
0112 //based on array of Walking-points).
0113
0114 if(theIsTo3DTgCompute)
0115 {
0116 //theTg3D will be normalized. Its magnitude is
0117 const Standard_Real aTgMagn = 1.0;
0118
0119 const Standard_Real aNorm = sqrt(aSqMagnDV);
0120 theTg3D = theDV.Divided(aNorm);
0121 theTg2D.SetCoord(0.0, aTgMagn/aNorm);
0122 }
0123 else
0124 {
0125 //theTg3D is already defined.
0126 //Here we check only, if this tangent is parallel to theDV.
0127
0128 if(theDV.Crossed(theTg3D).SquareMagnitude() <
0129 theAngTol*theAngTol*aSqMagnDV*aSQTan)
0130 {
0131 //theTg3D is parallel to theDV
0132
0133 //Use sign "+" if theTg3D and theDV are codirectional
0134 //and sign "-" if opposite
0135 const Standard_Real aDP = theTg3D.Dot(theDV);
0136 theTg2D.SetCoord(0.0, Sign(sqrt(aSQTan/aSqMagnDV), aDP));
0137 }
0138 else
0139 {
0140 //theTg3D is not parallel to theDV
0141 //It is abnormal
0142
0143 return Standard_False;
0144 }
0145 }
0146
0147 return Standard_True;
0148 }
0149
0150 //3.
0151 if(aSqMagnDV < theLinTol)
0152 {
0153 //In this case, theTg3D vector will be parallel with theDU.
0154 //Its true direction shall be precised later (the algorithm is
0155 //based on array of Walking-points).
0156
0157 if(theIsTo3DTgCompute)
0158 {
0159 //theTg3D will be normalized. Its magnitude is
0160 const Standard_Real aTgMagn = 1.0;
0161
0162 const Standard_Real aNorm = sqrt(aSqMagnDU);
0163 theTg3D = theDU.Divided(aNorm);
0164 theTg2D.SetCoord(aTgMagn/aNorm, 0.0);
0165 }
0166 else
0167 {
0168 //theTg3D is already defined.
0169 //Here we check only, if this tangent is parallel to theDU.
0170
0171 if(theDU.Crossed(theTg3D).SquareMagnitude() <
0172 theAngTol*theAngTol*aSqMagnDU*aSQTan)
0173 {
0174 //theTg3D is parallel to theDU
0175
0176 //Use sign "+" if theTg3D and theDU are codirectional
0177 //and sign "-" if opposite
0178 const Standard_Real aDP = theTg3D.Dot(theDU);
0179 theTg2D.SetCoord(Sign(sqrt(aSQTan/aSqMagnDU), aDP), 0.0);
0180 }
0181 else
0182 {
0183 //theTg3D is not parallel to theDU
0184 //It is abnormal
0185
0186 return Standard_False;
0187 }
0188 }
0189
0190 return Standard_True;
0191 }
0192
0193 //4. If aSqMagnDU > 0.0 && aSqMagnDV > 0.0 but theDV || theDU.
0194
0195 const Standard_Real aLenU = sqrt(aSqMagnDU),
0196 aLenV = sqrt(aSqMagnDV);
0197
0198 //aLenSum > 0.0 definitely
0199 const Standard_Real aLenSum = aLenU + aLenV;
0200
0201 if(theDV.Dot(theDU) > 0.0)
0202 {
0203 //Vectors theDV and theDU are codirectional.
0204
0205 if(theIsTo3DTgCompute)
0206 {
0207 theTg2D.SetCoord(1.0/aLenSum, 1.0/aLenSum);
0208 theTg3D = theDU*theTg2D.X() + theDV*theTg2D.Y();
0209 }
0210 else
0211 {
0212 //theTg3D is already defined.
0213 //Here we check only, if this tangent is parallel to theDU
0214 //(and theDV together).
0215
0216 if(theDU.Crossed(theTg3D).SquareMagnitude() <
0217 theAngTol*theAngTol*aSqMagnDU*aSQTan)
0218 {
0219 //theTg3D is parallel to theDU
0220
0221 const Standard_Real aDP = theTg3D.Dot(theDU);
0222 const Standard_Real aLenTg = Sign(sqrt(aSQTan), aDP);
0223 theTg2D.SetCoord(aLenTg/aLenSum, aLenTg/aLenSum);
0224 }
0225 else
0226 {
0227 //theTg3D is not parallel to theDU
0228 //It is abnormal
0229
0230 return Standard_False;
0231 }
0232 }
0233 }
0234 else
0235 {
0236 //Vectors theDV and theDU are opposite.
0237
0238 if(theIsTo3DTgCompute)
0239 {
0240 //Here we chose theDU as direction of theTg3D.
0241 //True direction shall be precised later (the algorithm is
0242 //based on array of Walking-points).
0243
0244 theTg2D.SetCoord(1.0/aLenSum, -1.0/aLenSum);
0245 theTg3D = theDU*theTg2D.X() + theDV*theTg2D.Y();
0246 }
0247 else
0248 {
0249 //theTg3D is already defined.
0250 //Here we check only, if this tangent is parallel to theDU
0251 //(and theDV together).
0252
0253 if(theDU.Crossed(theTg3D).SquareMagnitude() <
0254 theAngTol*theAngTol*aSqMagnDU*aSQTan)
0255 {
0256 //theTg3D is parallel to theDU
0257
0258 const Standard_Real aDP = theTg3D.Dot(theDU);
0259 const Standard_Real aLenTg = Sign(sqrt(aSQTan), aDP);
0260 theTg2D.SetCoord(aLenTg/aLenSum, -aLenTg/aLenSum);
0261 }
0262 else
0263 {
0264 //theTg3D is not parallel to theDU
0265 //It is abnormal
0266
0267 return Standard_False;
0268 }
0269 }
0270 }
0271
0272 return Standard_True;
0273 }
0274
0275 //=======================================================================
0276 //function : NonSingularProcessing
0277 //purpose : Computes 2D-representation (in UV-coordinates) of
0278 // theTg3D vector on the surface in case when
0279 // theDU.Crossed(theDV).Magnitude() > 0.0. Stores result in
0280 // theTg2D variable.
0281 // theDU and theDV are vectors of 1st derivative
0282 // (with respect to U and V variables correspondingly).
0283 // theLinTol is SQUARE of the tolerance.
0284 //
0285 //Algorithm:
0286 // Condition
0287 // Tg=theDU*theTg2D.X()+theDV*theTg2D.Y()
0288 // has to be satisfied strictly.
0289 // More over, vector Tg has always to be NORMALIZED.
0290 //=======================================================================
0291 static Standard_Boolean NonSingularProcessing(const gp_Vec& theDU,
0292 const gp_Vec& theDV,
0293 const gp_Vec& theTg3D,
0294 const Standard_Real theLinTol,
0295 const Standard_Real theAngTol,
0296 gp_Vec2d& theTg2D)
0297 {
0298 const gp_Vec aNormal = theDU.Crossed(theDV);
0299 const Standard_Real aSQMagn = aNormal.SquareMagnitude();
0300
0301 if(IsSingular(theDU, theDV, theLinTol, theAngTol))
0302 {
0303 gp_Vec aTg(theTg3D);
0304 return
0305 SingularProcessing(theDU, theDV, Standard_False,
0306 theLinTol, theAngTol, aTg, theTg2D);
0307 }
0308
0309 //If @\vec{T}=\vec{A}*U+\vec{B}*V@ then
0310
0311 // \left\{\begin{matrix}
0312 // \vec{A} \times \vec{T} = (\vec{A} \times \vec{B})*V
0313 // \vec{B} \times \vec{T} = (\vec{B} \times \vec{A})*U
0314 // \end{matrix}\right.
0315
0316 //From here, values of U and V can be found very easily
0317 //(if @\left \| \vec{A} \times \vec{B} \right \| > 0.0 @,
0318 //else it is singular case).
0319
0320 const gp_Vec aTgU(theTg3D.Crossed(theDU)), aTgV(theTg3D.Crossed(theDV));
0321 const Standard_Real aDeltaU = aTgV.SquareMagnitude()/aSQMagn;
0322 const Standard_Real aDeltaV = aTgU.SquareMagnitude()/aSQMagn;
0323
0324 theTg2D.SetCoord(Sign(sqrt(aDeltaU), aTgV.Dot(aNormal)), -Sign(sqrt(aDeltaV), aTgU.Dot(aNormal)));
0325
0326 return Standard_True;
0327 }
0328
0329 //--------------------------------------------------------------------------------
0330 ApproxInt_ImpPrmSvSurfaces::ApproxInt_ImpPrmSvSurfaces( const TheISurface& ISurf
0331 ,const ThePSurface& PSurf):
0332 MyIsTangent(Standard_False),
0333 MyHasBeenComputed(Standard_False),
0334 MyIsTangentbis(Standard_False),
0335 MyHasBeenComputedbis(Standard_False),
0336 MyImplicitFirst(Standard_True),
0337 MyZerImpFunc(PSurf,ISurf)
0338 {
0339 SetUseSolver(Standard_True);
0340 }
0341 //--------------------------------------------------------------------------------
0342 ApproxInt_ImpPrmSvSurfaces::ApproxInt_ImpPrmSvSurfaces( const ThePSurface& PSurf
0343 ,const TheISurface& ISurf):
0344 MyIsTangent(Standard_False),
0345 MyHasBeenComputed(Standard_False),
0346 MyIsTangentbis(Standard_False),
0347 MyHasBeenComputedbis(Standard_False),
0348 MyImplicitFirst(Standard_False),
0349 MyZerImpFunc(PSurf,ISurf)
0350 {
0351 SetUseSolver(Standard_True);
0352 }
0353 //--------------------------------------------------------------------------------
0354 void ApproxInt_ImpPrmSvSurfaces::Pnt(const Standard_Real u1,
0355 const Standard_Real v1,
0356 const Standard_Real u2,
0357 const Standard_Real v2,
0358 gp_Pnt& P) {
0359 gp_Pnt aP;
0360 gp_Vec aT;
0361 gp_Vec2d aTS1,aTS2;
0362 Standard_Real tu1=u1;
0363 Standard_Real tu2=u2;
0364 Standard_Real tv1=v1;
0365 Standard_Real tv2=v2;
0366 this->Compute(tu1,tv1,tu2,tv2,aP,aT,aTS1,aTS2);
0367 P=MyPnt;
0368 }
0369 //--------------------------------------------------------------------------------
0370 Standard_Boolean ApproxInt_ImpPrmSvSurfaces::Tangency(const Standard_Real u1,
0371 const Standard_Real v1,
0372 const Standard_Real u2,
0373 const Standard_Real v2,
0374 gp_Vec& T) {
0375 gp_Pnt aP;
0376 gp_Vec aT;
0377 gp_Vec2d aTS1,aTS2;
0378 Standard_Real tu1=u1;
0379 Standard_Real tu2=u2;
0380 Standard_Real tv1=v1;
0381 Standard_Real tv2=v2;
0382 Standard_Boolean t=this->Compute(tu1,tv1,tu2,tv2,aP,aT,aTS1,aTS2);
0383 T=MyTg;
0384 return(t);
0385 }
0386 //--------------------------------------------------------------------------------
0387 Standard_Boolean ApproxInt_ImpPrmSvSurfaces::TangencyOnSurf1(const Standard_Real u1,
0388 const Standard_Real v1,
0389 const Standard_Real u2,
0390 const Standard_Real v2,
0391 gp_Vec2d& T) {
0392 gp_Pnt aP;
0393 gp_Vec aT;
0394 gp_Vec2d aTS1,aTS2;
0395 Standard_Real tu1=u1;
0396 Standard_Real tu2=u2;
0397 Standard_Real tv1=v1;
0398 Standard_Real tv2=v2;
0399 Standard_Boolean t=this->Compute(tu1,tv1,tu2,tv2,aP,aT,aTS1,aTS2);
0400 T=MyTguv1;
0401 return(t);
0402 }
0403 //--------------------------------------------------------------------------------
0404 Standard_Boolean ApproxInt_ImpPrmSvSurfaces::TangencyOnSurf2(const Standard_Real u1,
0405 const Standard_Real v1,
0406 const Standard_Real u2,
0407 const Standard_Real v2,
0408 gp_Vec2d& T) {
0409 gp_Pnt aP;
0410 gp_Vec aT;
0411 gp_Vec2d aTS1,aTS2;
0412 Standard_Real tu1=u1;
0413 Standard_Real tu2=u2;
0414 Standard_Real tv1=v1;
0415 Standard_Real tv2=v2;
0416 Standard_Boolean t=this->Compute(tu1,tv1,tu2,tv2,aP,aT,aTS1,aTS2);
0417 T=MyTguv2;
0418 return(t);
0419 }
0420
0421 //=======================================================================
0422 //function : Compute
0423 //purpose : Computes point on curve, 3D and 2D-tangents of a curve and
0424 // parameters on the surfaces.
0425 //=======================================================================
0426 Standard_Boolean ApproxInt_ImpPrmSvSurfaces::Compute( Standard_Real& u1,
0427 Standard_Real& v1,
0428 Standard_Real& u2,
0429 Standard_Real& v2,
0430 gp_Pnt& P,
0431 gp_Vec& Tg,
0432 gp_Vec2d& Tguv1,
0433 gp_Vec2d& Tguv2)
0434 {
0435 const IntSurf_Quadric& aQSurf = MyZerImpFunc.ISurface();
0436 const ThePSurface& aPSurf = MyZerImpFunc.PSurface();
0437 gp_Vec2d& aQuadTg = MyImplicitFirst ? Tguv1 : Tguv2;
0438 gp_Vec2d& aPrmTg = MyImplicitFirst ? Tguv2 : Tguv1;
0439
0440 //for square
0441 const Standard_Real aNullValue = Precision::Approximation()*
0442 Precision::Approximation(),
0443 anAngTol = Precision::Angular();
0444
0445 Standard_Real tu1=u1;
0446 Standard_Real tu2=u2;
0447 Standard_Real tv1=v1;
0448 Standard_Real tv2=v2;
0449
0450 if(MyHasBeenComputed) {
0451 if( (MyParOnS1.X()==u1)&&(MyParOnS1.Y()==v1)
0452 &&(MyParOnS2.X()==u2)&&(MyParOnS2.Y()==v2)) {
0453 return(MyIsTangent);
0454 }
0455 else if(MyHasBeenComputedbis == Standard_False) {
0456 MyTgbis = MyTg;
0457 MyTguv1bis = MyTguv1;
0458 MyTguv2bis = MyTguv2;
0459 MyPntbis = MyPnt;
0460 MyParOnS1bis = MyParOnS1;
0461 MyParOnS2bis = MyParOnS2;
0462 MyIsTangentbis = MyIsTangent;
0463 MyHasBeenComputedbis = MyHasBeenComputed;
0464 }
0465 }
0466
0467 if(MyHasBeenComputedbis) {
0468 if( (MyParOnS1bis.X()==u1)&&(MyParOnS1bis.Y()==v1)
0469 &&(MyParOnS2bis.X()==u2)&&(MyParOnS2bis.Y()==v2)) {
0470
0471 gp_Vec TV(MyTg);
0472 gp_Vec2d TV1(MyTguv1);
0473 gp_Vec2d TV2(MyTguv2);
0474 gp_Pnt TP(MyPnt);
0475 gp_Pnt2d TP1(MyParOnS1);
0476 gp_Pnt2d TP2(MyParOnS2);
0477 Standard_Boolean TB=MyIsTangent;
0478
0479 MyTg = MyTgbis;
0480 MyTguv1 = MyTguv1bis;
0481 MyTguv2 = MyTguv2bis;
0482 MyPnt = MyPntbis;
0483 MyParOnS1 = MyParOnS1bis;
0484 MyParOnS2 = MyParOnS2bis;
0485 MyIsTangent = MyIsTangentbis;
0486
0487 MyTgbis = TV;
0488 MyTguv1bis = TV1;
0489 MyTguv2bis = TV2;
0490 MyPntbis = TP;
0491 MyParOnS1bis = TP1;
0492 MyParOnS2bis = TP2;
0493 MyIsTangentbis = TB;
0494
0495 return(MyIsTangent);
0496 }
0497 }
0498
0499 math_Vector X(1,2);
0500 math_Vector BornInf(1,2), BornSup(1,2), Tolerance(1,2);
0501 //--- ThePSurfaceTool::GetResolution(aPSurf,Tolerance(1),Tolerance(2));
0502 Tolerance(1) = 1.0e-8; Tolerance(2) = 1.0e-8;
0503 Standard_Real binfu,bsupu,binfv,bsupv;
0504 binfu = ThePSurfaceTool::FirstUParameter(aPSurf);
0505 binfv = ThePSurfaceTool::FirstVParameter(aPSurf);
0506 bsupu = ThePSurfaceTool::LastUParameter(aPSurf);
0507 bsupv = ThePSurfaceTool::LastVParameter(aPSurf);
0508 BornInf(1) = binfu; BornSup(1) = bsupu;
0509 BornInf(2) = binfv; BornSup(2) = bsupv;
0510 Standard_Real TranslationU = 0., TranslationV = 0.;
0511
0512 if (!FillInitialVectorOfSolution(u1, v1, u2, v2,
0513 binfu, bsupu, binfv, bsupv,
0514 X,
0515 TranslationU, TranslationV))
0516 {
0517 MyIsTangent=MyIsTangentbis=Standard_False;
0518 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0519 return(Standard_False);
0520 }
0521
0522 Standard_Boolean aRsnldIsDone = Standard_False;
0523 Standard_Real PourTesterU = X(1);
0524 Standard_Real PourTesterV = X(2);
0525 if (GetUseSolver())
0526 {
0527 math_FunctionSetRoot Rsnld(MyZerImpFunc);
0528 Rsnld.SetTolerance(Tolerance);
0529 Rsnld.Perform(MyZerImpFunc, X, BornInf, BornSup);
0530 aRsnldIsDone = Rsnld.IsDone();
0531 if (aRsnldIsDone)
0532 Rsnld.Root(X);
0533 }
0534 if(aRsnldIsDone || !GetUseSolver())
0535 {
0536 MyHasBeenComputed = Standard_True;
0537
0538 Standard_Real DistAvantApresU = Abs(PourTesterU-X(1));
0539 Standard_Real DistAvantApresV = Abs(PourTesterV-X(2));
0540
0541 MyPnt = P = ThePSurfaceTool::Value(aPSurf, X(1), X(2));
0542
0543 if( (DistAvantApresV <= 0.001 ) &&
0544 (DistAvantApresU <= 0.001 ))
0545 {
0546 gp_Vec aD1uPrm,aD1vPrm;
0547 gp_Vec aD1uQuad,aD1vQuad;
0548
0549 if(MyImplicitFirst)
0550 {
0551 u2 = X(1)-TranslationU;
0552 v2 = X(2)-TranslationV;
0553
0554 if(aQSurf.TypeQuadric() != GeomAbs_Plane)
0555 {
0556 while(u1-tu1>M_PI) u1-=M_PI+M_PI;
0557 while(tu1-u1>M_PI) u1+=M_PI+M_PI;
0558 }
0559
0560 MyParOnS1.SetCoord(tu1,tv1);
0561 MyParOnS2.SetCoord(tu2,tv2);
0562
0563 gp_Pnt aP2;
0564
0565 ThePSurfaceTool::D1(aPSurf, X(1), X(2), P, aD1uPrm, aD1vPrm);
0566 aQSurf.D1(u1,v1, aP2, aD1uQuad, aD1vQuad);
0567
0568 //Middle-point of P-P2 segment
0569 P.BaryCenter(1.0, aP2, 1.0);
0570 }
0571 else
0572 {
0573 u1 = X(1)-TranslationU;
0574 v1 = X(2)-TranslationV;
0575 //aQSurf.Parameters(P, u2, v2);
0576 if(aQSurf.TypeQuadric() != GeomAbs_Plane)
0577 {
0578 while(u2-tu2>M_PI) u2-=M_PI+M_PI;
0579 while(tu2-u2>M_PI) u2+=M_PI+M_PI;
0580 }
0581
0582 MyParOnS1.SetCoord(tu1,tv1);
0583 MyParOnS2.SetCoord(tu2,tu2);
0584
0585 gp_Pnt aP2;
0586 ThePSurfaceTool::D1(aPSurf, X(1), X(2), P, aD1uPrm, aD1vPrm);
0587
0588 aQSurf.D1(u2, v2, aP2, aD1uQuad, aD1vQuad);
0589
0590 //Middle-point of P-P2 segment
0591 P.BaryCenter(1.0, aP2, 1.0);
0592 }
0593
0594 MyPnt = P;
0595
0596 //Normals to the surfaces
0597 gp_Vec aNormalPrm(aD1uPrm.Crossed(aD1vPrm)),
0598 aNormalImp(aQSurf.Normale(MyPnt));
0599
0600 const Standard_Real aSQMagnPrm = aNormalPrm.SquareMagnitude(),
0601 aSQMagnImp = aNormalImp.SquareMagnitude();
0602
0603 Standard_Boolean isPrmSingular = Standard_False,
0604 isImpSingular = Standard_False;
0605
0606 if(IsSingular(aD1uPrm, aD1vPrm, aNullValue, anAngTol))
0607 {
0608 isPrmSingular = Standard_True;
0609 if(!SingularProcessing(aD1uPrm, aD1vPrm, Standard_True,
0610 aNullValue, anAngTol, Tg, aPrmTg))
0611 {
0612 MyIsTangent = Standard_False;
0613 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0614 return Standard_False;
0615 }
0616
0617 MyTg = Tg;
0618 }
0619 else
0620 {
0621 aNormalPrm.Divide(sqrt(aSQMagnPrm));
0622 }
0623
0624 //Analogically for implicit surface
0625 if(aSQMagnImp < aNullValue)
0626 {
0627 isImpSingular = Standard_True;
0628
0629 if(!SingularProcessing(aD1uQuad, aD1vQuad, !isPrmSingular,
0630 aNullValue, anAngTol, Tg, aQuadTg))
0631 {
0632 MyIsTangent = Standard_False;
0633 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0634 return Standard_False;
0635 }
0636
0637 MyTg = Tg;
0638 }
0639 else
0640 {
0641 aNormalImp.Divide(sqrt(aSQMagnImp));
0642 }
0643
0644 if(isImpSingular && isPrmSingular)
0645 {
0646 //All is OK. All abnormal cases were processed above.
0647
0648 MyTguv1 = Tguv1;
0649 MyTguv2 = Tguv2;
0650
0651 MyIsTangent=Standard_True;
0652 return MyIsTangent;
0653 }
0654 else if(!(isImpSingular || isPrmSingular))
0655 {
0656 //Processing pure non-singular case
0657 //(3D- and 2D-tangents are still not defined)
0658
0659 //Ask to pay attention to the fact that here
0660 //aNormalImp and aNormalPrm are normalized.
0661 //Therefore, @ \left \| \vec{Tg} \right \| = 0.0 @
0662 //if and only if (aNormalImp || aNormalPrm).
0663 Tg = aNormalImp.Crossed(aNormalPrm);
0664 }
0665
0666 const Standard_Real aSQMagnTg = Tg.SquareMagnitude();
0667
0668 if(aSQMagnTg < aNullValue)
0669 {
0670 MyIsTangent = Standard_False;
0671 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0672 return Standard_False;
0673 }
0674
0675 //Normalize Tg vector
0676 Tg.Divide(sqrt(aSQMagnTg));
0677 MyTg = Tg;
0678
0679 if(!isPrmSingular)
0680 {
0681 //If isPrmSingular==TRUE then aPrmTg has already been computed.
0682
0683 if(!NonSingularProcessing(aD1uPrm, aD1vPrm, Tg, aNullValue, anAngTol, aPrmTg))
0684 {
0685 MyIsTangent = Standard_False;
0686 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0687 return Standard_False;
0688 }
0689 }
0690
0691 if(!isImpSingular)
0692 {
0693 //If isImpSingular==TRUE then aQuadTg has already been computed.
0694
0695 if(!NonSingularProcessing(aD1uQuad, aD1vQuad, Tg, aNullValue, anAngTol, aQuadTg))
0696 {
0697 MyIsTangent = Standard_False;
0698 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0699 return Standard_False;
0700 }
0701 }
0702
0703 MyTguv1 = Tguv1;
0704 MyTguv2 = Tguv2;
0705
0706 MyIsTangent=Standard_True;
0707
0708 #ifdef OCCT_DEBUG
0709 //cout << "+++++++++++++++++ ApproxInt_ImpPrmSvSurfaces::Compute(...) ++++++++++" << endl;
0710 //printf( "P2d_1(%+10.20f, %+10.20f); P2d_2(%+10.20f, %+10.20f)\n"
0711 // "P(%+10.20f, %+10.20f, %+10.20f);\n"
0712 // "Tg = {%+10.20f, %+10.20f, %+10.20f};\n"
0713 // "Tguv1 = {%+10.20f, %+10.20f};\n"
0714 // "Tguv2 = {%+10.20f, %+10.20f}\n",
0715 // u1, v1, u2, v2,
0716 // P.X(), P.Y(), P.Z(),
0717 // Tg.X(), Tg.Y(), Tg.Z(),
0718 // Tguv1.X(), Tguv1.Y(), Tguv2.X(), Tguv2.Y());
0719 //cout << "-----------------------------------------------------------------------" << endl;
0720 #endif
0721
0722 return Standard_True;
0723 }
0724 else {
0725 //-- cout<<" ApproxInt_ImpImpSvSurfaces.gxx : Distance apres recadrage Trop Grande "<<endl;
0726
0727 MyIsTangent=Standard_False;
0728 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0729 return Standard_False;
0730 }
0731 }
0732 else {
0733 MyIsTangent = Standard_False;
0734 MyHasBeenComputed = MyHasBeenComputedbis = Standard_False;
0735 return Standard_False;
0736 }
0737 }
0738
0739 //=======================================================================
0740 //function : SeekPoint
0741 //purpose : Computes point on curve and
0742 // parameters on the surfaces.
0743 //=======================================================================
0744 Standard_Boolean ApproxInt_ImpPrmSvSurfaces::SeekPoint(const Standard_Real u1,
0745 const Standard_Real v1,
0746 const Standard_Real u2,
0747 const Standard_Real v2,
0748 IntSurf_PntOn2S& Point) {
0749 gp_Pnt aP;
0750 gp_Vec aT;
0751 gp_Vec2d aTS1,aTS2;
0752 const IntSurf_Quadric& aQSurf = MyZerImpFunc.ISurface();
0753 const ThePSurface& aPSurf = MyZerImpFunc.PSurface();
0754
0755 math_Vector X(1,2);
0756 math_Vector BornInf(1,2), BornSup(1,2), Tolerance(1,2);
0757 //--- ThePSurfaceTool::GetResolution(aPSurf,Tolerance(1),Tolerance(2));
0758 Tolerance(1) = 1.0e-8; Tolerance(2) = 1.0e-8;
0759 Standard_Real binfu,bsupu,binfv,bsupv;
0760 binfu = ThePSurfaceTool::FirstUParameter(aPSurf);
0761 binfv = ThePSurfaceTool::FirstVParameter(aPSurf);
0762 bsupu = ThePSurfaceTool::LastUParameter(aPSurf);
0763 bsupv = ThePSurfaceTool::LastVParameter(aPSurf);
0764 BornInf(1) = binfu; BornSup(1) = bsupu;
0765 BornInf(2) = binfv; BornSup(2) = bsupv;
0766 Standard_Real TranslationU = 0., TranslationV = 0.;
0767
0768 if (!FillInitialVectorOfSolution(u1, v1, u2, v2,
0769 binfu, bsupu, binfv, bsupv,
0770 X,
0771 TranslationU, TranslationV))
0772 return Standard_False;
0773
0774 Standard_Real NewU1, NewV1, NewU2, NewV2;
0775
0776 math_FunctionSetRoot Rsnld(MyZerImpFunc);
0777 Rsnld.SetTolerance(Tolerance);
0778 Rsnld.Perform(MyZerImpFunc,X,BornInf,BornSup);
0779 if(Rsnld.IsDone()) {
0780 MyHasBeenComputed = Standard_True;
0781 Rsnld.Root(X);
0782
0783 MyPnt = ThePSurfaceTool::Value(aPSurf, X(1), X(2));
0784
0785 if(MyImplicitFirst)
0786 {
0787 NewU2 = X(1)-TranslationU;
0788 NewV2 = X(2)-TranslationV;
0789
0790 aQSurf.Parameters(MyPnt, NewU1, NewV1);
0791 //adjust U
0792 if (aQSurf.TypeQuadric() != GeomAbs_Plane)
0793 {
0794 Standard_Real sign = (NewU1 > u1)? -1 : 1;
0795 while (Abs(u1 - NewU1) > M_PI)
0796 NewU1 += sign*(M_PI+M_PI);
0797 }
0798 }
0799 else
0800 {
0801 NewU1 = X(1)-TranslationU;
0802 NewV1 = X(2)-TranslationV;
0803
0804 aQSurf.Parameters(MyPnt, NewU2, NewV2);
0805 //adjust U
0806 if (aQSurf.TypeQuadric() != GeomAbs_Plane)
0807 {
0808 Standard_Real sign = (NewU2 > u2)? -1 : 1;
0809 while (Abs(u2 - NewU2) > M_PI)
0810 NewU2 += sign*(M_PI+M_PI);
0811 }
0812 }
0813 }
0814 else
0815 return Standard_False;
0816
0817 Point.SetValue(MyPnt, NewU1, NewV1, NewU2, NewV2);
0818 return Standard_True;
0819 }
0820 //--------------------------------------------------------------------------------
0821
0822 Standard_Boolean
0823 ApproxInt_ImpPrmSvSurfaces::FillInitialVectorOfSolution(const Standard_Real u1,
0824 const Standard_Real v1,
0825 const Standard_Real u2,
0826 const Standard_Real v2,
0827 const Standard_Real binfu,
0828 const Standard_Real bsupu,
0829 const Standard_Real binfv,
0830 const Standard_Real bsupv,
0831 math_Vector& X,
0832 Standard_Real& TranslationU,
0833 Standard_Real& TranslationV)
0834 {
0835 const ThePSurface& aPSurf = MyZerImpFunc.PSurface();
0836
0837 math_Vector F(1,1);
0838
0839 TranslationU = 0.0;
0840 TranslationV = 0.0;
0841
0842 if(MyImplicitFirst) {
0843 if(u2<binfu-0.0000000001) {
0844 if(ThePSurfaceTool::IsUPeriodic(aPSurf)) {
0845 Standard_Real d = ThePSurfaceTool::UPeriod(aPSurf);
0846 do { TranslationU+=d; } while(u2+TranslationU < binfu);
0847 }
0848 else
0849 return(Standard_False);
0850 }
0851 else if(u2>bsupu+0.0000000001) {
0852 if(ThePSurfaceTool::IsUPeriodic(aPSurf)) {
0853 Standard_Real d = ThePSurfaceTool::UPeriod(aPSurf);
0854 do { TranslationU-=d; } while(u2+TranslationU > bsupu);
0855 }
0856 else
0857 return(Standard_False);
0858 }
0859 if(v2<binfv-0.0000000001) {
0860 if(ThePSurfaceTool::IsVPeriodic(aPSurf)) {
0861 Standard_Real d = ThePSurfaceTool::VPeriod(aPSurf);
0862 do { TranslationV+=d; } while(v2+TranslationV < binfv);
0863 }
0864 else
0865 return(Standard_False);
0866 }
0867 else if(v2>bsupv+0.0000000001) {
0868 if(ThePSurfaceTool::IsVPeriodic(aPSurf)) {
0869 Standard_Real d = ThePSurfaceTool::VPeriod(aPSurf);
0870 do { TranslationV-=d; } while(v2+TranslationV > bsupv);
0871 }
0872 else
0873 return(Standard_False);
0874 }
0875 X(1) = u2+TranslationU;
0876 X(2) = v2+TranslationV;
0877 }
0878 else {
0879 if(u1<binfu-0.0000000001) {
0880 if(ThePSurfaceTool::IsUPeriodic(aPSurf)) {
0881 Standard_Real d = ThePSurfaceTool::UPeriod(aPSurf);
0882 do { TranslationU+=d; } while(u1+TranslationU < binfu);
0883 }
0884 else
0885 return(Standard_False);
0886 }
0887 else if(u1>bsupu+0.0000000001) {
0888 if(ThePSurfaceTool::IsUPeriodic(aPSurf)) {
0889 Standard_Real d = ThePSurfaceTool::UPeriod(aPSurf);
0890 do { TranslationU-=d; } while(u1+TranslationU > bsupu);
0891 }
0892 else
0893 return(Standard_False);
0894 }
0895 if(v1<binfv-0.0000000001) {
0896 if(ThePSurfaceTool::IsVPeriodic(aPSurf)) {
0897 Standard_Real d = ThePSurfaceTool::VPeriod(aPSurf);
0898 do { TranslationV+=d; } while(v1+TranslationV < binfv);
0899 }
0900 else
0901 return(Standard_False);
0902 }
0903 else if(v1>bsupv+0.0000000001) {
0904 if(ThePSurfaceTool::IsVPeriodic(aPSurf)) {
0905 Standard_Real d = ThePSurfaceTool::VPeriod(aPSurf);
0906 do { TranslationV-=d; } while(v1+TranslationV > bsupv);
0907 }
0908 else
0909 return(Standard_False);
0910 }
0911 X(1) = u1+TranslationU;
0912 X(2) = v1+TranslationV;
0913 }
0914
0915 //----------------------------------------------------
0916 //Make a small step from boundaries in order to avoid
0917 //finding "outboundaried" solution (Rsnld -> NotDone).
0918 if (GetUseSolver())
0919 {
0920 Standard_Real du = Max(Precision::Confusion(), ThePSurfaceTool::UResolution(aPSurf, Precision::Confusion()));
0921 Standard_Real dv = Max(Precision::Confusion(), ThePSurfaceTool::VResolution(aPSurf, Precision::Confusion()));
0922 if (X(1) - 0.0000000001 <= binfu) X(1) = X(1) + du;
0923 if (X(1) + 0.0000000001 >= bsupu) X(1) = X(1) - du;
0924 if (X(2) - 0.0000000001 <= binfv) X(2) = X(2) + dv;
0925 if (X(2) + 0.0000000001 >= bsupv) X(2) = X(2) - dv;
0926 }
0927
0928 return Standard_True;
0929 }