| 
/* 
 | 
* 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. 
 | 
*/ 
 | 
/** 
 | 
 * Parallel Coordinates 
 | 
 * <https://en.wikipedia.org/wiki/Parallel_coordinates> 
 | 
 */ 
 | 
import * as zrUtil from 'zrender/lib/core/util.js'; 
 | 
import * as matrix from 'zrender/lib/core/matrix.js'; 
 | 
import * as layoutUtil from '../../util/layout.js'; 
 | 
import * as axisHelper from '../../coord/axisHelper.js'; 
 | 
import ParallelAxis from './ParallelAxis.js'; 
 | 
import * as graphic from '../../util/graphic.js'; 
 | 
import * as numberUtil from '../../util/number.js'; 
 | 
import sliderMove from '../../component/helper/sliderMove.js'; 
 | 
var each = zrUtil.each; 
 | 
var mathMin = Math.min; 
 | 
var mathMax = Math.max; 
 | 
var mathFloor = Math.floor; 
 | 
var mathCeil = Math.ceil; 
 | 
var round = numberUtil.round; 
 | 
var PI = Math.PI; 
 | 
var Parallel = /** @class */function () { 
 | 
  function Parallel(parallelModel, ecModel, api) { 
 | 
    this.type = 'parallel'; 
 | 
    /** 
 | 
     * key: dimension 
 | 
     */ 
 | 
    this._axesMap = zrUtil.createHashMap(); 
 | 
    /** 
 | 
     * key: dimension 
 | 
     * value: {position: [], rotation, } 
 | 
     */ 
 | 
    this._axesLayout = {}; 
 | 
    this.dimensions = parallelModel.dimensions; 
 | 
    this._model = parallelModel; 
 | 
    this._init(parallelModel, ecModel, api); 
 | 
  } 
 | 
  Parallel.prototype._init = function (parallelModel, ecModel, api) { 
 | 
    var dimensions = parallelModel.dimensions; 
 | 
    var parallelAxisIndex = parallelModel.parallelAxisIndex; 
 | 
    each(dimensions, function (dim, idx) { 
 | 
      var axisIndex = parallelAxisIndex[idx]; 
 | 
      var axisModel = ecModel.getComponent('parallelAxis', axisIndex); 
 | 
      var axis = this._axesMap.set(dim, new ParallelAxis(dim, axisHelper.createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisIndex)); 
 | 
      var isCategory = axis.type === 'category'; 
 | 
      axis.onBand = isCategory && axisModel.get('boundaryGap'); 
 | 
      axis.inverse = axisModel.get('inverse'); 
 | 
      // Injection 
 | 
      axisModel.axis = axis; 
 | 
      axis.model = axisModel; 
 | 
      axis.coordinateSystem = axisModel.coordinateSystem = this; 
 | 
    }, this); 
 | 
  }; 
 | 
  /** 
 | 
   * Update axis scale after data processed 
 | 
   */ 
 | 
  Parallel.prototype.update = function (ecModel, api) { 
 | 
    this._updateAxesFromSeries(this._model, ecModel); 
 | 
  }; 
 | 
  Parallel.prototype.containPoint = function (point) { 
 | 
    var layoutInfo = this._makeLayoutInfo(); 
 | 
    var axisBase = layoutInfo.axisBase; 
 | 
    var layoutBase = layoutInfo.layoutBase; 
 | 
    var pixelDimIndex = layoutInfo.pixelDimIndex; 
 | 
    var pAxis = point[1 - pixelDimIndex]; 
 | 
    var pLayout = point[pixelDimIndex]; 
 | 
    return pAxis >= axisBase && pAxis <= axisBase + layoutInfo.axisLength && pLayout >= layoutBase && pLayout <= layoutBase + layoutInfo.layoutLength; 
 | 
  }; 
 | 
  Parallel.prototype.getModel = function () { 
 | 
    return this._model; 
 | 
  }; 
 | 
  /** 
 | 
   * Update properties from series 
 | 
   */ 
 | 
  Parallel.prototype._updateAxesFromSeries = function (parallelModel, ecModel) { 
 | 
    ecModel.eachSeries(function (seriesModel) { 
 | 
      if (!parallelModel.contains(seriesModel, ecModel)) { 
 | 
        return; 
 | 
      } 
 | 
      var data = seriesModel.getData(); 
 | 
      each(this.dimensions, function (dim) { 
 | 
        var axis = this._axesMap.get(dim); 
 | 
        axis.scale.unionExtentFromData(data, data.mapDimension(dim)); 
 | 
        axisHelper.niceScaleExtent(axis.scale, axis.model); 
 | 
      }, this); 
 | 
    }, this); 
 | 
  }; 
 | 
  /** 
 | 
   * Resize the parallel coordinate system. 
 | 
   */ 
 | 
  Parallel.prototype.resize = function (parallelModel, api) { 
 | 
    this._rect = layoutUtil.getLayoutRect(parallelModel.getBoxLayoutParams(), { 
 | 
      width: api.getWidth(), 
 | 
      height: api.getHeight() 
 | 
    }); 
 | 
    this._layoutAxes(); 
 | 
  }; 
 | 
  Parallel.prototype.getRect = function () { 
 | 
    return this._rect; 
 | 
  }; 
 | 
  Parallel.prototype._makeLayoutInfo = function () { 
 | 
    var parallelModel = this._model; 
 | 
    var rect = this._rect; 
 | 
    var xy = ['x', 'y']; 
 | 
    var wh = ['width', 'height']; 
 | 
    var layout = parallelModel.get('layout'); 
 | 
    var pixelDimIndex = layout === 'horizontal' ? 0 : 1; 
 | 
    var layoutLength = rect[wh[pixelDimIndex]]; 
 | 
    var layoutExtent = [0, layoutLength]; 
 | 
    var axisCount = this.dimensions.length; 
 | 
    var axisExpandWidth = restrict(parallelModel.get('axisExpandWidth'), layoutExtent); 
 | 
    var axisExpandCount = restrict(parallelModel.get('axisExpandCount') || 0, [0, axisCount]); 
 | 
    var axisExpandable = parallelModel.get('axisExpandable') && axisCount > 3 && axisCount > axisExpandCount && axisExpandCount > 1 && axisExpandWidth > 0 && layoutLength > 0; 
 | 
    // `axisExpandWindow` is According to the coordinates of [0, axisExpandLength], 
 | 
    // for sake of consider the case that axisCollapseWidth is 0 (when screen is narrow), 
 | 
    // where collapsed axes should be overlapped. 
 | 
    var axisExpandWindow = parallelModel.get('axisExpandWindow'); 
 | 
    var winSize; 
 | 
    if (!axisExpandWindow) { 
 | 
      winSize = restrict(axisExpandWidth * (axisExpandCount - 1), layoutExtent); 
 | 
      var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor(axisCount / 2); 
 | 
      axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2]; 
 | 
      axisExpandWindow[1] = axisExpandWindow[0] + winSize; 
 | 
    } else { 
 | 
      winSize = restrict(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent); 
 | 
      axisExpandWindow[1] = axisExpandWindow[0] + winSize; 
 | 
    } 
 | 
    var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount); 
 | 
    // Avoid axisCollapseWidth is too small. 
 | 
    axisCollapseWidth < 3 && (axisCollapseWidth = 0); 
 | 
    // Find the first and last indices > ewin[0] and < ewin[1]. 
 | 
    var winInnerIndices = [mathFloor(round(axisExpandWindow[0] / axisExpandWidth, 1)) + 1, mathCeil(round(axisExpandWindow[1] / axisExpandWidth, 1)) - 1]; 
 | 
    // Pos in ec coordinates. 
 | 
    var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0]; 
 | 
    return { 
 | 
      layout: layout, 
 | 
      pixelDimIndex: pixelDimIndex, 
 | 
      layoutBase: rect[xy[pixelDimIndex]], 
 | 
      layoutLength: layoutLength, 
 | 
      axisBase: rect[xy[1 - pixelDimIndex]], 
 | 
      axisLength: rect[wh[1 - pixelDimIndex]], 
 | 
      axisExpandable: axisExpandable, 
 | 
      axisExpandWidth: axisExpandWidth, 
 | 
      axisCollapseWidth: axisCollapseWidth, 
 | 
      axisExpandWindow: axisExpandWindow, 
 | 
      axisCount: axisCount, 
 | 
      winInnerIndices: winInnerIndices, 
 | 
      axisExpandWindow0Pos: axisExpandWindow0Pos 
 | 
    }; 
 | 
  }; 
 | 
  Parallel.prototype._layoutAxes = function () { 
 | 
    var rect = this._rect; 
 | 
    var axes = this._axesMap; 
 | 
    var dimensions = this.dimensions; 
 | 
    var layoutInfo = this._makeLayoutInfo(); 
 | 
    var layout = layoutInfo.layout; 
 | 
    axes.each(function (axis) { 
 | 
      var axisExtent = [0, layoutInfo.axisLength]; 
 | 
      var idx = axis.inverse ? 1 : 0; 
 | 
      axis.setExtent(axisExtent[idx], axisExtent[1 - idx]); 
 | 
    }); 
 | 
    each(dimensions, function (dim, idx) { 
 | 
      var posInfo = (layoutInfo.axisExpandable ? layoutAxisWithExpand : layoutAxisWithoutExpand)(idx, layoutInfo); 
 | 
      var positionTable = { 
 | 
        horizontal: { 
 | 
          x: posInfo.position, 
 | 
          y: layoutInfo.axisLength 
 | 
        }, 
 | 
        vertical: { 
 | 
          x: 0, 
 | 
          y: posInfo.position 
 | 
        } 
 | 
      }; 
 | 
      var rotationTable = { 
 | 
        horizontal: PI / 2, 
 | 
        vertical: 0 
 | 
      }; 
 | 
      var position = [positionTable[layout].x + rect.x, positionTable[layout].y + rect.y]; 
 | 
      var rotation = rotationTable[layout]; 
 | 
      var transform = matrix.create(); 
 | 
      matrix.rotate(transform, transform, rotation); 
 | 
      matrix.translate(transform, transform, position); 
 | 
      // TODO 
 | 
      // tick layout info 
 | 
      // TODO 
 | 
      // update dimensions info based on axis order. 
 | 
      this._axesLayout[dim] = { 
 | 
        position: position, 
 | 
        rotation: rotation, 
 | 
        transform: transform, 
 | 
        axisNameAvailableWidth: posInfo.axisNameAvailableWidth, 
 | 
        axisLabelShow: posInfo.axisLabelShow, 
 | 
        nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth, 
 | 
        tickDirection: 1, 
 | 
        labelDirection: 1 
 | 
      }; 
 | 
    }, this); 
 | 
  }; 
 | 
  /** 
 | 
   * Get axis by dim. 
 | 
   */ 
 | 
  Parallel.prototype.getAxis = function (dim) { 
 | 
    return this._axesMap.get(dim); 
 | 
  }; 
 | 
  /** 
 | 
   * Convert a dim value of a single item of series data to Point. 
 | 
   */ 
 | 
  Parallel.prototype.dataToPoint = function (value, dim) { 
 | 
    return this.axisCoordToPoint(this._axesMap.get(dim).dataToCoord(value), dim); 
 | 
  }; 
 | 
  /** 
 | 
   * Travel data for one time, get activeState of each data item. 
 | 
   * @param start the start dataIndex that travel from. 
 | 
   * @param end the next dataIndex of the last dataIndex will be travel. 
 | 
   */ 
 | 
  Parallel.prototype.eachActiveState = function (data, callback, start, end) { 
 | 
    start == null && (start = 0); 
 | 
    end == null && (end = data.count()); 
 | 
    var axesMap = this._axesMap; 
 | 
    var dimensions = this.dimensions; 
 | 
    var dataDimensions = []; 
 | 
    var axisModels = []; 
 | 
    zrUtil.each(dimensions, function (axisDim) { 
 | 
      dataDimensions.push(data.mapDimension(axisDim)); 
 | 
      axisModels.push(axesMap.get(axisDim).model); 
 | 
    }); 
 | 
    var hasActiveSet = this.hasAxisBrushed(); 
 | 
    for (var dataIndex = start; dataIndex < end; dataIndex++) { 
 | 
      var activeState = void 0; 
 | 
      if (!hasActiveSet) { 
 | 
        activeState = 'normal'; 
 | 
      } else { 
 | 
        activeState = 'active'; 
 | 
        var values = data.getValues(dataDimensions, dataIndex); 
 | 
        for (var j = 0, lenj = dimensions.length; j < lenj; j++) { 
 | 
          var state = axisModels[j].getActiveState(values[j]); 
 | 
          if (state === 'inactive') { 
 | 
            activeState = 'inactive'; 
 | 
            break; 
 | 
          } 
 | 
        } 
 | 
      } 
 | 
      callback(activeState, dataIndex); 
 | 
    } 
 | 
  }; 
 | 
  /** 
 | 
   * Whether has any activeSet. 
 | 
   */ 
 | 
  Parallel.prototype.hasAxisBrushed = function () { 
 | 
    var dimensions = this.dimensions; 
 | 
    var axesMap = this._axesMap; 
 | 
    var hasActiveSet = false; 
 | 
    for (var j = 0, lenj = dimensions.length; j < lenj; j++) { 
 | 
      if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') { 
 | 
        hasActiveSet = true; 
 | 
      } 
 | 
    } 
 | 
    return hasActiveSet; 
 | 
  }; 
 | 
  /** 
 | 
   * Convert coords of each axis to Point. 
 | 
   *  Return point. For example: [10, 20] 
 | 
   */ 
 | 
  Parallel.prototype.axisCoordToPoint = function (coord, dim) { 
 | 
    var axisLayout = this._axesLayout[dim]; 
 | 
    return graphic.applyTransform([coord, 0], axisLayout.transform); 
 | 
  }; 
 | 
  /** 
 | 
   * Get axis layout. 
 | 
   */ 
 | 
  Parallel.prototype.getAxisLayout = function (dim) { 
 | 
    return zrUtil.clone(this._axesLayout[dim]); 
 | 
  }; 
 | 
  /** 
 | 
   * @return {Object} {axisExpandWindow, delta, behavior: 'jump' | 'slide' | 'none'}. 
 | 
   */ 
 | 
  Parallel.prototype.getSlidedAxisExpandWindow = function (point) { 
 | 
    var layoutInfo = this._makeLayoutInfo(); 
 | 
    var pixelDimIndex = layoutInfo.pixelDimIndex; 
 | 
    var axisExpandWindow = layoutInfo.axisExpandWindow.slice(); 
 | 
    var winSize = axisExpandWindow[1] - axisExpandWindow[0]; 
 | 
    var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)]; 
 | 
    // Out of the area of coordinate system. 
 | 
    if (!this.containPoint(point)) { 
 | 
      return { 
 | 
        behavior: 'none', 
 | 
        axisExpandWindow: axisExpandWindow 
 | 
      }; 
 | 
    } 
 | 
    // Convert the point from global to expand coordinates. 
 | 
    var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos; 
 | 
    // For dragging operation convenience, the window should not be 
 | 
    // slided when mouse is the center area of the window. 
 | 
    var delta; 
 | 
    var behavior = 'slide'; 
 | 
    var axisCollapseWidth = layoutInfo.axisCollapseWidth; 
 | 
    var triggerArea = this._model.get('axisExpandSlideTriggerArea'); 
 | 
    // But consider touch device, jump is necessary. 
 | 
    var useJump = triggerArea[0] != null; 
 | 
    if (axisCollapseWidth) { 
 | 
      if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) { 
 | 
        behavior = 'jump'; 
 | 
        delta = pointCoord - winSize * triggerArea[2]; 
 | 
      } else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) { 
 | 
        behavior = 'jump'; 
 | 
        delta = pointCoord - winSize * (1 - triggerArea[2]); 
 | 
      } else { 
 | 
        (delta = pointCoord - winSize * triggerArea[1]) >= 0 && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0 && (delta = 0); 
 | 
      } 
 | 
      delta *= layoutInfo.axisExpandWidth / axisCollapseWidth; 
 | 
      delta ? sliderMove(delta, axisExpandWindow, extent, 'all') 
 | 
      // Avoid nonsense triger on mousemove. 
 | 
      : behavior = 'none'; 
 | 
    } 
 | 
    // When screen is too narrow, make it visible and slidable, although it is hard to interact. 
 | 
    else { 
 | 
      var winSize2 = axisExpandWindow[1] - axisExpandWindow[0]; 
 | 
      var pos = extent[1] * pointCoord / winSize2; 
 | 
      axisExpandWindow = [mathMax(0, pos - winSize2 / 2)]; 
 | 
      axisExpandWindow[1] = mathMin(extent[1], axisExpandWindow[0] + winSize2); 
 | 
      axisExpandWindow[0] = axisExpandWindow[1] - winSize2; 
 | 
    } 
 | 
    return { 
 | 
      axisExpandWindow: axisExpandWindow, 
 | 
      behavior: behavior 
 | 
    }; 
 | 
  }; 
 | 
  return Parallel; 
 | 
}(); 
 | 
