abstract class Oblig4 { // Required for TegnUt int x[]; int y[]; int n; int MAX_X; int MAX_Y; IntList coHull; NPunkter17 points; String name = "Oblig4"; Oblig4(int[] x, int[] y, int n) { this.x = x; this.y = y; this.n = n; coHull = new IntList(); } // This method should be overwritten by each implementation. // It's responsible for filling in MAX_X, MAX_Y, and coHull abstract void solve(); // We don't want to draw on the main thread. class DrawThread extends Thread { Oblig4 d; DrawThread(Oblig4 d) { this.d = d; } public void run() { try { TegnUt t = new TegnUt(d, coHull, name); t.setVisible(true); } catch (Exception ex) { System.out.println(name+": Couldn't draw window."); } } } // Draw points using TegnUt. // Requires x, y, n, MAX_X, MAX_Y, and coHull // to be filled out. Thread draw() { if (n > 20000) { System.out.println(name+": Too many dots to draw."); return null; } System.out.println(name+" coHull: "); for (int i = 0; i < coHull.size(); ++i) { if (i == 0) System.out.print(coHull.get(i)); else System.out.print(", "+coHull.get(i)); } System.out.println(""); DrawThread t = new DrawThread(this); t.start(); return t; } /* * The rest is utility methods which any implementation will use. */ // a, b, and c will be used in the line equation. // It doesn't make sense to recalculate them all the time, // as they only depend on p1 and p2. int lineA(int p1, int p2) { return y[p1] - y[p2]; } int lineB(int p1, int p2) { return x[p2] - x[p1]; } int lineC(int p1, int p2) { return (y[p2] * x[p1]) - (y[p1] * x[p2]); } // From p1 to p2. // == 0: p3 is on the line. // > 0: p3 is left of the line. // < 0: p3 is right of the line. double lineEquation(int a, int b, int c, int p3) { return (a * x[p3]) + (b * y[p3]) + c; } // Distance between two points double pointDist(int p1, int p2) { int x1 = x[p1], y1 = y[p1]; int x2 = x[p2], y2 = y[p2]; int dx = x2 - x1; int dy = y2 - y1; return Math.abs(Math.sqrt((dx * dx) + (dy * dy))); } // Distance between the line and p3 double dist(double l, int a, int b) { return l / Math.sqrt((a * a) + (b * b)); } // Create a list of points, in sorted order, on the line // given by (a, b, c, p1) IntList addPointsOnLine(IntList indexes, int a, int b, int c, int p1) { IntList l = new IntList(); // Add points on the line between p1 and p2 for (int i = 0; i < indexes.size(); ++i) { int idx = indexes.get(i); double line = lineEquation(a, b, c, idx); if (line == 0) l.add(idx); } // Calculate distances for sorting double[] dists = new double[l.size()]; for (int i = 0; i < l.size(); ++i) { dists[i] = pointDist(p1, l.get(i)); } // Sort points based on distance from p1 // (Bubble sort, but it's usually really few elements) boolean sorted; do { sorted = true; // Loop through points, swap non-sorted ones for (int i = 1; i < l.size(); ++i) { double dist = dists[i]; double prevDist = dists[i - 1]; // Skip if already sorted if (prevDist <= dist) continue; sorted = false; // Swap indexes int tmpi = l.data[i]; l.data[i] = l.data[i - 1]; l.data[i - 1] = tmpi; // Swap distances double tmpd = dists[i]; dists[i] = dists[i - 1]; dists[i - 1] = tmpd; } } while (!sorted); return l; } }