//ShowTree Tree Visualization System //Copyright (C) 2009 Yuvi Masory // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation, version 3 only. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. package logic.positioningAlgorithms; import java.util.ArrayList; import display.Start; import logic.Node; import logic.treeIterators.PreorderIterator; public class LevelSlide implements PositioningAlgorithm { public void embed(Node r, double s) { double xSep = s; double ySep = Start.Y_SEPARATION; r.assignDepths(); r.assignHeights(); PreorderIterator iter = new PreorderIterator(r); Node cur; while(iter.hasNext()) { cur = iter.next(); cur.setY(0); cur.setX(0); } iter = new PreorderIterator(r); while(iter.hasNext()) { cur = iter.next(); cur.setY(cur.getDepth() * ySep); } int maxHeight = r.getHeight(); ArrayList<ArrayList<Node>> levels = new ArrayList<ArrayList<Node>>(); for(int i = 0; i <= maxHeight; i++) { levels.add(new ArrayList<Node>()); } iter = new PreorderIterator(r); while(iter.hasNext()) { cur = iter.next(); levels.get(cur.getDepth()).add(cur); } for(int i = levels.size() - 1; i >= 0; i--) { double nextPos = 0; ArrayList<Node> level = levels.get(i); for(int j = 0; j < level.size(); j++) { cur = level.get(j); double pos = 0; // putting leaves at next position ensures there is enough area between internal nodes // on a level to fit the leaves if(cur.isLeaf()) { cur.setX(nextPos); } else { if(cur.degree() == 1) { pos = cur.getLeft().getX(); cur.setX(pos); } else { pos = (cur.getLeft().getX() + cur.getRight().getX())/2; cur.setX(pos); } } if(cur.getX() < nextPos) { double shift = nextPos - cur.getX(); cur.setX(pos + shift); shiftLevelStartingAt(levels.get(i + 1), cur.getLeft(), shift); } nextPos = cur.getX() + xSep; } adjustLevel(level, xSep); } } /* * The question really is, where do you put the leaves? * If you do nothing at this point, sticking with the nextPos placement above, you are identical to WS79 Tidy * In this approach we will shift the leaves left or right to its most closely related internal node * */ //FIXME filling of adjacentLeafGroups does not work public void adjustLevel(ArrayList<Node> level, double xSep) { System.out.println("adjusting level: " + level.get(0).getDepth()); ArrayList<ArrayList<Node>> adjacentLeafGroups = new ArrayList<ArrayList<Node>>(); int lSize = level.size(); boolean lastWasInternal = false; ArrayList<Node> curGroup = new ArrayList<Node>(); adjacentLeafGroups.add(curGroup); for(int i = 0; i < lSize; i++) { Node cur = level.get(i); if(cur.isInternal()) { lastWasInternal = true; continue; } else { if(lastWasInternal == false) { curGroup.add(cur); } else { adjacentLeafGroups.add(curGroup); curGroup = new ArrayList<Node>(); adjacentLeafGroups.add(curGroup); } lastWasInternal = false; } } for(int i = 0; i < adjacentLeafGroups.size(); i++) { adjustLeafGroup(adjacentLeafGroups.get(i)); } } public void adjustLeafGroup(ArrayList<Node> group) { for(int i = 0; i < group.size(); i++) { } } // TODO this function can easily be made linear using the mod techniques of WS79 public void shiftLevelStartingAt(ArrayList<Node> level, Node startNode, double shift) { int startNodeIndex = -1; for(int i = 0; i < level.size(); i++) { if(level.get(i) == startNode) { startNodeIndex = i; } } for(int i = startNodeIndex; i < level.size(); i++) { shiftTree(level.get(i), shift); } } public void shiftTree(Node n, double shift) { n.setX(n.getX() + shift); for(int i = 0; i < n.degree(); i++) { shiftTree(n.getChildren().get(i), shift); } } public boolean handlesNodeWidths() { return false; } public boolean isBinary() { return true; } public String toString() { return "2: Level Slide"; } }