/** * Recursive traverse of tree to determine selections A leaf is selected if rsm is selected. * Nonleaf nodes are selected if all children are selected. * * @param tn node in the tree for which to determine selection * @param nodeidx the ordinal postion in the segments array * @param gsm the graph segments selection model * @param rsm the table row selection model * @return true if given node tn is selected, else false */ private boolean selTraverse( TreeNode tn, int[] nodeidx, ListSelectionModel gsm, ListSelectionModel rsm) { boolean selected = true; if (!tn.isLeaf()) { // A nonleaf node is selected if all its children are selected. for (int i = 0; i < tn.getChildCount(); i++) { TreeNode cn = tn.getChildAt(i); selected &= selTraverse(cn, nodeidx, gsm, rsm); } } else { if (tn instanceof RowCluster) { // get the row index of the leaf node int ri = ((RowCluster) tn).getIndex(); // A leaf is selected if its row is selected in the row selection rsm. selected = rsm.isSelectedIndex(ri); } } // Get the offset into the segments array int idx = nodeidx[0] * segOffset; if (selected) { gsm.addSelectionInterval(idx, idx + (segOffset - 1)); } else { gsm.removeSelectionInterval(idx, idx + (segOffset - 1)); } // Increment the nodeidx in the tree nodeidx[0]++; return selected; }
/** * Return a count of this node and all its descendents. * * @param node A node in the Treemodel. * @return The number of nodes in this branch of the Treemodel. */ private static int getNodeCount(TreeNode tn) { int nc = 1; // this node if (!tn.isLeaf()) { for (int i = 0; i < tn.getChildCount(); i++) { TreeNode cn = tn.getChildAt(i); nc += getNodeCount(cn); } } return nc; }
/** * Return the number of leaf nodes that descend from the given node. * * @param node A node in the Treemodel. * @return The number of leaf nodes that descend from the given node. */ private static int getLeafCount(TreeNode tn) { int lc = 0; if (!tn.isLeaf()) { for (int i = 0; i < tn.getChildCount(); i++) { TreeNode cn = tn.getChildAt(i); lc += getLeafCount(cn); } } else { lc = 1; } return lc; }
/** * Traververse the tree selecting rows coresponding to leaf nodes of the given node tn * * @param tn the node from which to start traversing * @param rsm the selection model in which to mark selected rows */ private void selectTraverse(TreeNode tn, ListSelectionModel rsm) { if (!tn.isLeaf()) { for (int i = 0; i < tn.getChildCount(); i++) { TreeNode cn = tn.getChildAt(i); selectTraverse(cn, rsm); } } else { if (tn instanceof RowCluster) { int ri = ((RowCluster) tn).getIndex(); rsm.addSelectionInterval(ri, ri); } } }
/** * Traverse the tree creating dendogram graph line segments, a nodemap, and a leafmap. Traversal * is depth first. return child position currentleafcnt * * @param tn the tree node to traverse * @param leafcnt the leafcount prior to this node * @param parentDistance the distance of the parent node * @param nodeidx the current node index, incremented after each node is traversed * @param nodemap an ordered list of nodes traversed * @param leafmap an order list of row indices to the leafnode traversed * @param segs line segments comprising the dendogram * @param childpos position of child node returned to parent * @return the leafcount after traversing this node */ private int traverse( TreeNode tn, int leafcnt, double parentDistance, int[] nodeidx, TreeNode[] nodemap, int[] leafmap, double[] segs, double childpos[]) { int lc = leafcnt; double distance = 0.; double height = 0.; double minChildx = Double.NaN; double maxChildx = Double.NaN; double minChildy = Double.NaN; double maxChildy = Double.NaN; if (tn instanceof Cluster) { distance = ((Cluster) tn).getSimilarity(); } else { distance = ((DefaultMutableTreeNode) tn).getDepth(); } if (!tn.isLeaf()) { for (int i = 0; i < tn.getChildCount(); i++) { TreeNode cn = tn.getChildAt(i); lc = traverse(cn, lc, distance, nodeidx, nodemap, leafmap, segs, childpos); if (Double.isNaN(minChildx) || childpos[0] < minChildx) { minChildx = childpos[0]; } if (Double.isNaN(maxChildx) || childpos[0] > maxChildx) { maxChildx = childpos[0]; } if (Double.isNaN(minChildy) || childpos[1] < minChildy) { minChildy = childpos[1]; } if (Double.isNaN(maxChildy) || childpos[1] > maxChildy) { maxChildy = childpos[1]; } } } else { if (tn instanceof RowCluster) { leafmap[lc] = ((RowCluster) tn).getIndex(); } minChildx = distance; maxChildx = distance; minChildy = lc; maxChildy = lc; lc++; } // offset into segs int offset = nodeidx[0] * segOffset * 4; nodemap[nodeidx[0]] = tn; nodeidx[0]++; if (segs.length < offset + 8) { double tmp[] = segs; segs = new double[offset + 8]; System.arraycopy(tmp, 0, segs, 0, tmp.length); } // segment from minchild to maxchild segs[offset++] = distance; // X segs[offset++] = minChildy; // Y segs[offset++] = distance; // X segs[offset++] = maxChildy; // Y // segment from node to parent of length distance // postision half way between first and last child double y = minChildy + (maxChildy - minChildy) / 2.; segs[offset++] = distance; // X segs[offset++] = y; // Y segs[offset++] = parentDistance; // X segs[offset++] = y; // Y /* System.err.println(tn.toString() + " \tmlc " + leafcnt + " lc " + lc + " pd " + parentDistance + " d " + distance); for (int i = 8, j = leafcnt * 8; i < 8; i++,j++) { System.err.print("\t" + segs[j]); } System.err.println(""); */ // Update return values childpos[0] = distance; childpos[1] = y; return lc; }