import * as echarts from 'echarts/lib/echarts'; import Vector3 from 'claygl/src/math/Vector3'; import glmatrix from 'claygl/src/dep/glmatrix'; import cartesian3DLayout from './cartesian3DLayout'; import evaluateBarSparseness from './evaluateBarSparseness'; var vec3 = glmatrix.vec3; var isDimensionStacked = echarts.helper.dataStack.isDimensionStacked; function globeLayout(seriesModel, coordSys) { var data = seriesModel.getData(); var barMinHeight = seriesModel.get('minHeight') || 0; var barSize = seriesModel.get('barSize'); var dims = ['lng', 'lat', 'alt'].map(function (coordDimName) { return seriesModel.coordDimToDataDim(coordDimName)[0]; }); if (barSize == null) { var perimeter = coordSys.radius * Math.PI; var fillRatio = evaluateBarSparseness(data, dims[0], dims[1]); barSize = [perimeter / Math.sqrt(data.count() / fillRatio), perimeter / Math.sqrt(data.count() / fillRatio)]; } else if (!echarts.util.isArray(barSize)) { barSize = [barSize, barSize]; } var valueDim = getValueDimension(data, dims); data.each(dims, function (lng, lat, val, idx) { var stackedValue = data.get(valueDim.dimension, idx); var baseValue = valueDim.isStacked ? stackedValue - val : coordSys.altitudeAxis.scale.getExtent()[0]; // TODO Stacked with minHeight. var height = Math.max(coordSys.altitudeAxis.dataToCoord(val), barMinHeight); var start = coordSys.dataToPoint([lng, lat, baseValue]); var end = coordSys.dataToPoint([lng, lat, stackedValue]); var dir = vec3.sub([], end, start); vec3.normalize(dir, dir); var size = [barSize[0], height, barSize[1]]; data.setItemLayout(idx, [start, dir, size]); }); data.setLayout('orient', Vector3.UP.array); } function geo3DLayout(seriesModel, coordSys) { var data = seriesModel.getData(); var barSize = seriesModel.get('barSize'); var barMinHeight = seriesModel.get('minHeight') || 0; var dims = ['lng', 'lat', 'alt'].map(function (coordDimName) { return seriesModel.coordDimToDataDim(coordDimName)[0]; }); if (barSize == null) { var size = Math.min(coordSys.size[0], coordSys.size[2]); var fillRatio = evaluateBarSparseness(data, dims[0], dims[1]); barSize = [size / Math.sqrt(data.count() / fillRatio), size / Math.sqrt(data.count() / fillRatio)]; } else if (!echarts.util.isArray(barSize)) { barSize = [barSize, barSize]; } var dir = [0, 1, 0]; var valueDim = getValueDimension(data, dims); data.each(dims, function (lng, lat, val, idx) { var stackedValue = data.get(valueDim.dimension, idx); var baseValue = valueDim.isStacked ? stackedValue - val : coordSys.altitudeAxis.scale.getExtent()[0]; var height = Math.max(coordSys.altitudeAxis.dataToCoord(val), barMinHeight); var start = coordSys.dataToPoint([lng, lat, baseValue]); var size = [barSize[0], height, barSize[1]]; data.setItemLayout(idx, [start, dir, size]); }); data.setLayout('orient', [1, 0, 0]); } function mapService3DLayout(seriesModel, coordSys) { var data = seriesModel.getData(); var dimLng = seriesModel.coordDimToDataDim('lng')[0]; var dimLat = seriesModel.coordDimToDataDim('lat')[0]; var dimAlt = seriesModel.coordDimToDataDim('alt')[0]; var barSize = seriesModel.get('barSize'); var barMinHeight = seriesModel.get('minHeight') || 0; if (barSize == null) { var xExtent = data.getDataExtent(dimLng); var yExtent = data.getDataExtent(dimLat); var corner0 = coordSys.dataToPoint([xExtent[0], yExtent[0]]); var corner1 = coordSys.dataToPoint([xExtent[1], yExtent[1]]); var size = Math.min(Math.abs(corner0[0] - corner1[0]), Math.abs(corner0[1] - corner1[1])) || 1; var fillRatio = evaluateBarSparseness(data, dimLng, dimLat); // PENDING, data density barSize = [size / Math.sqrt(data.count() / fillRatio), size / Math.sqrt(data.count() / fillRatio)]; } else { if (!echarts.util.isArray(barSize)) { barSize = [barSize, barSize]; } barSize[0] /= coordSys.getScale() / 16; barSize[1] /= coordSys.getScale() / 16; } var dir = [0, 0, 1]; var dims = [dimLng, dimLat, dimAlt]; var valueDim = getValueDimension(data, dims); data.each(dims, function (lng, lat, val, idx) { var stackedValue = data.get(valueDim.dimension, idx); var baseValue = valueDim.isStacked ? stackedValue - val : 0; var start = coordSys.dataToPoint([lng, lat, baseValue]); var end = coordSys.dataToPoint([lng, lat, stackedValue]); var height = Math.max(end[2] - start[2], barMinHeight); var size = [barSize[0], height, barSize[1]]; data.setItemLayout(idx, [start, dir, size]); }); data.setLayout('orient', [1, 0, 0]); } function getValueDimension(data, dataDims) { var isStacked = isDimensionStacked(data, dataDims[2]); return { dimension: isStacked ? data.getCalculationInfo('stackResultDimension') : dataDims[2], isStacked: isStacked }; } export default function registerBarLayout(registers) { registers.registerLayout(function (ecModel, api) { ecModel.eachSeriesByType('bar3D', function (seriesModel) { var coordSys = seriesModel.coordinateSystem; var coordSysType = coordSys && coordSys.type; if (coordSysType === 'globe') { globeLayout(seriesModel, coordSys); } else if (coordSysType === 'cartesian3D') { cartesian3DLayout(seriesModel, coordSys); } else if (coordSysType === 'geo3D') { geo3DLayout(seriesModel, coordSys); } else if (coordSysType === 'mapbox3D' || coordSysType === 'maptalks3D') { mapService3DLayout(seriesModel, coordSys); } else { if (process.env.NODE_ENV !== 'production') { if (!coordSys) { throw new Error('bar3D doesn\'t have coordinate system.'); } else { throw new Error('bar3D doesn\'t support coordinate system ' + coordSys.type); } } } }); }); }