Path.java :  » Game » rugl » com » ryanm » util » march » Java Open Source

Java Open Source » Game » rugl 
rugl » com » ryanm » util » march » Path.java

package com.ryanm.util.march;

import java.awt.Point;
import java.awt.Polygon;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * Combines a sequence of directions into a path that is rooted at
 * some point in the plane. No restrictions are placed on paths; they
 * may be zero length, open/closed, self-intersecting. Path objects
 * are immutable.
 * 
 * @author Tom Gibara
 */

public class Path
{

  // statics

  private static final double ADJ_LEN = Math.sqrt( 2.0 ) / 2.0 - 1;

  // fields

  private final Direction[] directions;

  private final List<Direction> directionList;

  private final double length;

  private final int originX;

  private final int originY;

  private final int terminalX;

  private final int terminalY;

  // constructors

  private Path( Path that, int deltaX, int deltaY )
  {
    directions = that.directions;
    directionList = that.directionList;
    length = that.length;
    originX = that.originX + deltaX;
    originY = that.originY + deltaY;
    terminalX = that.terminalX + deltaX;
    terminalY = that.terminalY + deltaY;
  }

  /**
   * Constructs a path which starts at the specified point in the
   * plane. The array may be zero length.
   * 
   * @param startX
   *           the x coordinate of the path's origin in the plane
   * @param startY
   *           the y coordinate of the path's origin in the plane
   * @param directions
   *           an array of directions, never null
   */

  public Path( int startX, int startY, Direction[] directions )
  {
    originX = startX;
    originY = startY;
    this.directions = directions.clone();
    directionList = Collections.unmodifiableList( Arrays.asList( directions ) );

    int endX = startX;
    int endY = startY;
    int diagonals = 0;
    for( Direction direction : directions )
    {
      endX += direction.screenX;
      endY += direction.screenY;
      if( direction.screenX != 0 && direction.screenY != 0 )
      {
        diagonals++;
      }
    }

    terminalX = endX;
    terminalY = endY;

    length = directions.length + diagonals * ADJ_LEN;
  }

  /**
   * Convenience constructor that converts the supplied direction
   * list into an array which is then passed to another constructor.
   * 
   * @param startX
   *           the x coordinate of the path's origin in the plane
   * @param startY
   *           the y coordinate of the path's origin in the plane
   * @param directions
   *           a list of the directions in the path
   */

  public Path( int startX, int startY, List<Direction> directions )
  {
    this( startX, startY, directions.toArray( new Direction[ directions.size() ] ) );
  }

  /**
   * Constructs the {@link Polygon} of this path, in screen
   * coordinates
   * 
   * @return The {@link Polygon} bounded by this path
   */
  public Polygon buildShape()
  {
    List<Point> verts = new LinkedList<Point>();
    Point cursor = new Point( originX, -originY );
    Direction currentDir = directions[ 0 ];

    verts.add( new Point( cursor ) );

    for( int i = 0; i < directions.length; i++ )
    {
      if( directions[ i ] != currentDir )
      {
        verts.add( new Point( cursor ) );
        currentDir = directions[ i ];
      }

      cursor.x += directions[ i ].screenX;
      cursor.y += directions[ i ].screenY;
    }

    int[] xp = new int[ verts.size() ];
    int[] yp = new int[ verts.size() ];
    int i = 0;

    for( Point p : verts )
    {
      xp[ i ] = p.x;
      yp[ i ] = p.y;
      i++;
    }

    return new Polygon( xp, yp, xp.length );
  }

  // accessors

  /**
   * @return an immutable list of the directions that compose this
   *         path, never null
   */

  public List<Direction> getDirections()
  {
    return directionList;
  }

  /**
   * @return the x coordinate in the plane at which the path begins
   */

  public int getOriginX()
  {
    return originX;
  }

  /**
   * @return the y coordinate in the plane at which the path begins
   */

  public int getOriginY()
  {
    return originY;
  }

  /**
   * @return the x coordinate in the plane at which the path ends
   */

  public int getTerminalX()
  {
    return terminalX;
  }

  /**
   * @return the y coordinate in the plane at which the path ends
   */

  public int getTerminalY()
  {
    return terminalY;
  }

  /**
   * @return the length of the path using the standard euclidean
   *         metric
   */

  public double getLength()
  {
    return length;
  }

  /**
   * @return true if and only if the path's point of origin is the
   *         same as that of its point of termination
   */

  public boolean isClosed()
  {
    return originX == terminalX && originY == terminalY;
  }

  // methods

  /**
   * Creates a new path by translating this path in the plane.
   * 
   * @param deltaX
   *           the change in the path's x coordinate
   * @param deltaY
   *           the change in the path's y coordinate
   * @return a new path whose origin has been translated
   */

  public Path translate( int deltaX, int deltaY )
  {
    return new Path( this, deltaX, deltaY );
  }

  // TODO add rotate, mirror and reverse methods

  // object methods

  /**
   * Two paths are equal if they have the same origin and the same
   * directions.
   */

  @Override
  public boolean equals( Object obj )
  {
    if( obj == this )
    {
      return true;
    }
    if( !( obj instanceof Path ) )
    {
      return false;
    }
    Path that = ( Path ) obj;

    if( originX != that.originX )
    {
      return false;
    }
    if( originY != that.originY )
    {
      return false;
    }
    if( terminalX != that.terminalX )
    {
      return false; // optimization
    }
    if( terminalY != that.terminalY )
    {
      return false; // optimization
    }
    if( !Arrays.equals( directions, that.directions ) )
    {
      return false;
    }

    return true;
  }

  @Override
  public int hashCode()
  {
    return originX ^ 7 * originY ^ directions.hashCode();
  }

  @Override
  public String toString()
  {
    return "X: " + originX + ", Y: " + originY + " " + Arrays.toString( directions );
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.