import java.lang.*; import java.awt.*; /** * An implementation of Graham's Scan algorithm for 2-d convex hull * * @author Alejo Hausner (ah@cs.princeton.edu) */ public class Graham extends java.applet.Applet implements Runnable { /** * The thread that is running the hull alg. (or null). */ private Thread kicker; public synchronized void println (String s) { System.out.println(s); } /** * Phase of the algorithm: * 0 = ready * 1 = generating points * 2 = scanning for extreme point * 3 = sorting * 4 = building hull * 5 = done */ int phase; /** * the center of the star-shaped polygon obtained after the sort. */ Point pivot; /** * number of points */ int npts; /** * number of valid points */ int nvpts; /** * The data points themselves */ Point pts[] = null; /** * maximum y value during scan for extreme point */ float maxy; /** * index of point with maximum y value during scan for extreme point */ int maxyi; /** * index of current point during any scan */ int curpt; /** * The hull points */ Point hull[] = null; /** * Indexes into original list of points, from which the hull points came. */ int hulli[]; /** * Hull size */ int nhull; /** * The two points being compared during sorting. */ Point p1,p2,p3; /** * The indices of the three points. */ int i1,i2,i3; /** * Various global variables needed for drawing. */ private Image offScreenImage=null; private Dimension offScreenSize; private Graphics offScreenGraphics; int PointLabelWidth,PointLabelHeight,PointLabelLeading,AngleR; Font myFont; Canvas canvas; private Button StartB; private Checkbox PauseC; /** * Returns True if the sequence of points p,q,r form a right-hand turn. */ float ccw (Point p, Point q) { p1 = p; p2 = pivot; p3 = q; return ccw (p, pivot, q); } float ccw (Point p, Point q, Point r) { return (p.x-q.x)*(r.y-q.y) - (p.y-q.y)*(r.x-q.x); } void erase_point_label(Graphics g, int i, int x) { g.clearRect (x,(i+1)*(PointLabelHeight +PointLabelLeading), PointLabelWidth, PointLabelHeight+PointLabelLeading+1); } void draw_point_label (Graphics g, int i, int x) { g.drawString ("(" + pts[i].x + "," + pts[i].y + ")", x, (i+2)*(PointLabelHeight+PointLabelLeading) -PointLabelLeading ); } void swap (Point pts[], int i, int j, boolean draw) { if (draw) { erase_point_label (offScreenGraphics,i,400); erase_point_label (offScreenGraphics,j,400); erase_angle (offScreenGraphics,i); erase_angle (offScreenGraphics,j); } Point tmp = pts[i]; pts[i] = pts[j]; pts[j] = tmp; if (draw) { offScreenGraphics.setColor(Color.blue); draw_point_label (offScreenGraphics, i, 400); draw_point_label (offScreenGraphics, j, 400); show_angle (offScreenGraphics, i); show_angle (offScreenGraphics, j); pause (100); } } float compare (int i, int j) { return ccw (pts[i],pts[j]); } /** * Quick sort pretty much verbatim from Cormen, Leiserson and Rivest */ void quicksort (Point a[], int p, int q) { Point x; int i,j; if (p < q) { x = a[npts] = a[p]; i = p-1; j = q+1; while (true) { while (compare(--j,npts) > 0.0); while (compare(++i,npts) < 0.0); if (i maxy) { erase_h_line (maxyi); draw_point_label (offScreenGraphics, maxyi, 400); maxy = pts[curpt].y; maxyi = curpt; h_line (offScreenGraphics, maxyi, Color.red); draw_point_label (offScreenGraphics, maxyi, 400); } pause(200); } return maxyi; } void display_points (Point pts[], int n) { int i; println (" i x y"); for (i=0; i= 0 && curpt < npts) { h_line (g,curpt, Color.green); show_point (g,curpt,Color.green); draw_point_label (g, curpt, 400); } h_line (g, maxyi, Color.red); show_point (g,maxyi,Color.red); draw_point_label (g, maxyi, 400); } void show_spokes (Graphics g) { int i,x[],y[]; x = new int[npts]; y = new int[npts]; g.setColor(Color.darkGray); for (i=0; i