|   | 
| /* | 
| * Licensed to the Apache Software Foundation (ASF) under one | 
| * or more contributor license agreements.  See the NOTICE file | 
| * distributed with this work for additional information | 
| * regarding copyright ownership.  The ASF licenses this file | 
| * to you under the Apache License, Version 2.0 (the | 
| * "License"); you may not use this file except in compliance | 
| * with the License.  You may obtain a copy of the License at | 
| * | 
| *   http://www.apache.org/licenses/LICENSE-2.0 | 
| * | 
| * Unless required by applicable law or agreed to in writing, | 
| * software distributed under the License is distributed on an | 
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| * KIND, either express or implied.  See the License for the | 
| * specific language governing permissions and limitations | 
| * under the License. | 
| */ | 
|   | 
|   | 
| /** | 
|  * AUTO-GENERATED FILE. DO NOT MODIFY. | 
|  */ | 
|   | 
| /* | 
| * Licensed to the Apache Software Foundation (ASF) under one | 
| * or more contributor license agreements.  See the NOTICE file | 
| * distributed with this work for additional information | 
| * regarding copyright ownership.  The ASF licenses this file | 
| * to you under the Apache License, Version 2.0 (the | 
| * "License"); you may not use this file except in compliance | 
| * with the License.  You may obtain a copy of the License at | 
| * | 
| *   http://www.apache.org/licenses/LICENSE-2.0 | 
| * | 
| * Unless required by applicable law or agreed to in writing, | 
| * software distributed under the License is distributed on an | 
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| * KIND, either express or implied.  See the License for the | 
| * specific language governing permissions and limitations | 
| * under the License. | 
| */ | 
| /** | 
|  * Grid is a region which contains at most 4 cartesian systems | 
|  * | 
|  * TODO Default cartesian | 
|  */ | 
| import { isObject, each, indexOf, retrieve3, keys } from 'zrender/lib/core/util.js'; | 
| import { getLayoutRect } from '../../util/layout.js'; | 
| import { createScaleByModel, ifAxisCrossZero, niceScaleExtent, estimateLabelUnionRect, getDataDimensionsOnAxis } from '../../coord/axisHelper.js'; | 
| import Cartesian2D, { cartesian2DDimensions } from './Cartesian2D.js'; | 
| import Axis2D from './Axis2D.js'; | 
| import { SINGLE_REFERRING } from '../../util/model.js'; | 
| import { isCartesian2DSeries, findAxisModels } from './cartesianAxisHelper.js'; | 
| import { isIntervalOrLogScale } from '../../scale/helper.js'; | 
| import { alignScaleTicks } from '../axisAlignTicks.js'; | 
| var Grid = /** @class */function () { | 
|   function Grid(gridModel, ecModel, api) { | 
|     // FIXME:TS where used (different from registered type 'cartesian2d')? | 
|     this.type = 'grid'; | 
|     this._coordsMap = {}; | 
|     this._coordsList = []; | 
|     this._axesMap = {}; | 
|     this._axesList = []; | 
|     this.axisPointerEnabled = true; | 
|     this.dimensions = cartesian2DDimensions; | 
|     this._initCartesian(gridModel, ecModel, api); | 
|     this.model = gridModel; | 
|   } | 
|   Grid.prototype.getRect = function () { | 
|     return this._rect; | 
|   }; | 
|   Grid.prototype.update = function (ecModel, api) { | 
|     var axesMap = this._axesMap; | 
|     this._updateScale(ecModel, this.model); | 
|     function updateAxisTicks(axes) { | 
|       var alignTo; | 
|       // Axis is added in order of axisIndex. | 
|       var axesIndices = keys(axes); | 
|       var len = axesIndices.length; | 
|       if (!len) { | 
|         return; | 
|       } | 
|       var axisNeedsAlign = []; | 
|       // Process once and calculate the ticks for those don't use alignTicks. | 
|       for (var i = len - 1; i >= 0; i--) { | 
|         var idx = +axesIndices[i]; // Convert to number. | 
|         var axis = axes[idx]; | 
|         var model = axis.model; | 
|         var scale = axis.scale; | 
|         if ( | 
|         // Only value and log axis without interval support alignTicks. | 
|         isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null) { | 
|           axisNeedsAlign.push(axis); | 
|         } else { | 
|           niceScaleExtent(scale, model); | 
|           if (isIntervalOrLogScale(scale)) { | 
|             // Can only align to interval or log axis. | 
|             alignTo = axis; | 
|           } | 
|         } | 
|       } | 
|       ; | 
|       // All axes has set alignTicks. Pick the first one. | 
|       // PENDING. Should we find the axis that both set interval, min, max and align to this one? | 
|       if (axisNeedsAlign.length) { | 
|         if (!alignTo) { | 
|           alignTo = axisNeedsAlign.pop(); | 
|           niceScaleExtent(alignTo.scale, alignTo.model); | 
|         } | 
|         each(axisNeedsAlign, function (axis) { | 
|           alignScaleTicks(axis.scale, axis.model, alignTo.scale); | 
|         }); | 
|       } | 
|     } | 
|     updateAxisTicks(axesMap.x); | 
|     updateAxisTicks(axesMap.y); | 
|     // Key: axisDim_axisIndex, value: boolean, whether onZero target. | 
|     var onZeroRecords = {}; | 
|     each(axesMap.x, function (xAxis) { | 
|       fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords); | 
|     }); | 
|     each(axesMap.y, function (yAxis) { | 
|       fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords); | 
|     }); | 
|     // Resize again if containLabel is enabled | 
|     // FIXME It may cause getting wrong grid size in data processing stage | 
|     this.resize(this.model, api); | 
|   }; | 
|   /** | 
|    * Resize the grid | 
|    */ | 
|   Grid.prototype.resize = function (gridModel, api, ignoreContainLabel) { | 
|     var boxLayoutParams = gridModel.getBoxLayoutParams(); | 
|     var isContainLabel = !ignoreContainLabel && gridModel.get('containLabel'); | 
|     var gridRect = getLayoutRect(boxLayoutParams, { | 
|       width: api.getWidth(), | 
|       height: api.getHeight() | 
|     }); | 
|     this._rect = gridRect; | 
|     var axesList = this._axesList; | 
|     adjustAxes(); | 
|     // Minus label size | 
|     if (isContainLabel) { | 
|       each(axesList, function (axis) { | 
|         if (!axis.model.get(['axisLabel', 'inside'])) { | 
|           var labelUnionRect = estimateLabelUnionRect(axis); | 
|           if (labelUnionRect) { | 
|             var dim = axis.isHorizontal() ? 'height' : 'width'; | 
|             var margin = axis.model.get(['axisLabel', 'margin']); | 
|             gridRect[dim] -= labelUnionRect[dim] + margin; | 
|             if (axis.position === 'top') { | 
|               gridRect.y += labelUnionRect.height + margin; | 
|             } else if (axis.position === 'left') { | 
|               gridRect.x += labelUnionRect.width + margin; | 
|             } | 
|           } | 
|         } | 
|       }); | 
|       adjustAxes(); | 
|     } | 
|     each(this._coordsList, function (coord) { | 
|       // Calculate affine matrix to accelerate the data to point transform. | 
|       // If all the axes scales are time or value. | 
|       coord.calcAffineTransform(); | 
|     }); | 
|     function adjustAxes() { | 
|       each(axesList, function (axis) { | 
|         var isHorizontal = axis.isHorizontal(); | 
|         var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height]; | 
|         var idx = axis.inverse ? 1 : 0; | 
|         axis.setExtent(extent[idx], extent[1 - idx]); | 
|         updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y); | 
|       }); | 
|     } | 
|   }; | 
|   Grid.prototype.getAxis = function (dim, axisIndex) { | 
|     var axesMapOnDim = this._axesMap[dim]; | 
|     if (axesMapOnDim != null) { | 
|       return axesMapOnDim[axisIndex || 0]; | 
|     } | 
|   }; | 
|   Grid.prototype.getAxes = function () { | 
|     return this._axesList.slice(); | 
|   }; | 
|   Grid.prototype.getCartesian = function (xAxisIndex, yAxisIndex) { | 
|     if (xAxisIndex != null && yAxisIndex != null) { | 
|       var key = 'x' + xAxisIndex + 'y' + yAxisIndex; | 
|       return this._coordsMap[key]; | 
|     } | 
|     if (isObject(xAxisIndex)) { | 
|       yAxisIndex = xAxisIndex.yAxisIndex; | 
|       xAxisIndex = xAxisIndex.xAxisIndex; | 
|     } | 
|     for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) { | 
|       if (coordList[i].getAxis('x').index === xAxisIndex || coordList[i].getAxis('y').index === yAxisIndex) { | 
|         return coordList[i]; | 
|       } | 
|     } | 
|   }; | 
|   Grid.prototype.getCartesians = function () { | 
|     return this._coordsList.slice(); | 
|   }; | 
|   /** | 
|    * @implements | 
|    */ | 
|   Grid.prototype.convertToPixel = function (ecModel, finder, value) { | 
|     var target = this._findConvertTarget(finder); | 
|     return target.cartesian ? target.cartesian.dataToPoint(value) : target.axis ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) : null; | 
|   }; | 
|   /** | 
|    * @implements | 
|    */ | 
|   Grid.prototype.convertFromPixel = function (ecModel, finder, value) { | 
|     var target = this._findConvertTarget(finder); | 
|     return target.cartesian ? target.cartesian.pointToData(value) : target.axis ? target.axis.coordToData(target.axis.toLocalCoord(value)) : null; | 
|   }; | 
|   Grid.prototype._findConvertTarget = function (finder) { | 
|     var seriesModel = finder.seriesModel; | 
|     var xAxisModel = finder.xAxisModel || seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; | 
|     var yAxisModel = finder.yAxisModel || seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; | 
|     var gridModel = finder.gridModel; | 
|     var coordsList = this._coordsList; | 
|     var cartesian; | 
|     var axis; | 
|     if (seriesModel) { | 
|       cartesian = seriesModel.coordinateSystem; | 
|       indexOf(coordsList, cartesian) < 0 && (cartesian = null); | 
|     } else if (xAxisModel && yAxisModel) { | 
|       cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); | 
|     } else if (xAxisModel) { | 
|       axis = this.getAxis('x', xAxisModel.componentIndex); | 
|     } else if (yAxisModel) { | 
|       axis = this.getAxis('y', yAxisModel.componentIndex); | 
|     } | 
|     // Lowest priority. | 
|     else if (gridModel) { | 
|       var grid = gridModel.coordinateSystem; | 
|       if (grid === this) { | 
|         cartesian = this._coordsList[0]; | 
|       } | 
|     } | 
|     return { | 
|       cartesian: cartesian, | 
|       axis: axis | 
|     }; | 
|   }; | 
|   /** | 
|    * @implements | 
|    */ | 
|   Grid.prototype.containPoint = function (point) { | 
|     var coord = this._coordsList[0]; | 
|     if (coord) { | 
|       return coord.containPoint(point); | 
|     } | 
|   }; | 
|   /** | 
|    * Initialize cartesian coordinate systems | 
|    */ | 
|   Grid.prototype._initCartesian = function (gridModel, ecModel, api) { | 
|     var _this = this; | 
|     var grid = this; | 
|     var axisPositionUsed = { | 
|       left: false, | 
|       right: false, | 
|       top: false, | 
|       bottom: false | 
|     }; | 
|     var axesMap = { | 
|       x: {}, | 
|       y: {} | 
|     }; | 
|     var axesCount = { | 
|       x: 0, | 
|       y: 0 | 
|     }; | 
|     // Create axis | 
|     ecModel.eachComponent('xAxis', createAxisCreator('x'), this); | 
|     ecModel.eachComponent('yAxis', createAxisCreator('y'), this); | 
|     if (!axesCount.x || !axesCount.y) { | 
|       // Roll back when there no either x or y axis | 
|       this._axesMap = {}; | 
|       this._axesList = []; | 
|       return; | 
|     } | 
|     this._axesMap = axesMap; | 
|     // Create cartesian2d | 
|     each(axesMap.x, function (xAxis, xAxisIndex) { | 
|       each(axesMap.y, function (yAxis, yAxisIndex) { | 
|         var key = 'x' + xAxisIndex + 'y' + yAxisIndex; | 
|         var cartesian = new Cartesian2D(key); | 
|         cartesian.master = _this; | 
|         cartesian.model = gridModel; | 
|         _this._coordsMap[key] = cartesian; | 
|         _this._coordsList.push(cartesian); | 
|         cartesian.addAxis(xAxis); | 
|         cartesian.addAxis(yAxis); | 
|       }); | 
|     }); | 
|     function createAxisCreator(dimName) { | 
|       return function (axisModel, idx) { | 
|         if (!isAxisUsedInTheGrid(axisModel, gridModel)) { | 
|           return; | 
|         } | 
|         var axisPosition = axisModel.get('position'); | 
|         if (dimName === 'x') { | 
|           // Fix position | 
|           if (axisPosition !== 'top' && axisPosition !== 'bottom') { | 
|             // Default bottom of X | 
|             axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom'; | 
|           } | 
|         } else { | 
|           // Fix position | 
|           if (axisPosition !== 'left' && axisPosition !== 'right') { | 
|             // Default left of Y | 
|             axisPosition = axisPositionUsed.left ? 'right' : 'left'; | 
|           } | 
|         } | 
|         axisPositionUsed[axisPosition] = true; | 
|         var axis = new Axis2D(dimName, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisPosition); | 
|         var isCategory = axis.type === 'category'; | 
|         axis.onBand = isCategory && axisModel.get('boundaryGap'); | 
|         axis.inverse = axisModel.get('inverse'); | 
|         // Inject axis into axisModel | 
|         axisModel.axis = axis; | 
|         // Inject axisModel into axis | 
|         axis.model = axisModel; | 
|         // Inject grid info axis | 
|         axis.grid = grid; | 
|         // Index of axis, can be used as key | 
|         axis.index = idx; | 
|         grid._axesList.push(axis); | 
|         axesMap[dimName][idx] = axis; | 
|         axesCount[dimName]++; | 
|       }; | 
|     } | 
|   }; | 
|   /** | 
|    * Update cartesian properties from series. | 
|    */ | 
|   Grid.prototype._updateScale = function (ecModel, gridModel) { | 
|     // Reset scale | 
|     each(this._axesList, function (axis) { | 
|       axis.scale.setExtent(Infinity, -Infinity); | 
|       if (axis.type === 'category') { | 
|         var categorySortInfo = axis.model.get('categorySortInfo'); | 
|         axis.scale.setSortInfo(categorySortInfo); | 
|       } | 
|     }); | 
|     ecModel.eachSeries(function (seriesModel) { | 
|       if (isCartesian2DSeries(seriesModel)) { | 
|         var axesModelMap = findAxisModels(seriesModel); | 
|         var xAxisModel = axesModelMap.xAxisModel; | 
|         var yAxisModel = axesModelMap.yAxisModel; | 
|         if (!isAxisUsedInTheGrid(xAxisModel, gridModel) || !isAxisUsedInTheGrid(yAxisModel, gridModel)) { | 
|           return; | 
|         } | 
|         var cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); | 
|         var data = seriesModel.getData(); | 
|         var xAxis = cartesian.getAxis('x'); | 
|         var yAxis = cartesian.getAxis('y'); | 
|         unionExtent(data, xAxis); | 
|         unionExtent(data, yAxis); | 
|       } | 
|     }, this); | 
|     function unionExtent(data, axis) { | 
|       each(getDataDimensionsOnAxis(data, axis.dim), function (dim) { | 
|         axis.scale.unionExtentFromData(data, dim); | 
|       }); | 
|     } | 
|   }; | 
|   /** | 
|    * @param dim 'x' or 'y' or 'auto' or null/undefined | 
|    */ | 
|   Grid.prototype.getTooltipAxes = function (dim) { | 
|     var baseAxes = []; | 
|     var otherAxes = []; | 
|     each(this.getCartesians(), function (cartesian) { | 
|       var baseAxis = dim != null && dim !== 'auto' ? cartesian.getAxis(dim) : cartesian.getBaseAxis(); | 
|       var otherAxis = cartesian.getOtherAxis(baseAxis); | 
|       indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis); | 
|       indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis); | 
|     }); | 
|     return { | 
|       baseAxes: baseAxes, | 
|       otherAxes: otherAxes | 
|     }; | 
|   }; | 
|   Grid.create = function (ecModel, api) { | 
|     var grids = []; | 
|     ecModel.eachComponent('grid', function (gridModel, idx) { | 
|       var grid = new Grid(gridModel, ecModel, api); | 
|       grid.name = 'grid_' + idx; | 
|       // dataSampling requires axis extent, so resize | 
|       // should be performed in create stage. | 
|       grid.resize(gridModel, api, true); | 
|       gridModel.coordinateSystem = grid; | 
|       grids.push(grid); | 
|     }); | 
|     // Inject the coordinateSystems into seriesModel | 
|     ecModel.eachSeries(function (seriesModel) { | 
|       if (!isCartesian2DSeries(seriesModel)) { | 
|         return; | 
|       } | 
|       var axesModelMap = findAxisModels(seriesModel); | 
|       var xAxisModel = axesModelMap.xAxisModel; | 
|       var yAxisModel = axesModelMap.yAxisModel; | 
|       var gridModel = xAxisModel.getCoordSysModel(); | 
|       if (process.env.NODE_ENV !== 'production') { | 
|         if (!gridModel) { | 
|           throw new Error('Grid "' + retrieve3(xAxisModel.get('gridIndex'), xAxisModel.get('gridId'), 0) + '" not found'); | 
|         } | 
|         if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) { | 
|           throw new Error('xAxis and yAxis must use the same grid'); | 
|         } | 
|       } | 
|       var grid = gridModel.coordinateSystem; | 
|       seriesModel.coordinateSystem = grid.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); | 
|     }); | 
|     return grids; | 
|   }; | 
|   // For deciding which dimensions to use when creating list data | 
|   Grid.dimensions = cartesian2DDimensions; | 
|   return Grid; | 
| }(); | 
| /** | 
|  * Check if the axis is used in the specified grid. | 
|  */ | 
| function isAxisUsedInTheGrid(axisModel, gridModel) { | 
|   return axisModel.getCoordSysModel() === gridModel; | 
| } | 
| function fixAxisOnZero(axesMap, otherAxisDim, axis, | 
| // Key: see `getOnZeroRecordKey` | 
| onZeroRecords) { | 
|   axis.getAxesOnZeroOf = function () { | 
|     // TODO: onZero of multiple axes. | 
|     return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : []; | 
|   }; | 
|   // onZero can not be enabled in these two situations: | 
|   // 1. When any other axis is a category axis. | 
|   // 2. When no axis is cross 0 point. | 
|   var otherAxes = axesMap[otherAxisDim]; | 
|   var otherAxisOnZeroOf; | 
|   var axisModel = axis.model; | 
|   var onZero = axisModel.get(['axisLine', 'onZero']); | 
|   var onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']); | 
|   if (!onZero) { | 
|     return; | 
|   } | 
|   // If target axis is specified. | 
|   if (onZeroAxisIndex != null) { | 
|     if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) { | 
|       otherAxisOnZeroOf = otherAxes[onZeroAxisIndex]; | 
|     } | 
|   } else { | 
|     // Find the first available other axis. | 
|     for (var idx in otherAxes) { | 
|       if (otherAxes.hasOwnProperty(idx) && canOnZeroToAxis(otherAxes[idx]) | 
|       // Consider that two Y axes on one value axis, | 
|       // if both onZero, the two Y axes overlap. | 
|       && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]) { | 
|         otherAxisOnZeroOf = otherAxes[idx]; | 
|         break; | 
|       } | 
|     } | 
|   } | 
|   if (otherAxisOnZeroOf) { | 
|     onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true; | 
|   } | 
|   function getOnZeroRecordKey(axis) { | 
|     return axis.dim + '_' + axis.index; | 
|   } | 
| } | 
| function canOnZeroToAxis(axis) { | 
|   return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis); | 
| } | 
| function updateAxisTransform(axis, coordBase) { | 
|   var axisExtent = axis.getExtent(); | 
|   var axisExtentSum = axisExtent[0] + axisExtent[1]; | 
|   // Fast transform | 
|   axis.toGlobalCoord = axis.dim === 'x' ? function (coord) { | 
|     return coord + coordBase; | 
|   } : function (coord) { | 
|     return axisExtentSum - coord + coordBase; | 
|   }; | 
|   axis.toLocalCoord = axis.dim === 'x' ? function (coord) { | 
|     return coord - coordBase; | 
|   } : function (coord) { | 
|     return axisExtentSum - coord + coordBase; | 
|   }; | 
| } | 
| export default Grid; |