/
maps/
package mapmaker;

import java.awt.*;

public class MapMath {

  /** returns scalar(a/|a|, b/|b|)
   */
  public static double dirScalar(int[] a, int[] b) {
    if (a.length != b.length)
      throw new IllegalArgumentException();
    double[] scalars = new double[3];
    for (int i = 0; i < a.length; i++) {
      scalars[0] += a[i] * b[i];
      scalars[1] += a[i] * a[i];
      scalars[2] += b[i] * b[i];
    }
    return scalars[0] / Math.sqrt(scalars[1] * scalars[2]);
  } // dirScalar

  /** returns scalar(a/|a|, b/|b|)
   */
  public static double dirScalar(Point a, Point b) {
    int[] aArr = new int[2];
    int[] bArr = new int[2];
    aArr[0] = a.x;
    aArr[1] = a.y;
    bArr[0] = b.x;
    bArr[1] = b.y;
    return dirScalar(aArr, bArr);
  } // dirScalar

  /** performs a partial ascending sort on data, 
   * using comp to compare two objects in data
   */
  public static void partialSort(PartialComparer comp, Object[] data) {
    // implements a select-sort as it works for partial orders too
    for (int pos = 0; pos < data.length - 1; pos++) {
      int lowestPos = pos;
      for (int i = pos + 1; i < data.length; i++)
	if (comp.less(data[i], data[lowestPos]))
	  lowestPos = i;
      // swap lowest object to new position
      Object buf = data[pos];
      data[pos] = data[lowestPos];
      data[lowestPos] = buf;
    }
  } // partialSort

  /** if v1 lies within a Quadrant, returns wether v2 lies within 
   * the opposing Quadrant
   * if v1 lies on an axis, returns wether v2 lies on the 
   * opposing half-plane
   * if v1 is 0, returns false
   */
  public static boolean opposeQuadrant(Point v1, Point v2) {
    if (v1.x == 0)
      return (v1.y * v2.y < 0);
    if (v1.y == 0)
      return (v1.x * v2.x < 0);
    return (v1.x * v2.x < 0) && (v1.y * v2.y < 0);
  } // opposeQuadrant

  /** returns wether the two Vectors v1 and v2 are parallel
   * and point in the same direction
   * @param v1 if 0, returns true
   * @param v2 if 0, returns true
   */
  public static boolean positiveParallel(Point v1, Point v2) {
    boolean parallel = v1.x * v2.y == v1.y * v2.x;
    return parallel && (v1.x * v2.x >= 0) && (v1.y * v2.y >= 0);
  } // positiveParallel

  /** returns the greatest commen divider of a and b;
   * a and b must not both be 0
   */
  public static int gcd(int a, int b) {
    int buf;
    while (a != 0) {
      buf = b % a;
      b = a;
      a = buf;
    }
    return Math.abs(b);
  } // gcd

  /** returns an array containing all points with integer coordinates
   * that lie between start and end, start and end included;
   * the points will be in order from start to end
   */
  public static Point[] meanPoints(Point start, Point end) {
    // (vx, vy) is vector end - start
    int vx = end.x - start.x;
    int vy = end.y - start.y;
    // (dx, dy) is vector of minimum increase
    int gcd = gcd(vx, vy);
    int dx = vx / gcd;
    int dy = vy / gcd;
    Point[] meanPoints = new Point[gcd + 1];
    meanPoints[0] = new Point(start);
    meanPoints[gcd] = new Point(end);
    for (int i = 1; i < gcd; i++)
      meanPoints[i] = new Point(start.x + i * dx,
				start.y + i * dy);
    return meanPoints;
  } // meanPoints

} // MapMath