function restrict(len, extent) { 
 | 
  return mathMin(mathMax(len, extent[0]), extent[1]); 
 | 
} 
 | 
function layoutAxisWithoutExpand(axisIndex, layoutInfo) { 
 | 
  var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1); 
 | 
  return { 
 | 
    position: step * axisIndex, 
 | 
    axisNameAvailableWidth: step, 
 | 
    axisLabelShow: true 
 | 
  }; 
 | 
} 
 | 
function layoutAxisWithExpand(axisIndex, layoutInfo) { 
 | 
  var layoutLength = layoutInfo.layoutLength; 
 | 
  var axisExpandWidth = layoutInfo.axisExpandWidth; 
 | 
  var axisCount = layoutInfo.axisCount; 
 | 
  var axisCollapseWidth = layoutInfo.axisCollapseWidth; 
 | 
  var winInnerIndices = layoutInfo.winInnerIndices; 
 | 
  var position; 
 | 
  var axisNameAvailableWidth = axisCollapseWidth; 
 | 
  var axisLabelShow = false; 
 | 
  var nameTruncateMaxWidth; 
 | 
  if (axisIndex < winInnerIndices[0]) { 
 | 
    position = axisIndex * axisCollapseWidth; 
 | 
    nameTruncateMaxWidth = axisCollapseWidth; 
 | 
  } else if (axisIndex <= winInnerIndices[1]) { 
 | 
    position = layoutInfo.axisExpandWindow0Pos + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0]; 
 | 
    axisNameAvailableWidth = axisExpandWidth; 
 | 
    axisLabelShow = true; 
 | 
  } else { 
 | 
    position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth; 
 | 
    nameTruncateMaxWidth = axisCollapseWidth; 
 | 
  } 
 | 
  return { 
 | 
    position: position, 
 | 
    axisNameAvailableWidth: axisNameAvailableWidth, 
 | 
    axisLabelShow: axisLabelShow, 
 | 
    nameTruncateMaxWidth: nameTruncateMaxWidth 
 | 
  }; 
 | 
} 
 | 
export default Parallel; 
 |