package org.phylowidget.render; import java.util.List; import org.phylowidget.PhyloWidget; import org.phylowidget.tree.PhyloNode; import processing.core.PGraphics; /** * An unrooted radial layout based on the equal-angle algorithm. * @author Greg * */ public class LayoutUnrooted extends LayoutBase { static final float STARTING_ANGLE = (float)-Math.PI/2; @Override public void layoutImpl() { float angle = STARTING_ANGLE + context.config().layoutAngle / 360f * (float)Math.PI*2f; layoutNode((PhyloNode)tree.getRoot(),angle, angle + 2*Math.PI); } @Override public void drawLine(PGraphics canvas, PhyloNode p, PhyloNode c) { canvas.line(c.getX(), c.getY(), p.getX(),p.getY()); } void layoutNode(PhyloNode n, double loAngle, double hiAngle) { if (tree.isRoot(n)) // Set the root to (0,0). { setPosition(n,0,0); } if (tree.isLeaf(n)) // Leaves need no more laying out! return; float numEnclosed = tree.getNumEnclosedLeaves(n); // Total enclosed leaves for this node. double curX = n.getLayoutX(); double curY = n.getLayoutY(); List<PhyloNode> children = tree.getChildrenOf(n); double curAngle = loAngle; for (int i=0; i < children.size(); i++) { PhyloNode child = children.get(i); // Get the % of leaves under this child. float childEnclosed = tree.getNumEnclosedLeaves(child); double childRatio = childEnclosed / numEnclosed; double arcSize = childRatio * (hiAngle-loAngle); // Place this child in the middle of its given arc. double length = child.getBranchLength() * 10; double midAngle = curAngle+arcSize/2; double newX = curX + Math.cos(midAngle)*length; double newY = curY + Math.sin(midAngle)*length; setPosition(child, (float)newX, (float)newY); setAngle(child,(float)midAngle); layoutNode(child,curAngle,curAngle+arcSize); curAngle += arcSize; } } }