package hirondelle.starfield.physics;

/** Apply the physics of a Lorentz Boost to a star. */
final class Boost {
  
  /** 
   Account for changes the star's direction (aberration), brightness (magnitude), and surface temperature (color).
   @param aBeta is the speed related to the Lorentz boost. 
  */
  BoostedStar applyBoostTo(Star aStar, double aBeta){
    BoostedStar result = new BoostedStar();
    double theta = Math.PI/2 - aStar.Declination; // for motion towards the North Celestial Pole only
    double thetaPrime= aberrationDecr(theta, aBeta);
    double dopplerFactor = doppler(aBeta, thetaPrime);
    result.Magnitude = aStar.Magnitude + deltaMagnitude(dopplerFactor, aStar.Temperature);
    result.ThetaPrime = thetaPrime;
    result.Temperature = dopplerFactor * aStar.Temperature;
    return result;
  }

  // PRIVATE
  
  /** Aberration formula that decreases theta. Returns radians, 0..pi.  */
  private double aberrationDecr(double aTheta, double aBeta){
    double costhetaprime = (Math.cos(aTheta) + aBeta)/(1.0D+aBeta*Math.cos(aTheta));
    return Math.acos(costhetaprime);
  }

  /** Lorentz factor. */
  private double gamma(double aBeta){
    double radical = 1 - aBeta*aBeta;
    return 1.0D/Math.sqrt(radical);
  }

  /** The doppler factor at the given (aberrated) angle. */
  private double doppler(double aBeta, double aTheta){
    double gammaVal=gamma(aBeta);
    double  denom=gammaVal*(1-aBeta*Math.cos(aTheta));
    return 1.0D/denom;
  }

  /** The McKinley-Doherty (1979) formula for the change in stellar magnitude. This is an approximation. */
  private double deltaMagnitude(double aDoppler, double aTemperature){
    return 2.5*Math.log10(aDoppler) - 26000*(1/aTemperature - 1/(aDoppler*aTemperature));
  }
  
}