package myGraphics.Shape3d; import java.lang.System; public class Path { // globals and constants public static final int MAX_ENTRIES = 50; public static int BEZIER_STEPS = 10; // the path table protected PathTableEntry table[] = new PathTableEntry[MAX_ENTRIES]; // state information for path table public int tableSize = 0; public int pathPosition = 0; public double x_cur = 0.0, y_cur = 0.0; // variables for creating bezier curves protected double t = 0.0; protected double Cx[] = new double[4]; // Cx, Cy: coefficient arrays protected double Cy[] = new double[4]; public Path() { table = new PathTableEntry[MAX_ENTRIES]; tableSize = 0; pathPosition = 0; x_cur = 0.0; y_cur = 0.0; t = 0.0; Cx = new double[4]; Cy = new double[4]; for (int i = 0; i < 4; i++) { Cx[i] = 0.0; Cy[i] = 0.0; } } public Path copy() { Path target = new Path(); for (int i = 0; table[i].opcode != PathTableEntry.OP_NULL; i++) { target.table[i] = table[i].copy(); } target.tableSize = tableSize; target.pathPosition = pathPosition; target.x_cur = x_cur; target.y_cur = y_cur; target.t = t; for (int j = 0; j < 4; j++) { target.Cx[j] = Cx[j]; target.Cy[j] = Cy[j]; } return target; } // methods for filling up the path table public boolean moveTo(double the_x1, double the_y1) { table[pathPosition] = new PathTableEntry(); table[pathPosition].opcode = PathTableEntry.OP_MOVE_TO; table[pathPosition].x1 = the_x1; table[pathPosition].y1 = the_y1; tableSize++; pathPosition++; return true; } public boolean lineTo(double the_x2, double the_y2) { table[pathPosition] = new PathTableEntry(); table[pathPosition].opcode = PathTableEntry.OP_LINE_TO; table[pathPosition].x2 = the_x2; table[pathPosition].y2 = the_y2; tableSize++; pathPosition++; return true; } public boolean bezierTo(double the_x2, double the_y2, double the_x3, double the_y3, double the_x4, double the_y4) { table[pathPosition] = new PathTableEntry(); table[pathPosition].opcode = PathTableEntry.OP_BEZIER_TO; table[pathPosition].x2 = the_x2; table[pathPosition].y2 = the_y2; table[pathPosition].x3 = the_x3; table[pathPosition].y3 = the_y3; table[pathPosition].x4 = the_x4; table[pathPosition].y4 = the_y4; tableSize++; pathPosition++; return true; } public boolean terminatePath() { table[pathPosition] = new PathTableEntry(); table[pathPosition].opcode = PathTableEntry.OP_NULL; pathPosition = 0; return true; } // methods called while interpreting the path table protected boolean handleMoveTo(double the_x1, double the_y1) { x_cur = the_x1; y_cur = the_y1; pathPosition++; return true; } protected boolean handleLineTo(double the_x2, double the_y2) { x_cur = the_x2; y_cur = the_y2; pathPosition++; return true; } protected boolean handleBezierTo(double the_x2, double the_y2, double the_x3, double the_y3, double the_x4, double the_y4) { if (t == 0.0) { // starting this bezier curve // Initialize the coefficient array Cx = new double[4]; Cy = new double[4]; Cx[3] = -x_cur + 3 * (the_x2 - the_x3) + the_x4; Cx[2] = 3 * x_cur - 6 * the_x2 + 3 * the_x3; Cx[1] = -3 * x_cur + 3 * the_x2; Cx[0] = x_cur; Cy[3] = -y_cur + 3 * (the_y2 - the_y3) + the_y4; Cy[2] = 3 * y_cur - 6 * the_y2 + 3 * the_y3; Cy[1] = -3 * y_cur + 3 * the_y2; Cy[0] = y_cur; } t += 1.0 / (double) BEZIER_STEPS; double t2 = t * t; double t3 = t2 * t; x_cur = Cx[3] * t3 + Cx[2] * t2 + Cx[1] * t + Cx[0]; y_cur = Cy[3] * t3 + Cy[2] * t2 + Cy[1] * t + Cy[0]; if (t >= 1.0) { // finished with this bezier curve t = 0.0; pathPosition++; } return true; } // public interface to the path table interpreter public boolean start() { pathPosition = 0; t = 0.0; if (tableSize <= 0 || table[0].opcode != PathTableEntry.OP_MOVE_TO) { // this is an error return false; } else { return true; } } public boolean next() { switch (table[pathPosition].opcode) { case PathTableEntry.OP_NULL: return false; case PathTableEntry.OP_MOVE_TO: return handleMoveTo(table[pathPosition].x1, table[pathPosition].y1); case PathTableEntry.OP_LINE_TO: return handleLineTo(table[pathPosition].x2, table[pathPosition].y2); case PathTableEntry.OP_BEZIER_TO: return handleBezierTo(table[pathPosition].x2, table[pathPosition].y2, table[pathPosition].x3, table[pathPosition].y3, table[pathPosition].x4, table[pathPosition].y4); default: // This is an error // I should probably do something more helpful than just returning false. System.out.println("Attempted to read illegal Path Table opcode"); return false; } } public double x() { return x_cur; } public double y() { return y_cur; } }