@@ -739,6 +739,244 @@ function d3_layout_hierarchyValue(d) {
739739function d3_layout_hierarchySort ( a , b ) {
740740 return b . value - a . value ;
741741}
742+ // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
743+ d3 . layout . tree = function ( ) {
744+ var hierarchy = d3 . layout . hierarchy ( ) ,
745+ separation = d3_layout_treeSeparation ,
746+ size = [ 1 , 1 ] ; // width, height
747+
748+ function tree ( d , i ) {
749+ var nodes = hierarchy . call ( this , d , i ) ,
750+ root = nodes [ 0 ] ;
751+
752+ function firstWalk ( node , previousSibling ) {
753+ var children = node . children ,
754+ layout = node . _tree ;
755+ if ( children ) {
756+ var n = children . length ,
757+ firstChild = children [ 0 ] ,
758+ previousChild ,
759+ ancestor = firstChild ,
760+ child ,
761+ i = - 1 ;
762+ while ( ++ i < n ) {
763+ child = children [ i ] ;
764+ firstWalk ( child , previousChild ) ;
765+ ancestor = apportion ( child , previousChild , ancestor ) ;
766+ previousChild = child ;
767+ }
768+ d3_layout_treeShift ( node ) ;
769+ var midpoint = .5 * ( firstChild . _tree . prelim + child . _tree . prelim ) ;
770+ if ( previousSibling ) {
771+ layout . prelim = previousSibling . _tree . prelim + separation ( node , previousSibling ) ;
772+ layout . mod = layout . prelim - midpoint ;
773+ } else {
774+ layout . prelim = midpoint ;
775+ }
776+ } else {
777+ if ( previousSibling ) {
778+ layout . prelim = previousSibling . _tree . prelim + separation ( node , previousSibling ) ;
779+ }
780+ }
781+ }
782+
783+ function secondWalk ( node , x ) {
784+ node . x = node . _tree . prelim + x ;
785+ var children = node . children ;
786+ if ( children ) {
787+ var i = - 1 ,
788+ n = children . length ;
789+ x += node . _tree . mod ;
790+ while ( ++ i < n ) {
791+ secondWalk ( children [ i ] , x ) ;
792+ }
793+ }
794+ }
795+
796+ function apportion ( node , previousSibling , ancestor ) {
797+ if ( previousSibling ) {
798+ var vip = node ,
799+ vop = node ,
800+ vim = previousSibling ,
801+ vom = node . parent . children [ 0 ] ,
802+ sip = vip . _tree . mod ,
803+ sop = vop . _tree . mod ,
804+ sim = vim . _tree . mod ,
805+ som = vom . _tree . mod ,
806+ shift ;
807+ while ( vim = d3_layout_treeRight ( vim ) , vip = d3_layout_treeLeft ( vip ) , vim && vip ) {
808+ vom = d3_layout_treeLeft ( vom ) ;
809+ vop = d3_layout_treeRight ( vop ) ;
810+ vop . _tree . ancestor = node ;
811+ shift = vim . _tree . prelim + sim - vip . _tree . prelim - sip + separation ( vim , vip ) ;
812+ if ( shift > 0 ) {
813+ d3_layout_treeMove ( d3_layout_treeAncestor ( vim , node , ancestor ) , node , shift ) ;
814+ sip += shift ;
815+ sop += shift ;
816+ }
817+ sim += vim . _tree . mod ;
818+ sip += vip . _tree . mod ;
819+ som += vom . _tree . mod ;
820+ sop += vop . _tree . mod ;
821+ }
822+ if ( vim && ! d3_layout_treeRight ( vop ) ) {
823+ vop . _tree . thread = vim ;
824+ vop . _tree . mod += sim - sop ;
825+ }
826+ if ( vip && ! d3_layout_treeLeft ( vom ) ) {
827+ vom . _tree . thread = vip ;
828+ vom . _tree . mod += sip - som ;
829+ ancestor = node ;
830+ }
831+ }
832+ return ancestor ;
833+ }
834+
835+ // Initialize temporary layout variables.
836+ d3_layout_treeVisitAfter ( root , function ( node , previousSibling ) {
837+ node . _tree = {
838+ ancestor : node ,
839+ prelim : 0 ,
840+ mod : 0 ,
841+ change : 0 ,
842+ shift : 0 ,
843+ number : previousSibling ? previousSibling . _tree . number + 1 : 0
844+ } ;
845+ } ) ;
846+
847+ // Compute the layout using Buchheim et al.'s algorithm.
848+ firstWalk ( root ) ;
849+ secondWalk ( root , - root . _tree . prelim ) ;
850+
851+ // Compute the left-most, right-most, and depth-most nodes for extents.
852+ var left = d3_layout_treeSearch ( root , d3_layout_treeLeftmost ) ,
853+ right = d3_layout_treeSearch ( root , d3_layout_treeRightmost ) ,
854+ deep = d3_layout_treeSearch ( root , d3_layout_treeDeepest ) ,
855+ x0 = left . x - separation ( left , right ) / 2 ,
856+ x1 = right . x + separation ( right , left ) / 2 ,
857+ y1 = deep . depth ;
858+
859+ // Clear temporary layout variables; transform x and y.
860+ d3_layout_treeVisitAfter ( root , function ( node ) {
861+ node . x = ( node . x - x0 ) / ( x1 - x0 ) * size [ 0 ] ;
862+ node . y = node . depth / y1 * size [ 1 ] ;
863+ delete node . _tree ;
864+ } ) ;
865+
866+ return nodes ;
867+ }
868+
869+ tree . sort = d3 . rebind ( tree , hierarchy . sort ) ;
870+ tree . children = d3 . rebind ( tree , hierarchy . children ) ;
871+ tree . value = d3 . rebind ( tree , hierarchy . value ) ;
872+
873+ tree . separation = function ( x ) {
874+ if ( ! arguments . length ) return separation ;
875+ separation = x ;
876+ return tree ;
877+ } ;
878+
879+ tree . size = function ( x ) {
880+ if ( ! arguments . length ) return size ;
881+ size = x ;
882+ return tree ;
883+ } ;
884+
885+ return tree ;
886+ } ;
887+
888+ function d3_layout_treeSeparation ( a , b ) {
889+ return a . parent == b . parent ? 1 : 2 ;
890+ }
891+
892+ // function d3_layout_treeSeparationRadial(a, b) {
893+ // return (a.parent == b.parent ? 1 : 2) / a.depth;
894+ // }
895+
896+ function d3_layout_treeLeft ( node ) {
897+ return node . children ? node . children [ 0 ] : node . _tree . thread ;
898+ }
899+
900+ function d3_layout_treeRight ( node ) {
901+ return node . children ? node . children [ node . children . length - 1 ] : node . _tree . thread ;
902+ }
903+
904+ function d3_layout_treeSearch ( node , compare ) {
905+ var children = node . children ;
906+ if ( children ) {
907+ var child ,
908+ n = children . length ,
909+ i = - 1 ;
910+ while ( ++ i < n ) {
911+ if ( compare ( child = d3_layout_treeSearch ( children [ i ] , compare ) , node ) > 0 ) {
912+ node = child ;
913+ }
914+ }
915+ }
916+ return node ;
917+ }
918+
919+ function d3_layout_treeRightmost ( a , b ) {
920+ return a . x - b . x ;
921+ }
922+
923+ function d3_layout_treeLeftmost ( a , b ) {
924+ return b . x - a . x ;
925+ }
926+
927+ function d3_layout_treeDeepest ( a , b ) {
928+ return a . depth - b . depth ;
929+ }
930+
931+ function d3_layout_treeVisitAfter ( node , callback ) {
932+ function visit ( node , previousSibling ) {
933+ var children = node . children ;
934+ if ( children ) {
935+ var child ,
936+ previousChild = null ,
937+ i = - 1 ,
938+ n = children . length ;
939+ while ( ++ i < n ) {
940+ child = children [ i ] ;
941+ visit ( child , previousChild ) ;
942+ previousChild = child ;
943+ }
944+ }
945+ callback ( node , previousSibling ) ;
946+ }
947+ visit ( node , null ) ;
948+ }
949+
950+ function d3_layout_treeShift ( node ) {
951+ var shift = 0 ,
952+ change = 0 ,
953+ children = node . children ,
954+ i = children . length ,
955+ child ;
956+ while ( -- i >= 0 ) {
957+ child = children [ i ] . _tree ;
958+ child . prelim += shift ;
959+ child . mod += shift ;
960+ shift += child . shift + ( change += child . change ) ;
961+ }
962+ }
963+
964+ function d3_layout_treeMove ( ancestor , node , shift ) {
965+ ancestor = ancestor . _tree ;
966+ node = node . _tree ;
967+ var change = shift / ( node . number - ancestor . number ) ;
968+ ancestor . change += change ;
969+ node . change -= change ;
970+ node . shift += shift ;
971+ node . prelim += shift ;
972+ node . mod += shift ;
973+ }
974+
975+ function d3_layout_treeAncestor ( vim , node , ancestor ) {
976+ return vim . _tree . ancestor . parent == node . parent
977+ ? vim . _tree . ancestor
978+ : ancestor ;
979+ }
742980// Squarified Treemaps by Mark Bruls, Kees Huizing, and Jarke J. van Wijk
743981d3 . layout . treemap = function ( ) {
744982 var hierarchy = d3 . layout . hierarchy ( ) ,
0 commit comments