package perimeter;
import java.io.*;

/**
 * A Java version of the <tt>perimeter</tt> Olden benchmark.
 * <p>
 * The algorithm computes the total perimeter of a region
 * in a binary image represented by a quadtree.  The
 * algorithm was presented in the paper:
 * <p>
 * <cite>
 * Hanan Samet, "Computing Perimeters of Regions in Images
 * Represented by Quadtrees," IEEE Transactions on Pattern
 * Analysis and Machine Intelligence, PAMI-3(6), November, 1981.
 * </cite>
 * <p>
 * The benchmark creates an image, count the number of leaves on the
 * quadtree and then computes the perimeter of the image using Samet's
 * algorithm.
 **/
public class Perimeter
{
  /**
   * The number of levels in the tree/image.
   **/
  private static int levels = 0;
  /**
   * Set to true to print the final result.
   **/
  private static boolean printResult = false;
  /**
   * Set to true to print information messages.
   **/
  private static boolean printMsgs = false;

  /**
   * The entry point to computing the perimeter of an image.
   * @param args the command line arguments
   **/
  public static void main(String args[]) 
  {
    
    parseCmdLine(args);

    int size = 1 << levels;
    int msize = 1 << (levels - 1);
    QuadTreeNode.gcmp = size * 1024;
    QuadTreeNode.lcmp = msize * 1024;
      
    long start0 = System.currentTimeMillis();
    QuadTreeNode tree = 
      QuadTreeNode.createTree(msize, 0, 0, null, Quadrant.cSouthEast, levels);
    long end0 = System.currentTimeMillis();

    long start1 = System.currentTimeMillis();
    int leaves = tree.countTree();
    long end1 = System.currentTimeMillis();

    long start2 = System.currentTimeMillis();
    int perm = tree.perimeter(size);
    long end2 = System.currentTimeMillis();

    if (printResult) {
      System.out.println("Perimeter is " + perm);
      System.out.println("Number of leaves " + leaves);
    }

    if (printMsgs) {
      System.out.println("QuadTree alloc time " + (end0 - start0)/1000.0);
      System.out.println("Count leaves time " + (end1 - start1)/1000.0);
      System.out.println("Perimeter compute time " + (end2 - start2)/1000.0);
    }
    System.out.println("Done!");
  }

  /**
   * Parse the command line options.
   * @param args the command line options.
   **/
  private static final void parseCmdLine(String args[])
  {
    int i = 0;
    String arg;

    while (i < args.length && args[i].startsWith("-")) {
      arg = args[i++];

      if (arg.equals("-l")) {
	if (i < args.length) {
	  levels = new Integer(args[i++]).intValue();
	} else {
	  throw new Error("-l requires the number of levels");
	}
      } else if (arg.equals("-p")) {
	printResult = true;
      } else if (arg.equals("-m")) {
	printMsgs = true;
      } else if (arg.equals("-h")) {
	usage();
      }
    }
    if (levels == 0) usage();
  }

  /**
   * The usage routine which describes the program options.
   **/
  private static final void usage()
  {
    System.err.println("usage: java Perimeter -l <num> [-p] [-m] [-h]");
    System.err.println("    -l number of levels in the quadtree (image size = 2^l)");
    System.err.println("    -p (print the results)");
    System.err.println("    -m (print informative messages)");
    System.err.println("    -h (this message)");
    System.exit(0);
  }
}
