java - recursive method to draw a dendrogram -


i have draw dendrogram :

dendogram

but bigger. there option representation of data clustering. stuck recursive method draw dendrogram.

i principle draw method should like

 draw(cluster){       if(clusters.haschildren()){          draw(cluster.child1)          draw(cluster.child2)       }       //draw actual cluster here     } 

but quite stuck @ implementing it.

my method @ moment looks this

drawcluster(cluster, startx, starty){    if(cluster.haschildren()){       drawcluster, cluster.child1(), cluster.child1().getdepth * 30, height - cluster.child2.getwidth * 20)       drawcluster, cluster.child2(), cluster.child2().getdepth * 30, height - 20)    }    if cluster.getdepth() == 0 )       drawline(500 - 30), height, 500)    else       drawline(500 - (width * 30), height, 500); } 

so space have drawing 500 px in width , height total_number_of_leafs * 20 draw line each cluster distances correct. every time start line @ 500px minus depth of cluster times 20.and draw line 500th pixel.

also height supposed maxheight. example when come draw lets cluster (1,2) height in argument 40. , on.

but not working well. stuck on how change values every time call draw method. need pass more variable other x start of line , y?

any appreciated since have deadline catch.

thanks in advance.

painting dendrogram recursively bit tricky.

the leaf nodes not "know" y-position. additionally, no node "directly" know has painted, , how lines should painted connect children: information not available before leaves (or children of each node, respectively) have been painted.

i think iterative solution easier , more flexible. however, here implementation using recursive approach. note simple implementation, (for example) assumes data structure dendrogram binary tree, should in line example posted.

dendrogram

btw: fills available space, , i'd strongly recommend avoid "magic constants" , assumptions pixel size of nodes or painting area in drawline(500 - (width * 30), height, 500). if not want compute these size of tree , number of leaf nodes, should at least introduce variables can change more later.

import java.awt.graphics; import java.awt.graphics2d; import java.awt.point; import java.util.arraylist; import java.util.collections; import java.util.list;  import javax.swing.jframe; import javax.swing.jpanel; import javax.swing.swingutilities;   public class dendrogrampainttest {     public static void main(string[] args)     {         swingutilities.invokelater(new runnable()         {             @override             public void run()             {                 createandshowgui();             }         });     }      private static void createandshowgui()     {         jframe f = new jframe();         f.setdefaultcloseoperation(jframe.exit_on_close);          dendrogrampaintpanel panel = new dendrogrampaintpanel();         f.getcontentpane().add(panel);          f.setsize(1000,800);         f.setlocationrelativeto(null);         f.setvisible(true);     } }  class node<t>  {     private final t contents;     private final list<node<t>> children;      node(t contents)     {         this.contents = contents;         this.children = collections.emptylist();     }      node(node<t> child0, node<t> child1)     {         this.contents = null;          list<node<t>> list = new arraylist<node<t>>();         list.add(child0);         list.add(child1);         this.children = collections.unmodifiablelist(list);     }      public t getcontents()     {         return contents;     }      public list<node<t>> getchildren()     {         return collections.unmodifiablelist(children);     } }   class dendrogrampaintpanel extends jpanel {     private static <t> node<t> create(t contents)     {         return new node<t>(contents);     }     private static <t> node<t> create(node<t> child0, node<t> child1)     {         return new node<t>(child0, child1);     }       private node<string> root;     private int leaves;     private int levels;     private int heightperleaf;     private int widthperlevel;     private int currenty;     private final int margin = 25;      dendrogrampaintpanel()     {         root =             create(                 create(                     create("10"),                     create(                         create("9"),                         create(                             create("8"),                              create("7")                         )                     )                 ),                 create(                     create(                         create("6"),                         create("5")                     ),                     create(                         create("4"),                         create(                             create("3"),                             create(                                 create("2"),                                 create("1")                             )                         )                     )                 )             );     }      private static <t> int countleaves(node<t> node)     {         list<node<t>> children = node.getchildren();         if (children.size() == 0)         {             return 1;         }         node<t> child0 = children.get(0);         node<t> child1 = children.get(1);         return countleaves(child0) + countleaves(child1);     }      private static <t> int countlevels(node<t> node)     {         list<node<t>> children = node.getchildren();         if (children.size() == 0)         {             return 1;         }         node<t> child0 = children.get(0);         node<t> child1 = children.get(1);         return 1+math.max(countlevels(child0), countlevels(child1));     }       @override     protected void paintcomponent(graphics gr)     {         super.paintcomponent(gr);         graphics2d g = (graphics2d)gr;          leaves = countleaves(root);         levels = countlevels(root);         heightperleaf = (getheight() - margin - margin) / leaves;         widthperlevel = (getwidth() - margin - margin)/ levels;         currenty = 0;          g.translate(margin, margin);         draw(g, root, 0);     }       private <t> point draw(graphics g, node<t> node, int y)     {         list<node<t>> children = node.getchildren();         if (children.size() == 0)         {             int x = getwidth() - widthperlevel - 2 * margin;             g.drawstring(string.valueof(node.getcontents()), x+8, currenty+8);             int resultx = x;             int resulty = currenty;             currenty += heightperleaf;             return new point(resultx, resulty);         }         if (children.size() >= 2)         {             node<t> child0 = children.get(0);             node<t> child1 = children.get(1);             point p0 = draw(g, child0, y);             point p1 = draw(g, child1, y+heightperleaf);              g.fillrect(p0.x-2, p0.y-2, 4, 4);             g.fillrect(p1.x-2, p1.y-2, 4, 4);             int dx = widthperlevel;             int vx = math.min(p0.x-dx, p1.x-dx);             g.drawline(vx, p0.y, p0.x, p0.y);             g.drawline(vx, p1.y, p1.x, p1.y);             g.drawline(vx, p0.y, vx, p1.y);             point p = new point(vx, p0.y+(p1.y - p0.y)/2);             return p;         }         // should never happen         return new point();     } } 

Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -