Matrix.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { getLayoutRect } from '../../util/layout.js';
  41. import { ListIterator } from '../../util/model.js';
  42. import { eqNaN, isArray, retrieve2 } from 'zrender/lib/core/util.js';
  43. import { WH, XY } from '../../util/graphic.js';
  44. import Model from '../../model/Model.js';
  45. import { mathMax, mathMin, parsePositionSizeOption } from '../../util/number.js';
  46. import { createNaNRectLike, MatrixClampOption, MatrixCellLayoutInfoType, parseCoordRangeOption, resetXYLocatorRange, xyLocatorRangeToRectOneDim } from './matrixCoordHelper.js';
  47. import { error } from '../../util/log.js';
  48. import { injectCoordSysByOption, simpleCoordSysInjectionProvider } from '../../core/CoordinateSystem.js';
  49. var Matrix = /** @class */function () {
  50. function Matrix(matrixModel, ecModel, api) {
  51. this.dimensions = Matrix.dimensions;
  52. this.type = 'matrix';
  53. this._model = matrixModel;
  54. var models = this._dimModels = {
  55. x: matrixModel.getDimensionModel('x'),
  56. y: matrixModel.getDimensionModel('y')
  57. };
  58. this._dims = {
  59. x: models.x.dim,
  60. y: models.y.dim
  61. };
  62. this._resize(matrixModel, api);
  63. }
  64. /**
  65. * @see fetchers in `model/referHelper.ts`,
  66. * which is used to parse data in ordinal way.
  67. * In most series only 'x' and 'y' is required,
  68. * but some series, such as heatmap, can specify value.
  69. */
  70. Matrix.getDimensionsInfo = function () {
  71. return [{
  72. name: 'x',
  73. type: 'ordinal'
  74. }, {
  75. name: 'y',
  76. type: 'ordinal'
  77. }, {
  78. name: 'value'
  79. }];
  80. };
  81. Matrix.create = function (ecModel, api) {
  82. var matrixList = [];
  83. ecModel.eachComponent('matrix', function (matrixModel) {
  84. var matrix = new Matrix(matrixModel, ecModel, api);
  85. matrixList.push(matrix);
  86. matrixModel.coordinateSystem = matrix;
  87. });
  88. // Inject coordinate system
  89. // PENDING: optimize to not to travel all components?
  90. // (collect relevant components in ecModel only when model update?)
  91. ecModel.eachComponent(function (mainType, componentModel) {
  92. injectCoordSysByOption({
  93. targetModel: componentModel,
  94. coordSysType: 'matrix',
  95. coordSysProvider: simpleCoordSysInjectionProvider
  96. });
  97. });
  98. return matrixList;
  99. };
  100. Matrix.prototype.getRect = function () {
  101. return this._rect;
  102. };
  103. Matrix.prototype._resize = function (matrixModel, api) {
  104. var dims = this._dims;
  105. var dimModels = this._dimModels;
  106. var rect = this._rect = getLayoutRect(matrixModel.getBoxLayoutParams(), {
  107. width: api.getWidth(),
  108. height: api.getHeight()
  109. });
  110. layOutUnitsOnDimension(dimModels, dims, rect, 0);
  111. layOutUnitsOnDimension(dimModels, dims, rect, 1);
  112. layOutDimCellsRestInfoByUnit(0, dims);
  113. layOutDimCellsRestInfoByUnit(1, dims);
  114. layOutBodyCornerCellMerge(this._model.getBody(), dims);
  115. layOutBodyCornerCellMerge(this._model.getCorner(), dims);
  116. };
  117. /**
  118. * @implement
  119. * - The input is allowed to be `[NaN/null/undefined, xxx]`/`[xxx, NaN/null/undefined]`;
  120. * the return is `[NaN, xxxresult]`/`[xxxresult, NaN]` or clamped boundary value if
  121. * `clamp` passed. This is for the usage that only get coord on single x or y.
  122. * - Alwasy return an numeric array, but never be null/undefined.
  123. * If it can not be located or invalid, return `[NaN, NaN]`.
  124. */
  125. Matrix.prototype.dataToPoint = function (data, opt, out) {
  126. out = out || [];
  127. this.dataToLayout(data, opt, _dtpOutDataToLayout);
  128. out[0] = _dtpOutDataToLayout.rect.x + _dtpOutDataToLayout.rect.width / 2;
  129. out[1] = _dtpOutDataToLayout.rect.y + _dtpOutDataToLayout.rect.height / 2;
  130. return out;
  131. };
  132. /**
  133. * @implement
  134. * - The input is allowed to be `[NaN/null/undefined, xxx]`/`[xxx, NaN/null/undefined]`;
  135. * the return is `{x: NaN, width: NaN, y: xxxresulty, height: xxxresulth}`/
  136. * `{y: NaN, height: NaN, x: xxxresultx, width: xxxresultw}` or clamped boundary value
  137. * if `clamp` passed. This is for the usage that only get coord on single x or y.
  138. * - The returned `out.rect` and `out.matrixXYLocatorRange` is always an object or an 2d-array,
  139. * but never be null/undefined. If it cannot be located or invalid, `NaN` is in their
  140. * corresponding number props.
  141. * - Do not provide `out.contentRect`, because it's allowed to input non-leaf dimension x/y or
  142. * a range of x/y, which determines a rect covering multiple cells (even not merged), in which
  143. * case the padding and borderWidth can not be determined to make a contentRect. Therefore only
  144. * return `out.rect` in any case for consistency. The caller is responsible for adding space to
  145. * avoid covering cell borders, if necessary.
  146. */
  147. Matrix.prototype.dataToLayout = function (data, opt, out) {
  148. var dims = this._dims;
  149. out = out || {};
  150. var outRect = out.rect = out.rect || {};
  151. outRect.x = outRect.y = outRect.width = outRect.height = NaN;
  152. var outLocRange = out.matrixXYLocatorRange = resetXYLocatorRange(out.matrixXYLocatorRange);
  153. if (!isArray(data)) {
  154. if (process.env.NODE_ENV !== 'production') {
  155. error('Input data must be an array in `convertToLayout`, `convertToPixel`');
  156. }
  157. return out;
  158. }
  159. parseCoordRangeOption(outLocRange, null, data, dims, retrieve2(opt && opt.clamp, MatrixClampOption.none));
  160. if (!opt || !opt.ignoreMergeCells) {
  161. if (!opt || opt.clamp !== MatrixClampOption.corner) {
  162. this._model.getBody().expandRangeByCellMerge(outLocRange);
  163. }
  164. if (!opt || opt.clamp !== MatrixClampOption.body) {
  165. this._model.getCorner().expandRangeByCellMerge(outLocRange);
  166. }
  167. }
  168. xyLocatorRangeToRectOneDim(outRect, outLocRange, dims, 0);
  169. xyLocatorRangeToRectOneDim(outRect, outLocRange, dims, 1);
  170. return out;
  171. };
  172. /**
  173. * The returned locator pair can be the input of `dataToPoint` or `dataToLayout`.
  174. *
  175. * If point[0] is out of the matrix rect,
  176. * the out[0] is NaN;
  177. * else if it is on the right of top-left corner of body,
  178. * the out[0] is the oridinal number (>= 0).
  179. * else
  180. * out[0] is the locator for corner or header (<= 0).
  181. *
  182. * The same rule goes for point[1] and out[1].
  183. *
  184. * But point[0] and point[1] are calculated separately, i.e.,
  185. * the reuslt can be `[1, NaN]` or `[NaN, 1]` if only one dimension is out of boundary.
  186. *
  187. * @implement
  188. */
  189. Matrix.prototype.pointToData = function (point, opt, out) {
  190. var dims = this._dims;
  191. pointToDataOneDimPrepareCtx(_tmpCtxPointToData, 0, dims, point, opt && opt.clamp);
  192. pointToDataOneDimPrepareCtx(_tmpCtxPointToData, 1, dims, point, opt && opt.clamp);
  193. out = out || [];
  194. out[0] = out[1] = NaN;
  195. if (_tmpCtxPointToData.y === CtxPointToDataAreaType.inCorner && _tmpCtxPointToData.x === CtxPointToDataAreaType.inBody) {
  196. pointToDataOnlyHeaderFillOut(_tmpCtxPointToData, out, 0, dims);
  197. } else if (_tmpCtxPointToData.x === CtxPointToDataAreaType.inCorner && _tmpCtxPointToData.y === CtxPointToDataAreaType.inBody) {
  198. pointToDataOnlyHeaderFillOut(_tmpCtxPointToData, out, 1, dims);
  199. } else {
  200. pointToDataBodyCornerFillOut(_tmpCtxPointToData, out, 0, dims);
  201. pointToDataBodyCornerFillOut(_tmpCtxPointToData, out, 1, dims);
  202. }
  203. return out;
  204. };
  205. Matrix.prototype.convertToPixel = function (ecModel, finder, value, opt) {
  206. var coordSys = getCoordSys(finder);
  207. return coordSys === this ? coordSys.dataToPoint(value, opt) : undefined;
  208. };
  209. Matrix.prototype.convertToLayout = function (ecModel, finder, value, opt) {
  210. var coordSys = getCoordSys(finder);
  211. return coordSys === this ? coordSys.dataToLayout(value, opt) : undefined;
  212. };
  213. Matrix.prototype.convertFromPixel = function (ecModel, finder, pixel, opt) {
  214. var coordSys = getCoordSys(finder);
  215. return coordSys === this ? coordSys.pointToData(pixel, opt) : undefined;
  216. };
  217. Matrix.prototype.containPoint = function (point) {
  218. return this._rect.contain(point[0], point[1]);
  219. };
  220. Matrix.dimensions = ['x', 'y', 'value'];
  221. return Matrix;
  222. }();
  223. var _dtpOutDataToLayout = {
  224. rect: createNaNRectLike()
  225. };
  226. var _ptdLevelIt = new ListIterator();
  227. var _ptdDimCellIt = new ListIterator();
  228. function layOutUnitsOnDimension(dimModels, dims, matrixRect, dimIdx) {
  229. var otherDimIdx = 1 - dimIdx;
  230. var thisDim = dims[XY[dimIdx]];
  231. var otherDim = dims[XY[otherDimIdx]];
  232. // Notice: If matrix.x/y.show is false, still lay out, to ensure the
  233. // consistent return of `dataToLayout`.
  234. var otherDimShow = otherDim.shouldShow();
  235. // Reset
  236. for (var it_1 = thisDim.resetCellIterator(); it_1.next();) {
  237. it_1.item.wh = it_1.item.xy = NaN;
  238. }
  239. for (var it_2 = otherDim.resetLayoutIterator(null, dimIdx); it_2.next();) {
  240. it_2.item.wh = it_2.item.xy = NaN;
  241. }
  242. // Set specified size from option.
  243. var restSize = matrixRect[WH[dimIdx]];
  244. var restCellsCount = thisDim.getLocatorCount(dimIdx) + otherDim.getLocatorCount(dimIdx);
  245. var tmpLevelModel = new Model();
  246. for (var it_3 = otherDim.resetLevelIterator(); it_3.next();) {
  247. // Consider `matrix.x.levelSize` and `matrix.x.levels[i].levelSize`.
  248. tmpLevelModel.option = it_3.item.option;
  249. tmpLevelModel.parentModel = dimModels[XY[otherDimIdx]];
  250. layOutSpecified(it_3.item, otherDimShow ? tmpLevelModel.get('levelSize') : 0);
  251. }
  252. var tmpCellModel = new Model();
  253. for (var it_4 = thisDim.resetCellIterator(); it_4.next();) {
  254. // Only leaf support size specification, to avoid unnecessary complexity.
  255. if (it_4.item.type === MatrixCellLayoutInfoType.leaf) {
  256. tmpCellModel.option = it_4.item.option;
  257. tmpCellModel.parentModel = undefined;
  258. layOutSpecified(it_4.item, tmpCellModel.get('size'));
  259. }
  260. }
  261. function layOutSpecified(item, sizeOption) {
  262. var size = parseSizeOption(sizeOption, dimIdx, matrixRect);
  263. if (!eqNaN(size)) {
  264. item.wh = confineSize(size, restSize);
  265. restSize = confineSize(restSize - item.wh);
  266. restCellsCount--;
  267. }
  268. }
  269. // Set all sizes and positions to levels and leaf cells of which size is unspecified.
  270. // Contents lay out based on matrix, rather than inverse; therefore do not support
  271. // calculating size based on content, but allocate equally.
  272. var computedCellWH = restCellsCount ? restSize / restCellsCount : 0;
  273. // If all size specified, but some space remain (may also caused by matrix.x/y.show: false)
  274. // do not align to the big most edge.
  275. var notAlignToBigmost = !restCellsCount && restSize >= 1; // `1` for cumulative precision error.
  276. var currXY = matrixRect[XY[dimIdx]];
  277. var maxLocator = thisDim.getLocatorCount(dimIdx) - 1;
  278. var it = new ListIterator();
  279. // Lay out levels of the perpendicular dim.
  280. for (otherDim.resetLayoutIterator(it, dimIdx); it.next();) {
  281. layOutUnspecified(it.item);
  282. }
  283. for (thisDim.resetLayoutIterator(it, dimIdx); it.next();) {
  284. layOutUnspecified(it.item);
  285. }
  286. function layOutUnspecified(item) {
  287. if (eqNaN(item.wh)) {
  288. item.wh = computedCellWH;
  289. }
  290. item.xy = currXY;
  291. if (item.id[XY[dimIdx]] === maxLocator && !notAlignToBigmost) {
  292. // Align to the rightmost border, consider cumulative precision error.
  293. item.wh = matrixRect[XY[dimIdx]] + matrixRect[WH[dimIdx]] - item.xy;
  294. }
  295. currXY += item.wh;
  296. }
  297. }
  298. function layOutDimCellsRestInfoByUnit(dimIdx, dims) {
  299. // Finally save layout info based on the unit leaves and levels.
  300. for (var it_5 = dims[XY[dimIdx]].resetCellIterator(); it_5.next();) {
  301. var dimCell = it_5.item;
  302. layOutRectOneDimBasedOnUnit(dimCell.rect, dimIdx, dimCell.id, dimCell.span, dims);
  303. // Consider level varitation on tree leaves, should extend the size to touch matrix body
  304. // to avoid weird appearance.
  305. layOutRectOneDimBasedOnUnit(dimCell.rect, 1 - dimIdx, dimCell.id, dimCell.span, dims);
  306. if (dimCell.type === MatrixCellLayoutInfoType.nonLeaf) {
  307. // `xy` and `wh` need to be saved in non-leaf since it supports locating by non-leaf
  308. // in `dataToPoint` or `dataToLayout`.
  309. dimCell.xy = dimCell.rect[XY[dimIdx]];
  310. dimCell.wh = dimCell.rect[WH[dimIdx]];
  311. }
  312. }
  313. }
  314. function layOutBodyCornerCellMerge(bodyOrCorner, dims) {
  315. bodyOrCorner.travelExistingCells(function (cell) {
  316. var computedSpan = cell.span;
  317. if (computedSpan) {
  318. var layoutRect = cell.spanRect;
  319. var id = cell.id;
  320. layOutRectOneDimBasedOnUnit(layoutRect, 0, id, computedSpan, dims);
  321. layOutRectOneDimBasedOnUnit(layoutRect, 1, id, computedSpan, dims);
  322. }
  323. });
  324. }
  325. // Save to rect for rendering.
  326. function layOutRectOneDimBasedOnUnit(outRect, dimIdx, id, span, dims) {
  327. outRect[WH[dimIdx]] = 0;
  328. var locator = id[XY[dimIdx]];
  329. var dim = locator < 0 ? dims[XY[1 - dimIdx]] : dims[XY[dimIdx]];
  330. var layoutUnit = dim.getUnitLayoutInfo(dimIdx, id[XY[dimIdx]]);
  331. outRect[XY[dimIdx]] = layoutUnit.xy;
  332. outRect[WH[dimIdx]] = layoutUnit.wh;
  333. if (span[XY[dimIdx]] > 1) {
  334. var layoutUnit2 = dim.getUnitLayoutInfo(dimIdx, id[XY[dimIdx]] + span[XY[dimIdx]] - 1);
  335. // Be careful the cumulative error - cell must be aligned.
  336. outRect[WH[dimIdx]] = layoutUnit2.xy + layoutUnit2.wh - layoutUnit.xy;
  337. }
  338. }
  339. /**
  340. * Return NaN if not defined or invalid.
  341. */
  342. function parseSizeOption(sizeOption, dimIdx, matrixRect) {
  343. var sizeNum = parsePositionSizeOption(sizeOption, matrixRect[WH[dimIdx]]);
  344. return confineSize(sizeNum, matrixRect[WH[dimIdx]]);
  345. }
  346. function confineSize(sizeNum, sizeLimit) {
  347. return Math.max(Math.min(sizeNum, retrieve2(sizeLimit, Infinity)), 0);
  348. }
  349. function getCoordSys(finder) {
  350. var matrixModel = finder.matrixModel;
  351. var seriesModel = finder.seriesModel;
  352. var coordSys = matrixModel ? matrixModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem : null;
  353. return coordSys;
  354. }
  355. var CtxPointToDataAreaType = {
  356. inBody: 1,
  357. inCorner: 2,
  358. outside: 3
  359. };
  360. // For handy performance optimization in pointToData.
  361. var _tmpCtxPointToData = {
  362. x: null,
  363. y: null,
  364. point: []
  365. };
  366. function pointToDataOneDimPrepareCtx(ctx, dimIdx, dims, point, clamp) {
  367. var thisDim = dims[XY[dimIdx]];
  368. var otherDim = dims[XY[1 - dimIdx]];
  369. // Notice: considered cases: `matrix.x/y.show: false`, `matrix.x/y.data` is empty.
  370. // In this cases the `layout.xy` is on the edge and `layout.wh` is `0`; they still can be
  371. // use to calculate clampping.
  372. var bodyMaxUnit = thisDim.getUnitLayoutInfo(dimIdx, thisDim.getLocatorCount(dimIdx) - 1);
  373. var body0Unit = thisDim.getUnitLayoutInfo(dimIdx, 0);
  374. var cornerMinUnit = otherDim.getUnitLayoutInfo(dimIdx, -otherDim.getLocatorCount(dimIdx));
  375. var cornerMinus1Unit = otherDim.shouldShow() ? otherDim.getUnitLayoutInfo(dimIdx, -1) : null;
  376. var coord = ctx.point[dimIdx] = point[dimIdx]; // Transfer the oridinal coord.
  377. if (!body0Unit && !cornerMinus1Unit) {
  378. ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
  379. return;
  380. }
  381. if (clamp === MatrixClampOption.body) {
  382. if (body0Unit) {
  383. ctx[XY[dimIdx]] = CtxPointToDataAreaType.inBody;
  384. coord = mathMin(bodyMaxUnit.xy + bodyMaxUnit.wh, mathMax(body0Unit.xy, coord));
  385. ctx.point[dimIdx] = coord;
  386. } else {
  387. // If clamp to body, the result must not be in header.
  388. ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
  389. }
  390. return;
  391. } else if (clamp === MatrixClampOption.corner) {
  392. if (cornerMinus1Unit) {
  393. ctx[XY[dimIdx]] = CtxPointToDataAreaType.inCorner;
  394. coord = mathMin(cornerMinus1Unit.xy + cornerMinus1Unit.wh, mathMax(cornerMinUnit.xy, coord));
  395. ctx.point[dimIdx] = coord;
  396. } else {
  397. // If clamp to corner, the result must not be in body.
  398. ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
  399. }
  400. return;
  401. }
  402. var pxLoc0 = body0Unit ? body0Unit.xy : cornerMinus1Unit ? cornerMinus1Unit.xy + cornerMinus1Unit.wh : NaN;
  403. var pxMin = cornerMinUnit ? cornerMinUnit.xy : pxLoc0;
  404. var pxMax = bodyMaxUnit ? bodyMaxUnit.xy + bodyMaxUnit.wh : pxLoc0;
  405. if (coord < pxMin) {
  406. if (!clamp) {
  407. // Quick pass for later calc, since mouse event on any place will enter this method if use `pointToData`.
  408. ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
  409. return;
  410. }
  411. coord = pxMin;
  412. } else if (coord > pxMax) {
  413. if (!clamp) {
  414. ctx[XY[dimIdx]] = CtxPointToDataAreaType.outside;
  415. return;
  416. }
  417. coord = pxMax;
  418. }
  419. ctx.point[dimIdx] = coord; // Save the updated coord.
  420. ctx[XY[dimIdx]] = pxLoc0 <= coord && coord <= pxMax ? CtxPointToDataAreaType.inBody : pxMin <= coord && coord <= pxLoc0 ? CtxPointToDataAreaType.inCorner : CtxPointToDataAreaType.outside;
  421. // Every props in ctx must be set in every branch of this method.
  422. }
  423. // Assume partialOut has been set to NaN outside.
  424. // This method may fill out[0] and out[1] in one call.
  425. function pointToDataOnlyHeaderFillOut(ctx, partialOut, dimIdx, dims) {
  426. var otherDimIdx = 1 - dimIdx;
  427. if (ctx[XY[dimIdx]] === CtxPointToDataAreaType.outside) {
  428. return;
  429. }
  430. for (dims[XY[dimIdx]].resetCellIterator(_ptdDimCellIt); _ptdDimCellIt.next();) {
  431. var cell = _ptdDimCellIt.item;
  432. if (isCoordInRect(ctx.point[dimIdx], cell.rect, dimIdx) && isCoordInRect(ctx.point[otherDimIdx], cell.rect, otherDimIdx)) {
  433. // non-leaves are also allowed to be located.
  434. // If the point is in x or y dimension cell area, should check both x and y coord to
  435. // determine a cell; in this way a non-leaf cell can be determined.
  436. partialOut[dimIdx] = cell.ordinal;
  437. partialOut[otherDimIdx] = cell.id[XY[otherDimIdx]];
  438. return;
  439. }
  440. }
  441. }
  442. // Assume partialOut has been set to NaN outside.
  443. // This method may fill out[0] and out[1] in one call.
  444. function pointToDataBodyCornerFillOut(ctx, partialOut, dimIdx, dims) {
  445. if (ctx[XY[dimIdx]] === CtxPointToDataAreaType.outside) {
  446. return;
  447. }
  448. var dim = ctx[XY[dimIdx]] === CtxPointToDataAreaType.inCorner ? dims[XY[1 - dimIdx]] : dims[XY[dimIdx]];
  449. for (dim.resetLayoutIterator(_ptdLevelIt, dimIdx); _ptdLevelIt.next();) {
  450. if (isCoordInLayoutInfo(ctx.point[dimIdx], _ptdLevelIt.item)) {
  451. partialOut[dimIdx] = _ptdLevelIt.item.id[XY[dimIdx]];
  452. return;
  453. }
  454. }
  455. }
  456. function isCoordInLayoutInfo(coord, cell) {
  457. return cell.xy <= coord && coord <= cell.xy + cell.wh;
  458. }
  459. function isCoordInRect(coord, rect, dimIdx) {
  460. return rect[XY[dimIdx]] <= coord && coord <= rect[XY[dimIdx]] + rect[WH[dimIdx]];
  461. }
  462. export default Matrix;