public abstract class Curve { public abstract double x(double t); public abstract double y(double t); // screen coordinates public int x_center; // x-coordinate of the origin public int y_center; // y-coordinate of the origin public int radius; // distance to unit circle public void setScreen(int x_center, int y_center, int radius) { this.x_center = x_center; this.y_center = y_center; this.radius = radius; } private int xScreen(double t) { return (int)Math.round(x_center+radius*x(t)); } private int yScreen(double t) { return (int)Math.round(y_center+radius*y(t)); } // Determine if a curve between t=a and t=b is bent at t=c. // Say it is if C is outside a narrow ellipse. // If it is bent there, subdivide the interval. private SCL bent (double a, double b, double c, SCL list) { int a1 = xScreen(a); int a2 = yScreen(a); int b1 = xScreen(b); int b2 = yScreen(b); int c1 = xScreen(c); int c2 = yScreen(c); double excess = Math.sqrt((a1-c1)*(a1-c1) + (a2-c2)*(a2-c2)) + Math.sqrt((b1-c1)*(b1-c1) + (b2-c2)*(b2-c2)) - Math.sqrt((a1-b1)*(a1-b1) + (a2-b2)*(a2-b2)); if (excess > 0.03) { list = interpolate(list,a,c); list = interpolate(list,c,b); } return list; } // Add to the list the coordinates of the curve (f(t),g(t)) for t // between a and b. It is assumed that the point (f(a),g(a)) is // already on the list. Enough points will be interpolated between a // and b so that the approximating polygon looks like the curve. // The last point to be included will be (f(b),g(b)).} public SCL interpolate (SCL list, double a, double b) { // first try bending it at the midpoint SCL result = bent(a,b,(a+b)/2.0,list); if (result!=list) return result; // now try 4 random points for (int i=0; i<4; ++i) { double t = Math.random(); result = bent(a,b,t*a+(1.0-t)*b,list); if (result!=list) return result; } // for // it's a straight line int b1 = xScreen(b); int b2 = yScreen(b); if ((list.x!= b1 || list.y!=b2) && b1!=Double.NaN && b2!=Double.NaN) list = new SCL(list,b1,b2); return list; // it's a straight line } // interpolate }