1 package org.lcsim.recon.tracking.trfcylplane; 2 3 import org.lcsim.recon.tracking.trfbase.Propagator; 4 import org.lcsim.recon.tracking.trfbase.PropDirected; 5 import org.lcsim.recon.tracking.trfbase.PropDir; 6 import org.lcsim.recon.tracking.trfbase.TrackVector; 7 import org.lcsim.recon.tracking.trfbase.TrackDerivative; 8 import org.lcsim.recon.tracking.trfbase.PropStat; 9 import org.lcsim.recon.tracking.trfutil.TRFMath; 10 import org.lcsim.recon.tracking.trfutil.Assert; 11 import org.lcsim.recon.tracking.trfcyl.SurfCylinder; 12 import org.lcsim.recon.tracking.trfzp.SurfZPlane; 13 import org.lcsim.recon.tracking.trfbase.Surface; 14 import org.lcsim.recon.tracking.trfbase.VTrack; 15 import org.lcsim.recon.tracking.trfbase.ETrack; 16 17 /** 18 * Propagates tracks from an ZPlane to a Cylinder in a constant field. 19 *<p> 20 * Propagation will fail if either the origin is not an ZPlane 21 * or destination is not a Cylinder. 22 * Propagator works incorrectly for tracks with very small curvatures. 23 *<p> 24 *@author Norman A. Graf 25 *@version 1.0 26 * 27 */ 28 29 public class PropZCyl extends PropDirected 30 { 31 // Assign track parameter indices. 32 private static final int IX = SurfZPlane.IX; 33 private static final int IY = SurfZPlane.IY; 34 private static final int IDXDZ = SurfZPlane.IDXDZ; 35 private static final int IDYDZ = SurfZPlane.IDYDZ; 36 private static final int IQP_Z = SurfZPlane.IQP; 37 38 private static final int IPHI = SurfCylinder.IPHI; 39 private static final int IZ = SurfCylinder.IZ; 40 private static final int IALF = SurfCylinder.IALF; 41 private static final int ITLM = SurfCylinder.ITLM; 42 private static final int IQPT = SurfCylinder.IQPT; 43 44 // attributes 45 46 private double _bfac; 47 48 // static methods 49 50 // Return the type name. 51 /** 52 *Return a String representation of the class' type name. 53 *Included for completeness with the C++ version. 54 * 55 * @return A String representation of the class' type name. 56 */ 57 public static String typeName() 58 { return "PropZCyl"; 59 } 60 61 // Return the type. 62 /** 63 *Return a String representation of the class' type name. 64 *Included for completeness with the C++ version. 65 * 66 * @return A String representation of the class' type name. 67 */ 68 public static String staticType() 69 { return typeName(); 70 } 71 72 73 74 /** 75 *Construct an instance from a constant solenoidal magnetic field in Tesla. 76 * 77 * @param bfield The magnetic field strength in Tesla. 78 */ 79 public PropZCyl(double bfield) 80 { 81 _bfac = TRFMath.BFAC*bfield; 82 } 83 84 /** 85 *Clone an instance. 86 * 87 * @return A Clone of this instance. 88 */ 89 public Propagator newPropagator( ) 90 { 91 return new PropZCyl( bField() ); 92 } 93 94 /** 95 *Propagate a track without error in the specified direction. 96 * 97 * The track parameters for a cylinder are: 98 * phi z alpha tan(lambda) curvature 99 * 100 * @param trv The VTrack to propagate. 101 * @param srf The Surface to which to propagate. 102 * @param dir The direction in which to propagate. 103 * @return The propagation status. 104 */ 105 public PropStat vecDirProp( VTrack trv, Surface srf, 106 PropDir dir) 107 { 108 TrackDerivative deriv = null; 109 return vecDirProp(trv, srf, dir, deriv); 110 111 } 112 113 /** 114 *Propagate a track without error in the specified direction 115 *and return the derivative matrix in deriv. 116 * 117 * The track parameters for a cylinder are: 118 * phi z alpha tan(lambda) curvature 119 * 120 * @param trv The VTrack to propagate. 121 * @param srf The Surface to which to propagate. 122 * @param dir The direction in which to propagate. 123 * @param deriv The track derivatives to update at the surface srf. 124 * @return The propagation status. 125 */ 126 public PropStat vecDirProp( VTrack trv, Surface srf, 127 PropDir dir,TrackDerivative deriv) 128 { 129 return vecPropagateZCyl( _bfac, trv, srf, dir, deriv ); 130 } 131 132 /** 133 *Return the strength of the magnetic field in Tesla. 134 * 135 * @return The strength of the magnetic field in Tesla. 136 */ 137 public double bField() 138 { 139 return _bfac/TRFMath.BFAC; 140 } 141 142 /** 143 *Return a String representation of the class' type name. 144 *Included for completeness with the C++ version. 145 * 146 * @return A String representation of the class' type name. 147 */ 148 public String type() 149 { return staticType(); 150 } 151 152 /** 153 *output stream 154 * @return A String representation of this instance. 155 */ 156 public String toString() 157 { 158 return "ZPlane-Cylinder propagation with constant " 159 + bField() + " Tesla field"; 160 161 } 162 163 164 //********************************************************************** 165 166 // Private function to propagate a track without error 167 // 168 // The track parameters for a cylinder are: 169 // phi z alpha tan(lambda) curvature 170 // (NOT [. . . lambda .] as in TRF and earlier version of TRF++.) 171 // 172 // If pderiv is nonzero, return the derivative matrix there. 173 // On Cylinder: 174 // r (cm) is fixed 175 // 0 - phi 176 // 1 - z (cm) 177 // 2 - alp 178 // 3 - tlam 179 // 4 - q/pt pt is transverse momentum of a track, q is its charge 180 // On ZPlane: 181 // 0 - x (cm) 182 // 1 - y (cm) 183 // 2 - dx/dz 184 // 3 - dy/dz 185 // 4 - q/p p is momentum of a track, q is its charge 186 // If pderiv is nonzero, return the derivative matrix there. 187 188 private PropStat 189 vecPropagateZCyl( double bfac, VTrack trv, Surface srf, 190 PropDir dir, 191 TrackDerivative deriv ) 192 { 193 194 // construct return status 195 PropStat pstat = new PropStat(); 196 197 // fetch the originating surface and vector 198 Surface srf1 = trv.surface(); 199 TrackVector vec1 = trv.vector(); 200 201 // Check origin is a Zplane. 202 Assert.assertTrue( srf1.pureType().equals(SurfZPlane.staticType()) ); 203 if ( !srf1.pureType( ).equals(SurfZPlane.staticType()) ) 204 return pstat; 205 SurfZPlane szp1 = ( SurfZPlane ) srf1; 206 207 // Check destination is a cylinder. 208 Assert.assertTrue( srf.pureType().equals(SurfCylinder.staticType()) ); 209 if ( !srf.pureType( ).equals(SurfCylinder.staticType()) ) 210 return pstat; 211 SurfCylinder scy2 = ( SurfCylinder ) srf; 212 213 214 // Fetch the z of the plane and the starting track vector. 215 int iz = SurfZPlane.ZPOS; 216 double z = szp1.parameter(iz); 217 218 TrackVector vec = trv.vector(); 219 double x = vec.get(IX); // v 220 double y = vec.get(IY); // z 221 double b = vec.get(IDXDZ); // dv/du 222 double a = vec.get(IDYDZ); // dz/du 223 double e = vec.get(IQP_Z); // q/p 224 225 // Fetch the radii and the starting track vector. 226 int irad = SurfCylinder.RADIUS; 227 double r2 = scy2.parameter(irad); 228 229 int sign_dz = 0; 230 if(trv.isForward()) sign_dz = 1; 231 if(trv.isBackward()) sign_dz = -1; 232 if(sign_dz == 0) 233 { 234 System.out.println("PropZCyl._vec_propagate: Unknown direction of a track "); 235 System.exit(1); 236 } 237 238 // Calculate cylindrical coordinates 239 240 double cnst1=x>0?0.:Math.PI; 241 double cnst2=Math.PI; 242 if(a>0.&&b>0.&&sign_dz>0.) cnst2=0.; 243 if(a<0.&&b>0.&&sign_dz>0.) cnst2=0.; 244 if(a>0.&&b<0.&&sign_dz<0.) cnst2=0.; 245 if(a<0.&&b<0.&&sign_dz<0.) cnst2=0.; 246 247 double sign_y= y>0 ? 1.:-1; 248 double sign_a= a>0 ? 1.:-1; 249 if(y==0) sign_y=0.; 250 if(a==0) sign_a=0.; 251 double atnxy=(x!=0.?Math.atan(y/x):sign_y*Math.PI/2.); 252 double atnab=(b!=0.?Math.atan(a/b):sign_a*Math.PI/2.); 253 254 double phi1= TRFMath.fmod2(atnxy+cnst1,TRFMath.TWOPI); 255 double r1=Math.sqrt(x*x+y*y); 256 // 28jan01 dla 257 // Handle r1 = 0 to avaoid crash later on. 258 if ( r1 < 0.001 ) 259 { 260 return pstat; 261 } 262 double z1=z; 263 double alp1= TRFMath.fmod2(atnab-phi1+cnst2,TRFMath.TWOPI); 264 double tlm1= sign_dz/Math.sqrt(a*a+b*b); 265 double qpt1=e*Math.sqrt((1+a*a+b*b)/(a*a+b*b)); 266 267 268 // Check alpha range. 269 alp1 = TRFMath.fmod2( alp1, TRFMath.TWOPI ); 270 Assert.assertTrue( Math.abs(alp1) <= Math.PI ); 271 272 //if ( trv.is_forward() ) Assert.assertTrue( fabs(alp1) <= PI2 ); 273 //else Assert.assertTrue( fabs(alp1) > PI2 ); 274 275 // Calculate the cosine of lambda. 276 //double clam1 = 1.0/sqrt(1+tlm1*tlm1); 277 278 // Calculate curvature: C = _bfac*(q/p)/cos(lambda) 279 // and its derivatives 280 // Assert.assertTrue( clam1 != 0.0 ); 281 // double dcrv1_dqp1 = bfac/clam1; 282 // double crv1 = dcrv1_dqp1*qp1; 283 // double dcrv1_dtlm1 = crv1*clam1*clam1*tlm1; 284 285 // Calculate the curvature = _bfac*(q/pt) 286 double dcrv1_dqpt1 = bfac; 287 double crv1 = dcrv1_dqpt1*qpt1; 288 //double dcrv1_dtlm1 = 0.0; 289 290 // Evaluate the new track vector. 291 // See dla log I-044 292 293 // lambda and curvature do not change 294 double tlm2 = tlm1; 295 double crv2 = crv1; 296 double qpt2 = qpt1; 297 298 // We can evaluate sin(alp2), leaving two possibilities for alp2 299 // 1st solution: alp21, phi21, phid21, tht21 300 // 2nd solution: alp22, phi22, phid22, tht22 301 // evaluate phi2 to choose 302 double salp1 = Math.sin( alp1 ); 303 double calp1 = Math.cos( alp1 ); 304 double salp2 = r1/r2*salp1 + 0.5*crv1/r2*(r2*r2-r1*r1); 305 // if salp2 > 1, track does not cross cylinder 306 if ( Math.abs(salp2) > 1.0 ) return pstat; 307 double alp21 = Math.asin( salp2 ); 308 double alp22 = alp21>0 ? Math.PI-alp21 : -Math.PI-alp21; 309 double calp21 = Math.cos( alp21 ); 310 double calp22 = Math.cos( alp22 ); 311 double phi20 = phi1 + Math.atan2( salp1-r1*crv1, calp1 ); 312 double phi21 = phi20 - Math.atan2( salp2-r2*crv2, calp21 ); // phi position 313 double phi22 = phi20 - Math.atan2( salp2-r2*crv2, calp22 ); 314 315 // Construct an sT object for each solution. 316 STCalcZ sto1 = new STCalcZ(r1,phi1,alp1,crv1,r2,phi21,alp21); 317 STCalcZ sto2 = new STCalcZ(r1,phi1,alp1,crv1,r2,phi22,alp22); 318 // Check the two solutions are nonzero and have opposite sign 319 // or at least one is nonzero. 320 321 // Choose the correct solution 322 boolean use_first_solution = false; 323 if (dir.equals(PropDir.NEAREST)) 324 { 325 use_first_solution = Math.abs(sto2.st()) > Math.abs(sto1.st()); 326 } 327 else if (dir.equals(PropDir.FORWARD)) 328 { 329 use_first_solution = sto1.st() > 0.0; 330 } 331 else if (dir.equals(PropDir.BACKWARD)) 332 { 333 use_first_solution = sto1.st() < 0.0; 334 } 335 else 336 { 337 System.out.println( "PropCyl._vec_propagate: Unknown direction."); 338 System.exit(1); 339 } 340 341 // Assign phi2, alp2 and sto2 for the chosen solution. 342 double phi2, alp2; 343 STCalcZ sto; 344 double calp2; 345 if ( use_first_solution ) 346 { 347 sto = sto1; 348 phi2 = phi21; 349 alp2 = alp21; 350 calp2 = calp21; 351 } 352 else 353 { 354 sto = sto2; 355 phi2 = phi22; 356 alp2 = alp22; 357 calp2 = calp22; 358 } 359 360 // fetch sT. 361 double st = sto.st(); 362 363 // use sT to evaluate z2 364 double z2 = z1 + tlm1*st; 365 366 // Check alpha range. 367 Assert.assertTrue( Math.abs(alp2) <= Math.PI ); 368 369 // put new values in vec 370 vec.set(IPHI , phi2); 371 vec.set(IZ , z2); 372 vec.set(IALF , alp2); 373 vec.set(ITLM , tlm2); 374 vec.set(IQPT , qpt2); 375 376 // Update trv 377 trv.setSurface(srf.newPureSurface()); 378 trv.setVector(vec); 379 if ( Math.abs(alp2) <= TRFMath.PI2 ) trv.setForward(); 380 else trv.setBackward(); 381 382 // Evaluate s. 383 double s = st*Math.sqrt(1.0+tlm2*tlm2); 384 385 // Set the return status. 386 pstat.setPathDistance(s); 387 //st > 0 ? pstat.set_forward() : pstat.set_backward(); 388 389 // exit now if user did not ask for error matrix. 390 if ( deriv == null ) return pstat; 391 392 // Calculate derivatives. 393 // dphi1 394 395 double dphi1_dx= -y/(x*x+y*y); 396 double dphi1_dy= x/(x*x+y*y); 397 398 // dz1 399 400 //double dz1_dz=0.; 401 402 // dalf1 403 404 double dalp1_da= b/(a*a+b*b); 405 double dalp1_db= -a/(a*a+b*b); 406 double dalp1_dy= -dphi1_dy; 407 double dalp1_dx= -dphi1_dx; 408 409 // dr1 410 411 double dr1_dx= x/Math.sqrt(x*x+y*y); 412 double dr1_dy= y/Math.sqrt(x*x+y*y); 413 414 // dtlm1 415 416 double dtlm1_da= -sign_dz*a/Math.sqrt(a*a+b*b)/(a*a+b*b); 417 double dtlm1_db= -sign_dz*b/(a*a+b*b)/Math.sqrt(a*a+b*b); 418 419 // dcrv1 420 421 double dqpt1_de= Math.sqrt((1+a*a+b*b)/(a*a+b*b)); 422 double dqpt1_da= -a*e/Math.sqrt((a*a+b*b)*(1+a*a+b*b))/(a*a+b*b); 423 double dqpt1_db= -e*b/Math.sqrt(1+a*a+b*b)/Math.sqrt(a*a+b*b)/(a*a+b*b); 424 425 double dcrv1_de= dqpt1_de*bfac; 426 double dcrv1_da= dqpt1_da*bfac; 427 double dcrv1_db= dqpt1_db*bfac; 428 429 // alpha_2 430 double da2da1 = r1*calp1/r2/calp2; 431 double da2dc1 = (r2*r2-r1*r1)*0.5/r2/calp2; 432 double da2dr1 = (salp1-crv2*r1)/r2/calp2; 433 434 // phi2 435 double rcsal1 = r1*crv1*salp1; 436 double rcsal2 = r2*crv2*salp2; 437 double den1 = 1.0 + r1*r1*crv1*crv1 - 2.0*rcsal1; 438 double den2 = 1.0 + r2*r2*crv2*crv2 - 2.0*rcsal2; 439 double dp2dp1 = 1.0; 440 double dp2da1 = (1.0-rcsal1)/den1 - (1.0-rcsal2)/den2*da2da1; 441 double dp2dc1 = -r1*calp1/den1 + r2*calp2/den2 442 - (1.0-rcsal2)/den2*da2dc1; 443 double dp2dr1= -crv1*calp1/den1-(1.0-rcsal2)*da2dr1/den2; 444 445 // z2 446 //double dz2dz1 = 1.0; 447 double dz2dl1 = st; 448 double dz2da1 = tlm1*sto.d_st_dalp1(dp2da1, da2da1); 449 double dz2dc1 = tlm1*sto.d_st_dcrv1(dp2dc1, da2dc1); 450 double dz2dr1 = tlm1*sto.d_st_dr1( dp2dr1, da2dr1); 451 452 453 // final derivatives 454 455 // phi2 456 double dphi2_dx=dp2dp1*dphi1_dx+dp2da1*dalp1_dx+dp2dr1*dr1_dx; 457 double dphi2_dy=dp2dp1*dphi1_dy+dp2da1*dalp1_dy+dp2dr1*dr1_dy; 458 double dphi2_db=dp2da1*dalp1_db+dp2dc1*dcrv1_db; 459 double dphi2_da=dp2da1*dalp1_da+dp2dc1*dcrv1_da; 460 double dphi2_de=dp2dc1*dcrv1_de; 461 462 // alp2 463 double dalp2_dx= da2da1*dalp1_dx+da2dr1*dr1_dx; 464 double dalp2_dy= da2da1*dalp1_dy+da2dr1*dr1_dy; 465 double dalp2_db= da2da1*dalp1_db+da2dc1*dcrv1_db; 466 double dalp2_da= da2da1*dalp1_da+da2dc1*dcrv1_da; 467 double dalp2_de= da2dc1*dcrv1_de; 468 469 // crv2 470 double dqpt2_da=dqpt1_da; 471 double dqpt2_db=dqpt1_db; 472 double dqpt2_de=dqpt1_de; 473 474 // tlm2 475 double dtlm2_da= dtlm1_da; 476 double dtlm2_db= dtlm1_db; 477 478 // z2 479 double dz2_dx= dz2dr1*dr1_dx+dz2da1*dalp1_dx; 480 double dz2_dy= dz2dr1*dr1_dy+dz2da1*dalp1_dy; 481 double dz2_db= dz2da1*dalp1_db+dz2dl1*dtlm1_db+dz2dc1*dcrv1_db; 482 double dz2_da= dz2da1*dalp1_da+dz2dl1*dtlm1_da+dz2dc1*dcrv1_da; 483 double dz2_de= dz2dc1*dcrv1_de; 484 485 486 // Build derivative matrix. 487 488 deriv.set(IPHI,IX , dphi2_dx); 489 deriv.set(IPHI,IY , dphi2_dy); 490 deriv.set(IPHI,IDXDZ, dphi2_db); 491 deriv.set(IPHI,IDYDZ, dphi2_da); 492 deriv.set(IPHI,IQP_Z, dphi2_de); 493 deriv.set(IZ,IX , dz2_dx); 494 deriv.set(IZ,IY , dz2_dy); 495 deriv.set(IZ,IDXDZ , dz2_db); 496 deriv.set(IZ,IDYDZ , dz2_da); 497 deriv.set(IZ,IQP_Z, dz2_de); 498 deriv.set(IALF,IX , dalp2_dx); 499 deriv.set(IALF,IY , dalp2_dy); 500 deriv.set(IALF,IDXDZ , dalp2_db); 501 deriv.set(IALF,IDYDZ , dalp2_da); 502 deriv.set(IALF,IQP_Z , dalp2_de); 503 deriv.set(ITLM,IDXDZ , dtlm2_db); 504 deriv.set(ITLM,IDYDZ , dtlm2_da); 505 deriv.set(IQPT,IDXDZ , dqpt2_db); 506 deriv.set(IQPT,IDYDZ , dqpt2_da); 507 deriv.set(IQPT,IQP_Z , dqpt2_de); 508 509 510 return pstat; 511 512 } 513 514 515 //********************************************************************** 516 // helpers 517 //********************************************************************** 518 519 // Private class STCalcZ. 520 // 521 // An STCalcZ_ object calculates sT (the signed transverse path length) 522 // and its derivatives w.r.t. alf1 and crv1. It is constructed from 523 // the starting (r1, phi1, alf1, crv1) and final track parameters 524 // (r2, phi2, alf2) assuming these are consistent. Methods are 525 // provided to retrieve sT and the two derivatives. 526 527 class STCalcZ 528 { 529 530 private boolean _big_crv; 531 private double _st; 532 private double _dst_dphi21; 533 private double _dst_dcrv1; 534 private double _dst_dr1; 535 private double _cnst1,_cnst2; 536 public double _crv1; 537 // constructor 538 public STCalcZ() 539 { 540 } 541 public STCalcZ(double r1, double phi1, double alf1, double crv1, 542 double r2, double phi2, double alf2) 543 { 544 545 _crv1 = crv1; 546 Assert.assertTrue( r1 > 0.0 ); 547 Assert.assertTrue( r2 > 0.0 ); 548 double rmax = r1+r2; 549 550 // Calculate the change in xy direction 551 double phi_dir_diff = TRFMath.fmod2(phi2+alf2-phi1-alf1,TRFMath.TWOPI); 552 Assert.assertTrue( Math.abs(phi_dir_diff) <= Math.PI ); 553 554 // Evaluate whether |C| is" big" 555 _big_crv = rmax*Math.abs(crv1) > 0.001 || Math.abs(r1-r2)<1.e-9; 556 if( Math.abs(crv1) < 1.e-10 ) _big_crv=false; 557 558 // If the curvature is big we can use 559 // sT = (phi_dir2 - phi_dir1)/crv1 560 if ( _big_crv ) 561 { 562 Assert.assertTrue( crv1 != 0.0 ); 563 _st = phi_dir_diff/crv1; 564 } 565 566 // Otherwise, we calculate the straight-line distance 567 // between the points and use an approximate correction 568 // for the (small) curvature. 569 else 570 { 571 572 // evaluate the distance 573 double d = Math.sqrt( r1*r1 + r2*r2 - 2.0*r1*r2*Math.cos(phi2-phi1) ); 574 double arg = 0.5*d*crv1; 575 double arg2 = arg*arg; 576 double st_minus_d = d*arg2*( 1.0/6.0 + 3.0/40.0*arg2 ); 577 _st = d + st_minus_d; 578 579 // evaluate the sign 580 // We define a metric xsign = abs( (dphid-d*C)/(d*C) ). 581 // Because sT*C = dphid and d = abs(sT): 582 // xsign = 0 for sT > 0 583 // xsign = 2 for sT < 0 584 // Numerical roundoff will smear these predictions. 585 double xsign = (crv1 == 0. ? 0.: Math.abs( (phi_dir_diff - _st*crv1) / (_st*crv1)) ); 586 double sign = 0.0; 587 if ( crv1 != 0 ) 588 { 589 if ( xsign < 0.5 ) sign = 1.0; 590 if ( xsign > 1.5 && xsign < 3.0 ) sign = -1.0; 591 } 592 // If the above is indeterminate, assume zero curvature. 593 // In this case abs(alpha) decreases monotonically 594 // with sT. Track passing through origin has alpha = 0 on one 595 // side and alpha = +/-pi on the other. If both points are on 596 // the same side, we use dr/ds > 0 for |alpha|<pi/2. 597 if ( sign == 0 ) 598 { 599 sign = 1.0; 600 if ( Math.abs(alf2) > Math.abs(alf1) ) sign = -1.0; 601 if ( Math.abs(alf2) == Math.abs(alf1) ) 602 { 603 if ( Math.abs(alf2) < TRFMath.PI2 ) 604 { 605 if ( r2 < r1 ) sign = -1.0; 606 } 607 else 608 { 609 if ( r2 > r1 ) sign = -1.0; 610 } 611 } 612 } 613 614 if ( Math.abs(r2 - r1)<1e-12 && crv1 == 0. && Math.abs(alf1) < TRFMath.PI2 ) sign = -1.0; 615 if ( Math.abs(r2 - r1)<1e-12 && crv1 == 0. && Math.abs(alf1) > TRFMath.PI2 ) sign = 1.0; 616 617 618 // Correct _st using the above sign. 619 Assert.assertTrue( Math.abs(sign) == 1.0 ); 620 _st = sign*_st; 621 622 // save derivatives 623 _dst_dcrv1 = sign*d*d*arg*( 1.0/6.0 + 3.0/20.0*arg2); 624 double root = (1.0 + 0.5*arg*arg + 3.0/8.0*arg*arg*arg*arg ); 625 if( Math.abs(_st) > 1e-11 ) 626 { 627 _dst_dphi21 = sign*(r1*r2*Math.sin(phi2-phi1))*root/d; 628 _dst_dr1= (1.+arg2/2.*(1+3./4.*arg2))/d*sign; 629 _cnst1=r1-r2*Math.cos(phi2-phi1); 630 _cnst2=r1*r2*Math.sin(phi2-phi1); 631 } 632 else 633 { 634 _dst_dphi21= r1; 635 _dst_dr1= sign; 636 _cnst1=0.; 637 _cnst2=0.; 638 } 639 } 640 641 } 642 public double st() 643 { return _st; 644 } 645 public double d_st_dalp1(double d_phi2_dalf1, double d_alf2_dalf1 ) 646 { 647 if ( _big_crv ) return ( d_phi2_dalf1 + d_alf2_dalf1 - 1.0 ) / _crv1; 648 else return _dst_dphi21 * d_phi2_dalf1; 649 } 650 public double d_st_dcrv1(double d_phi2_dcrv1, double d_alf2_dcrv1 ) 651 { 652 if ( _big_crv ) return ( d_phi2_dcrv1 + d_alf2_dcrv1 - _st ) / _crv1; 653 else return _dst_dcrv1 + _dst_dphi21*d_phi2_dcrv1; 654 655 } 656 public double d_st_dr1( double d_phi2_dr1, double d_alf2_dr1 ) 657 { 658 if ( _big_crv ) return ( d_phi2_dr1 + d_alf2_dr1 ) / _crv1; 659 else 660 { 661 if( Math.abs(_cnst2)<1e-12 && Math.abs(_cnst1)<1e-12 ) 662 { 663 return _dst_dr1*Math.sqrt(1. + _dst_dphi21*_dst_dphi21*d_phi2_dr1*d_phi2_dr1); 664 } 665 else 666 return _dst_dr1*(_cnst1+_cnst2*d_phi2_dr1); 667 } 668 669 } 670 671 } 672 673 }