/*----------------------------------------------------------------------+ | Title: Phyltree.java | | Java Class | | (used in Phylap.java applet) | | | | Author: David E. Joyce | | Department of Mathematics and Computer Science | | Clark University | | Worcester, MA 01610-1477 | | U.S.A. | | | | http://aleph0.clarku.edu/~djoyce/ | | | | Date: January, 1996, updated November, 2002. | +----------------------------------------------------------------------*/ import java.awt.*; import java.lang.*; /*----------------------------------------------------------------------+ | Class PhylPanel | +----------------------------------------------------------------------*/ public class PhylPanel extends Panel { private Phyltree t; private int displayNumbers; // used when painting the component: // if 0, always display dots; if 1 display numbers // for leaves only; if 2, always display numbers. private int compare[]; // resulting comparison with another tree, if needed public PhylPanel (Phyltree tVal) { t = tVal; setFont(new Font("TimesRoman",Font.PLAIN,10)); } public void setComparison (int[] compareVal) { compare = compareVal; } private double compute_x(int i, double current_x, double dx, int x[], boolean computed[]) { if (computed[i]) return current_x; computed[i]=true; if (i < t.getLeaves()) { x[i] = (int)current_x; current_x += dx; } else { int lj=t.getEldest(i), rj=t.getEldest(i); for (int j = t.getEldest(i); j != -1; j = t.getSib(j)) { current_x = compute_x(j,current_x,dx,x,computed); if (x[j] < x[lj]) lj = j; if (x[j] > x[rj]) rj = j; } if (2.0*t.getHeight(i) == t.getHeight(lj) + t.getHeight(rj)) x[i] = (x[lj]+x[rj])/2; else x[i] = (int)((t.getHeight(i)*(x[lj]+x[rj]) - x[lj]*t.getHeight(rj) - x[rj]*t.getHeight(lj)) / (2.0*t.getHeight(i) - t.getHeight(lj) - t.getHeight(rj))); } // if/else if (t.getParent(i) != -1) current_x = compute_x(t.getParent(i),current_x,dx,x,computed); return current_x; } // compute_x private void drawNumber(Graphics g, int i, int x, int y, Color bg) { String digits = Integer.toString(i); Color curColor = g.getColor(); g.setColor(bg); FontMetrics fm = g.getFontMetrics(); int w = fm.stringWidth(digits)+10; int h = fm.getHeight()+4; g.fillRoundRect(x-w/2+1,y-h/2, w-3,h-1, 6,5); g.setColor(curColor); g.drawRoundRect(x-w/2+1,y-h/2, w-3,h-1, 6,5); g.drawString(digits, x-(w-10)/2, y-(h-4)/2 + fm.getAscent()); } // drawNumber private void drawScale(Graphics g, double max, int x0, int x1, int y0, int y1) { double logmax = Math.log(max)/Math.log(10.0); double base = Math.pow(10.0,Math.floor(logmax)); g.setColor(Color.black); g.drawLine(x1,y0,x1,y1); FontMetrics fm = g.getFontMetrics(); int h = fm.getHeight()/3; for (int i=0; i<10; ++i) { int x = x0; double numeral = Math.round(i*base); if (numeral > t.getTreeHeight()) { numeral /= 10.0; x += 4; } int y = y0-(int)((y0-y1)*numeral/max); if (i==1 || i==2 || i==3 || i==5) { Double dnum = new Double(numeral); String digits = dnum.toString(); g.drawString(digits, x, y+h); x += fm.stringWidth(digits) + 2; } else x += 8; if (x < x1) g.drawLine(x,y,x1,y); } // for } // drawScale private void drawCurve(Graphics g, int theta, int a, int b, int c, int d) { if (theta == 0.0 || Math.abs(a-c)<=1 || Math.abs(b-d)<=1) g.drawLine(a,b,c,d); else { double thetaRad = Math.PI*theta/180.0; int r = (int)((a-c)/(1.0-Math.cos(thetaRad))); r = Math.abs(r); int s = (int)((b-d)/Math.sin(thetaRad)); if (a > c) g.drawArc(a-2*r,b-s,2*r,2*s,0,theta); else g.drawArc(a,b-s,2*r,2*s,180-theta,theta); } // if/else } // drawCurve public void update(Graphics g) { int n = t.getLeaves(); displayNumbers = (n>25)? 0 : 1; int assigned = t.getAssigned(); double treeHeight = t.getTreeHeight(); Color bg = getBackground(); Dimension d = getSize(); int h = d.height; int w = d.width; g.setColor(bg); g.fillRect(0,0,w,h); double dx = w/(n+1.0); int border = (int)(dx/2.0); // select a convenient vertical scale and draw it drawScale (g,treeHeight,0,(int)dx,h-border,border); // first determine the coordinates of the vertices int i,j; boolean computed[] = new boolean[assigned]; for (i=0; i0) g.setColor(Color.red); else g.setColor(Color.green); drawCurve(g,45, x[i],y[i], x[j],y[j]); } // draw the vertices for (i=0; i 0) g.setColor(Color.red); else g.setColor(Color.green); if (displayNumbers==1 || (displayNumbers==1 && i