@@ -672,4 +672,126 @@ d3.geom.delaunay = function(vertices) {
672672
673673 return triangles ;
674674} ;
675+ /**
676+ * Constructs a new quadtree for the specified array of points. A quadtree is a
677+ * two-dimensional recursive spatial subdivision. This implementation uses
678+ * square partitions, dividing each square into four equally-sized squares. Each
679+ * point exists in a unique node; if multiple points are in the same position,
680+ * some points may be stored on internal nodes rather than leaf nodes. Quadtrees
681+ * can be used to accelerate various spatial operations, such as the Barnes-Hut
682+ * approximation for computing n-body forces, or collision detection.
683+ *
684+ * @param points [[x1, y1], [x2, y2], …]
685+ * @return quadtree root {left: boolean, nodes: […], point: [x, y]}
686+ */
687+ d3 . geom . quadtree = function ( points ) {
688+ var p ,
689+ i = - 1 ,
690+ n = points . length ;
691+
692+ /* Compute bounds. */
693+ var x1 = Number . POSITIVE_INFINITY , y1 = x1 ,
694+ x2 = Number . NEGATIVE_INFINITY , y2 = x2 ;
695+ while ( ++ i < n ) {
696+ p = points [ i ] ;
697+ if ( p [ 0 ] < x1 ) x1 = p [ 0 ] ;
698+ if ( p [ 1 ] < y1 ) y1 = p [ 1 ] ;
699+ if ( p [ 0 ] > x2 ) x2 = p [ 0 ] ;
700+ if ( p [ 1 ] > y2 ) y2 = p [ 1 ] ;
701+ }
702+
703+ /* Squarify the bounds. */
704+ var dx = x2 - x1 ,
705+ dy = y2 - y1 ;
706+ if ( dx > dy ) y2 = y1 + dx ;
707+ else x2 = x1 + dy ;
708+
709+ /**
710+ * @ignore Recursively inserts the specified point <i>p</i> at the node
711+ * <i>n</i> or one of its descendants. The bounds are defined by [<i>x1</i>,
712+ * <i>x2</i>] and [<i>y1</i>, <i>y2</i>].
713+ */
714+ function insert ( n , p , x1 , y1 , x2 , y2 ) {
715+ if ( isNaN ( p [ 0 ] ) || isNaN ( p [ 1 ] ) ) return ; // ignore invalid points
716+ if ( n . leaf ) {
717+ var v = n . point ;
718+ if ( v ) {
719+ /*
720+ * If the point at this leaf node is at the same position as the new
721+ * point we are adding, we leave the point associated with the
722+ * internal node while adding the new point to a child node. This
723+ * avoids infinite recursion.
724+ */
725+ if ( ( Math . abs ( v [ 0 ] - p [ 0 ] ) + Math . abs ( v [ 1 ] - p [ 1 ] ) ) < .01 ) {
726+ insertChild ( n , p , x1 , y1 , x2 , y2 ) ;
727+ } else {
728+ n . point = null ;
729+ insertChild ( n , v , x1 , y1 , x2 , y2 ) ;
730+ insertChild ( n , p , x1 , y1 , x2 , y2 ) ;
731+ }
732+ } else {
733+ n . point = p ;
734+ }
735+ } else {
736+ insertChild ( n , p , x1 , y1 , x2 , y2 ) ;
737+ }
738+ }
739+
740+ /**
741+ * @ignore Recursively inserts the specified point <i>p</i> into a
742+ * descendant of node <i>n</i>. The bounds are defined by [<i>x1</i>,
743+ * <i>x2</i>] and [<i>y1</i>, <i>y2</i>].
744+ */
745+ function insertChild ( n , p , x1 , y1 , x2 , y2 ) {
746+ /* Compute the split point, and the quadrant in which to insert p. */
747+ var sx = ( x1 + x2 ) * .5 ,
748+ sy = ( y1 + y2 ) * .5 ,
749+ right = p [ 0 ] >= sx ,
750+ bottom = p [ 1 ] >= sy ,
751+ i = ( bottom << 1 ) + right ;
752+
753+ /* Recursively insert into the child node. */
754+ n . leaf = false ;
755+ n = n . nodes [ i ] || ( n . nodes [ i ] = d3_geom_quadtreeNode ( ) ) ;
756+
757+ /* Update the bounds as we recurse. */
758+ if ( right ) x1 = sx ; else x2 = sx ;
759+ if ( bottom ) y1 = sy ; else y2 = sy ;
760+ insert ( n , p , x1 , y1 , x2 , y2 ) ;
761+ }
762+
763+ /* Create the root node. */
764+ var root = d3_geom_quadtreeNode ( ) ;
765+
766+ /* Insert all points. */
767+ i = - 1 ;
768+ while ( ++ i < n ) insert ( root , points [ i ] , x1 , y1 , x2 , y2 ) ;
769+
770+ /* Register a visitor function for the root. */
771+ root . visit = function ( f ) {
772+ d3_geom_quadtreeVisit ( f , root , x1 , y1 , x2 , y2 ) ;
773+ } ;
774+
775+ return root ;
776+ } ;
777+
778+ function d3_geom_quadtreeNode ( ) {
779+ return {
780+ leaf : true ,
781+ nodes : [ ] ,
782+ point : null
783+ } ;
784+ }
785+
786+ function d3_geom_quadtreeVisit ( f , node , x1 , y1 , x2 , y2 ) {
787+ if ( ! f ( node , x1 , y1 , x2 , y2 ) ) {
788+ var sx = ( x1 + x2 ) * .5 ,
789+ sy = ( y1 + y2 ) * .5 ,
790+ children = node . nodes ;
791+ if ( children [ 0 ] ) d3_geom_quadtreeVisit ( f , children [ 0 ] , x1 , y1 , sx , sy ) ;
792+ if ( children [ 1 ] ) d3_geom_quadtreeVisit ( f , children [ 1 ] , sx , y1 , x2 , sy ) ;
793+ if ( children [ 2 ] ) d3_geom_quadtreeVisit ( f , children [ 2 ] , x1 , sy , sx , y2 ) ;
794+ if ( children [ 3 ] ) d3_geom_quadtreeVisit ( f , children [ 3 ] , sx , sy , x2 , y2 ) ;
795+ }
796+ }
675797} ) ( )
0 commit comments