// (c) MIT 2003.  All rights reserved.

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	Radian.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	06-XX-98
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:     Geometric modeling utility library for mathematical radians
//
// HISTORY:     11-15-98 archon
//              Incorporated into rec.geo package
//
////////////////////////////////////////////////////////////////////////////////

package rec.geo;

/**
 * Radian handles conversions from degrees in a geographical frame
 *     of reference to radians in a mathematical frame of
 *     reference.  Positive infinity on the x-axis is 0.
 */
public final class Radian
{
  /**
   * Use this function to convert differences of angles
   *     in degrees to radians.
   *
   * @return  0.0 <= return < 2.0 * Math.PI.
   */
  public static double scaleFromDegrees( double degrees )
  {
    return( reduce( 2.0 * Math.PI * degrees / 360.0 ) );
  }

  /**
   * @return  0.0 <= return < 2.0 * Math.PI.
   */
  public static double fromDegrees( double degrees )
  {
    return( reduce( (Math.PI / 2.0)
      - (2.0 * Math.PI * Degree.reduce( degrees ) / 360.0) ) );
  }

  /**
   * @return  0.0 <= return < Math.PI.
   */
  public static double fromSlope( double slope )
  {
    return( reduce( Geometry.angle( new GPoint( 0.0, 0.0 ),
				    new GPoint( 1.0, slope ) ) ) );
  }

  /**
   * @return  0.0 <= return < 2.0 * Math.PI
   */
  public static double fromPoints( GPoint p1, GPoint p2 )
  {
    return( reduce( Geometry.angle( p1, p2 ) ) );
  }

  /**
   * @return  true if angle is between beginAngle and endAngle;
   *     otherwise, false.
   */
  public static boolean isBetween( double beginAngle, double endAngle,
				   double angle )
  {
    // first reduce all the angles
    double begin = reduce( beginAngle );
    double end = reduce( endAngle );
    double a = reduce( angle );

    // normal case
    if( begin < end )
      return( a > begin && a < end );

    // case where begin > end
    return( a > begin || a < end );
  }

  //////////////////////////////////////////////////////////////////////////////

  /**
   * Reduces radians into the range [0.0, 2.0 * Math.PI).
   */
  public static double reduce( double radians )
  {
    if( radians < 0.0 )
      return( reduce( radians + 2.0 * Math.PI ) );

    if( radians >= 2.0 * Math.PI )
      return( reduce( radians - 2.0 * Math.PI ) );

    return( radians );
  }
}

////////////////////////////////////////////////////////////////////////////////
