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

////////////////////////////////////////////////////////////////////////////////
//
// FILE:	Degree.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 geographical degrees
//
// HISTORY:     11-15-98 archon
//              Incorporated into rec.geo package
//
////////////////////////////////////////////////////////////////////////////////

package rec.geo;

/**
 * Degree handles conversions from radians in a mathematical frame
 *     of reference to degrees as seen on a compass.  Positive
 *     on the y-axis is north.
 */
public final class Degree
{
  /**
   * Use this function to convert differences of angles
   *     in radians to degrees.
   *
   * @return  0.0 <= return < 360.0
   */
  public static double scaleFromRadians( double radians )
  {
    return( reduce( 360.0 * radians / (2.0 * Math.PI) ) );
  }

  /**
   * @return  0.0 <= return < 360.0.
   */
  public static double fromRadians( double radians )
  {
    return( reduce( 360.0 * ((2.0 * Math.PI)
      - Radian.reduce( radians + (3.0 / 2.0 * Math.PI) ))
      / (2.0 * Math.PI) ) );
  }

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

  /**
   * @return  0.0 <= return < 360.0.
   */
  public static double fromPoints( GPoint p1, GPoint p2 )
  {
    return( fromRadians( 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 degrees into the range [0.0, 360.0).
   */
  public static double reduce( double degrees )
  {
    if( degrees < 0.0 )
      return( reduce( degrees + 360.0 ) );

    if( degrees >= 360.0 )
      return( reduce( degrees - 360.0 ) );

    return( degrees );
  }
}

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