@@ -150,4 +150,167 @@ d3.layout.chord = function() {
150150
151151 return chord ;
152152} ;
153+ // data is two-dimensional array of x,y; we populate y0
154+ // TODO perhaps make the `x`, `y` and `y0` structure customizable
155+ d3 . layout . stack = function ( ) {
156+ var order = "default" ,
157+ offset = "zero" ;
158+
159+ function stack ( data ) {
160+ var n = data . length ,
161+ m = data [ 0 ] . length ,
162+ i ,
163+ j ,
164+ y0 ;
165+
166+ // compute the order of series
167+ var index = d3_layout_stackOrders [ order ] ( data ) ;
168+
169+ // set y0 on the baseline
170+ d3_layout_stackOffsets [ offset ] ( data , index ) ;
171+
172+ // propagate offset to other series
173+ for ( j = 0 ; j < m ; ++ j ) {
174+ for ( i = 1 , y0 = data [ index [ 0 ] ] [ j ] . y0 ; i < n ; ++ i ) {
175+ data [ index [ i ] ] [ j ] . y0 = y0 += data [ index [ i - 1 ] ] [ j ] . y ;
176+ }
177+ }
178+
179+ return data ;
180+ }
181+
182+ stack . order = function ( x ) {
183+ if ( ! arguments . length ) return order ;
184+ order = x ;
185+ return stack ;
186+ } ;
187+
188+ stack . offset = function ( x ) {
189+ if ( ! arguments . length ) return offset ;
190+ offset = x ;
191+ return stack ;
192+ } ;
193+
194+ return stack ;
195+ }
196+
197+ var d3_layout_stackOrders = {
198+
199+ "inside-out" : function ( data ) {
200+ var n = data . length ,
201+ i ,
202+ j ,
203+ max = data . map ( d3_layout_stackMaxIndex ) ,
204+ sums = data . map ( d3_layout_stackReduceSum ) ,
205+ index = d3 . range ( n ) . sort ( function ( a , b ) { return max [ a ] - max [ b ] ; } ) ,
206+ top = 0 ,
207+ bottom = 0 ,
208+ tops = [ ] ,
209+ bottoms = [ ] ;
210+ for ( i = 0 ; i < n ; i ++ ) {
211+ j = index [ i ] ;
212+ if ( top < bottom ) {
213+ top += sums [ j ] ;
214+ tops . push ( j ) ;
215+ } else {
216+ bottom += sums [ j ] ;
217+ bottoms . push ( j ) ;
218+ }
219+ }
220+ return bottoms . reverse ( ) . concat ( tops ) ;
221+ } ,
222+
223+ "reverse" : function ( data ) {
224+ return d3 . range ( data . length ) . reverse ( ) ;
225+ } ,
226+
227+ "default" : function ( data ) {
228+ return d3 . range ( data . length ) ;
229+ }
230+
231+ } ;
232+
233+ var d3_layout_stackOffsets = {
234+
235+ "silhouette" : function ( data , index ) {
236+ var n = data . length ,
237+ m = data [ 0 ] . length ,
238+ sums = [ ] ,
239+ max = 0 ,
240+ i ,
241+ j ,
242+ o ;
243+ for ( j = 0 ; j < m ; ++ j ) {
244+ for ( i = 0 , o = 0 ; i < n ; i ++ ) o += data [ i ] [ j ] . y ;
245+ if ( o > max ) max = o ;
246+ sums . push ( o ) ;
247+ }
248+ for ( j = 0 , i = index [ 0 ] ; j < m ; ++ j ) {
249+ data [ i ] [ j ] . y0 = ( max - sums [ j ] ) / 2 ;
250+ }
251+ } ,
252+
253+ "wiggle" : function ( data , index ) {
254+ var n = data . length ,
255+ x = data [ 0 ] ,
256+ m = x . length ,
257+ max = 0 ,
258+ i ,
259+ j ,
260+ k ,
261+ ii ,
262+ ik ,
263+ i0 = index [ 0 ] ,
264+ s1 ,
265+ s2 ,
266+ s3 ,
267+ dx ,
268+ o ,
269+ o0 ;
270+ data [ i0 ] [ 0 ] . y0 = o = o0 = 0 ;
271+ for ( j = 1 ; j < m ; ++ j ) {
272+ for ( i = 0 , s1 = 0 ; i < n ; ++ i ) s1 += data [ i ] [ j ] . y ;
273+ for ( i = 0 , s2 = 0 , dx = x [ j ] . x - x [ j - 1 ] . x ; i < n ; ++ i ) {
274+ for ( k = 0 , ii = index [ i ] , s3 = ( data [ ii ] [ j ] . y - data [ ii ] [ j - 1 ] . y ) / ( 2 * dx ) ; k < i ; ++ k ) {
275+ s3 += ( data [ ik = index [ k ] ] [ j ] . y - data [ ik ] [ j - 1 ] . y ) / dx ;
276+ }
277+ s2 += s3 * data [ ii ] [ j ] . y ;
278+ }
279+ data [ i0 ] [ j ] . y0 = o -= s1 ? s2 / s1 * dx : 0 ;
280+ if ( o < o0 ) o0 = o ;
281+ }
282+ for ( j = 0 ; j < m ; ++ j ) data [ i0 ] [ j ] . y0 -= o0 ;
283+ } ,
284+
285+ "zero" : function ( data , index ) {
286+ var j = 0 ,
287+ m = data [ 0 ] . length ,
288+ i0 = index [ 0 ] ;
289+ for ( ; j < m ; ++ j ) data [ i0 ] [ j ] . y0 = 0 ;
290+ }
291+
292+ } ;
293+
294+ function d3_layout_stackReduceSum ( d ) {
295+ return d . reduce ( d3_layout_stackSum , 0 ) ;
296+ }
297+
298+ function d3_layout_stackMaxIndex ( array ) {
299+ var i = 1 ,
300+ j = 0 ,
301+ v = array [ 0 ] . y ,
302+ k ,
303+ n = array . length ;
304+ for ( ; i < n ; ++ i ) {
305+ if ( ( k = array [ i ] . y ) > v ) {
306+ j = i ;
307+ v = k ;
308+ }
309+ }
310+ return j ;
311+ }
312+
313+ function d3_layout_stackSum ( p , d ) {
314+ return p + d . y ;
315+ }
153316} ) ( )
0 commit comments