import java.util.*; import java.awt.*; class Path { int dimension; Vector step; Arrow endPt; static Path compost; static boolean composting = true; static CompostHeap compostHeap = new CompostHeap(new Path().getClass(), true,2); public void debug(int i, String s) { if (i>=4) System.out.println(s); } public void dbgalloc(int i,String s) { if (i>=3) System.out.println(" "+s); } public Path() { dbgalloc(2,"Made a null path"); } public Path(Arrow arrow) { dimension = arrow.dimension; step = new Vector(); step.addElement(arrow); endPt = new Arrow(arrow); dbgalloc(2,"Made a path from an arrow"); } public Path(Path pathToCopy) { copy(pathToCopy); dbgalloc(2,"...of another path"); } static public Path newPath(Path pathToCopy) { Path ans; if (compostHeap.exists()) { pathToCopy.dbgalloc(2,"Reused a path!"); ans = (Path)compostHeap.likeNew(); ans.copy(pathToCopy); } else { pathToCopy.dbgalloc(2,"Couldn't reuse"); ans = new Path(pathToCopy); } return ans; } public void free() { compostHeap.recycle(this); } public void copy(Path pathToCopy) { int newSteps = pathToCopy.step.size(); dimension = pathToCopy.dimension; if (step == null) step = new Vector(); int oldSteps = step.size(); for (int i=step.size(); i= 0) && (where < step.size()-1)) { Arrow a = (Arrow)step.elementAt(where); Arrow b = (Arrow)step.elementAt(where+1); if (a.posPropTo(b)) { // if (a.color == b.color) { // debug(0,"Coalescing "+where+"="+a+" and "+(where+1)+"="+b); step.setElementAt(a.plus(b), where); b.free(); step.removeElementAt(where+1); ans = true; } // else // System.out.println(where + ": "+ a.color +" != "+b.color); } } return ans; } public boolean LittelArrow(Arrow root, int where) { Arrow straight = (Arrow)step.elementAt(where); Arrow reflected = straight.reflectedThrough(root); Arrow shift = straight.minus(reflected); Szam scale = root.dotProd(root).over( root.dotProd(reflected).times(Szam.TWO)); //shift.over(root); // debug(0,"Flipping the "+th(where)+" step would move by " // +Szam.ONE.over(scale)+" * "+root); if (scale.lessThanEq(Szam.ZERO)) { debug(0,"Don't want to flip the "+th(where)+" step"); return false; } else { if (!scale.lessThan(Szam.ONE)) { // debug(0,"Want to completely flip the "+th(where)+" step"); ((Arrow)step.elementAt(where)).copy(reflected); root.add(shift); shift.free(); return false; } else { // scale = (root.dotProd(root)).over(scale.times(new Szam(2,1))); // debug(0,"Have to break the "+th(where)+" step at "+scale+" along"); step.setElementAt(reflected.scaleBy(scale),where); reflected.free(); ((Arrow)step.elementAt(where)).color = Color.red; // System.out.println( ((Arrow)step.elementAt(where)).color); step.insertElementAt( straight.scaleBy(Szam.ONE.minus(scale)), where+1); ((Arrow)step.elementAt(where+1)).color = Color.black; root.copy(new Arrow(dimension)); return (!coalesce(where-1)); } } } static Szam extent2 = new Szam(0,1); static Szam curExtent = new Szam(0,1); public boolean LittelPiece(Arrow root, Step Where, Step WhereNext) // // This operates destructively on the current Path after the Whereth step, // doing the Littelmann lowering operation in the direction root. // It is assumed when we enter that the point on Path after Where furthest // in the root direction is its first point, with the runnerup in WhereNext // (or WhereNext == -1, in which case LittelPiece determines it). // Where and WhereNext are set appropriately on exit. This speed up // repeated application of the same root. // { int dbg = 2; int where = Where.intValue(); int furthest = where, nextFurthest = WhereNext.intValue(); // debug(dbg,"Into LittelPiece at "+where+","+nextFurthest+" with a " // +step.size()+"-step path, "+this+", to move "+root); boolean haveRunnerUp = false; Arrow soFar = new Arrow(dimension); boolean ans = true; if (nextFurthest > -1) { extent2 = root.dotProd((Arrow) step.elementAt(WhereNext.intValue())); haveRunnerUp = true; } else for (int i=where; i