/**
 * Transform the raw data to layout information.
 */
define(function (require) {
    var zrUtil = require('zrender/core/util');
    var numberUtil =  require('../../util/number');
    return function (ecModel, api) {
        ecModel.eachSeriesByType('themeRiver', function (seriesModel) {
            var data = seriesModel.getData();
            var single = seriesModel.coordinateSystem;
            var layoutInfo = {};
            // use the axis boundingRect for view
            var rect = single.getRect();
            layoutInfo.rect = rect;
            var boundaryGap = seriesModel.get('boundaryGap');
            var axis = single.getAxis();
            layoutInfo.boundaryGap = boundaryGap;
            if (axis.orient === 'horizontal') {
                boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], rect.height);
                boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], rect.height);
                var height = rect.height - boundaryGap[0] - boundaryGap[1];
                themeRiverLayout(data, seriesModel, height);
            }
            else {
                boundaryGap[0] = numberUtil.parsePercent(boundaryGap[0], rect.width);
                boundaryGap[1] = numberUtil.parsePercent(boundaryGap[1], rect.width);
                var width = rect.width - boundaryGap[0] - boundaryGap[1];
                themeRiverLayout(data, seriesModel, width);
            }
            data.setLayout('layoutInfo', layoutInfo);
        });
    };
    /**
     * the layout information about themeriver
     * @param  {module:echarts/data/List} data
     * @return
     */
    function themeRiverLayout(data, seriesModel, height) {
        if (!data.count()) {
            return;
        }
        // the data in each layer are organized into a series.
        var layerSeries = seriesModel.getLayerSeries();
        //the points in each layer.
        var layerPoints = zrUtil.map(layerSeries, function (singleLayer) {
            return zrUtil.map(singleLayer.indices, function (idx) {
                return seriesModel.coordinateSystem.dataToPoint([
                    data.get('time', idx), data.get('value', idx)
                ]);
            });
        });
        var base = computeBaseline(layerPoints);
        var baseLine = base.y0;
        var ky = height / base.max;
        //set layout information for each item.
        var n = layerSeries.length;
        var m = layerSeries[0].indices.length;
        var baseY0;
        for (var j = 0; j < m; ++j) {
            baseY0 = baseLine[j] * ky;
            data.setItemLayout(layerSeries[0].indices[j], {
                layerIndex: 0,
                x: layerPoints[0][j][0],
                y0: baseY0,
                y: layerPoints[0][j][1] * ky
            });
            for (var i = 1; i < n; ++i) {
                baseY0 += layerPoints[i - 1][j][1] * ky;
                data.setItemLayout(layerSeries[i].indices[j], {
                    layerIndex: i,
                    x: layerPoints[i][j][0],
                    y0: baseY0,
                    y: layerPoints[i][j][1] * ky
                });
            }
        }
    }
    /**
     * Compute the baseLine of the rawdata.
     * Inspired by Lee Byron's paper Stacked Graphs - Geometry & Aesthetics.
     * @param  {Array.<Array>} data
     * @return {Array}
     */
    function computeBaseline(data) {
        var layerNum = data.length;
        var pointNum = data[0].length;
        var sums = [];
        var y0 = [];
        var max = 0;
        var temp;
        var base = {};
        for (var i = 0; i < pointNum; ++i) {
            for (var j = 0, temp = 0; j < layerNum; ++j) {
                temp += data[j][i][1];
            }
            if (temp > max) {
                max = temp;
            }
            sums.push(temp);
        }
        for (var k = 0; k < pointNum; ++k) {
            y0[k] = (max - sums[k]) / 2;
        }
        max = 0;
        for (var l = 0; l < pointNum; ++l) {
            var sum = sums[l] + y0[l];
            if (sum > max) {
                max = sum;
            }
        }
        base.y0 = y0;
        base.max = max;
        return base;
    }
}); 
  |