UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

285 lines (284 loc) 14.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hitTestHelpersRectangleSeries = void 0; var ColumnMode_1 = require("../../../../types/ColumnMode"); var vectorToArray_1 = require("../../../../utils/vectorToArray"); function testIsYHit(yValues, y1Values, yCoordinateCalculator, yHitCoord, defaultY1, resPointIndex, columnYMode) { var yValue = yValues ? yValues.get(resPointIndex) : 1; var y1Value = y1Values ? y1Values.get(resPointIndex) : defaultY1; var top = yValue; var bottom = y1Value; switch (columnYMode) { case ColumnMode_1.EColumnYMode.TopBottom: break; case ColumnMode_1.EColumnYMode.TopHeight: bottom = yValue - y1Value; break; case ColumnMode_1.EColumnYMode.CenterHeight: var halfHeight = y1Value / 2; top = yValue + halfHeight; bottom = yValue - halfHeight; break; } var topCoord = yCoordinateCalculator.getCoordinate(top); var bottomCoord = yCoordinateCalculator.getCoordinate(bottom); var maxYValue = Math.max(topCoord, bottomCoord); var minYValue = Math.min(topCoord, bottomCoord); return minYValue <= yHitCoord && yHitCoord <= maxYValue; } /** * Hit-test function for BoxSeries or PolarColumnSeries * Only for sorted data without overlapping columns only for columnXMode = EColumnMode.Mid or EColumnMode.Start * Using binary search, time complexity O(log(N)) */ function hitTestForBoxSorted(wasmContext, xCoordinateCalculator, yCoordinateCalculator, xValues, yValues, y1Values, xHitCoord, yHitCoord, defaultY1, columnCoordWidth, columnXMode, columnYMode, isPolar) { var _a; var xHitValue = xCoordinateCalculator.getDataValue(xHitCoord); var hitValuesArray = [[xHitValue, xHitCoord]]; if (isPolar) { var xHitCoordMinus2Pi = xHitCoord - 2 * Math.PI; var xHitValueMinus2Pi = xCoordinateCalculator.getDataValue(xHitCoordMinus2Pi); hitValuesArray.push([xHitValueMinus2Pi, xHitCoordMinus2Pi]); var xHitCoordPlus2Pi = xHitCoord + 2 * Math.PI; var xHitValuePlus2Pi = xCoordinateCalculator.getDataValue(xHitCoordPlus2Pi); hitValuesArray.push([xHitValuePlus2Pi, xHitCoordPlus2Pi]); } var xVectorSize = xValues.size(); var xOffsetDirection = xCoordinateCalculator.isFlipped ? -1 : 1; var xCoordOffset = columnXMode === ColumnMode_1.EColumnMode.Mid ? 0 : columnCoordWidth / 2; var xValueOffset = xCoordinateCalculator.getDataWidth(xCoordOffset); var getNearestXIndexFn = function (xHitValue$, xHitCoord$) { var xIndex$ = wasmContext.NumberUtil.FindIndex(xValues, xHitValue$ - xValueOffset, wasmContext.SCRTFindIndexSearchMode.Nearest, true); if (xIndex$ === -1) return { index: -1, dist: Number.MAX_VALUE, xCoord: undefined, xHitCoord: undefined }; var xCoord$ = xCoordinateCalculator.getCoordinate(xValues.get(xIndex$)); var dist$ = Math.abs(xCoord$ + xOffsetDirection * xCoordOffset - xHitCoord$); return { index: xIndex$, dist: dist$, xCoord: xCoord$, xHitCoord: xHitCoord$ }; }; var resIndex = -1; var resDist = Number.MAX_VALUE; var resXCoord = undefined; var resXHitCoord = undefined; hitValuesArray.forEach(function (_a) { var value = _a[0], coord = _a[1]; var r = getNearestXIndexFn(value, coord); if (r.index >= 0 && r.dist < resDist) { resIndex = r.index; resDist = r.dist; resXCoord = r.xCoord; resXHitCoord = r.xHitCoord; } }); if (resIndex === -1) return { isHit: false, nearestPointIndex: -1, isWithinDataBounds: false }; var isXHit = resDist <= columnCoordWidth / 2; var isYHit = testIsYHit(yValues, y1Values, yCoordinateCalculator, yHitCoord, defaultY1, resIndex, columnYMode); var isWithinDataBounds = false; if (resIndex > 0 && resIndex < xVectorSize - 1) { isWithinDataBounds = true; } if (xValues.size() <= 1) { isWithinDataBounds = isXHit; } else { if (xCoordinateCalculator.isFlipped) { if (resIndex === 0 && (resXHitCoord <= resXCoord + xOffsetDirection * xCoordOffset || isXHit)) { isWithinDataBounds = true; } if (resIndex === xVectorSize - 1 && (resXHitCoord >= resXCoord + xOffsetDirection * xCoordOffset || isXHit)) { isWithinDataBounds = true; } } else { if (resIndex === 0 && (resXHitCoord >= resXCoord + xOffsetDirection * xCoordOffset || isXHit)) { isWithinDataBounds = true; } if (resIndex === xVectorSize - 1 && (resXHitCoord <= resXCoord + xOffsetDirection * xCoordOffset || isXHit)) { isWithinDataBounds = true; } } } var isCategoryAxis = xCoordinateCalculator.isCategoryCoordinateCalculator; var xValue = isCategoryAxis ? resIndex : xValues.get(resIndex); var yValue = yValues.get(resIndex); var x1Value = undefined; var y1Value = (_a = y1Values === null || y1Values === void 0 ? void 0 : y1Values.get) === null || _a === void 0 ? void 0 : _a.call(y1Values, resIndex); return { nearestPointIndex: resIndex, isHit: isXHit && isYHit, isWithinDataBounds: isWithinDataBounds, xValue: xValue, yValue: yValue, x1Value: x1Value, y1Value: y1Value }; } /** * Hit-test function for BoxSeries or PolarColumnSeries * Iterates over all data points, time complexity O(N) */ function hitTestForBoxUnsorted(wasmContext, xCoordinateCalculator, yCoordinateCalculator, xValues, x1Values, yValues, y1Values, xHitCoord, yHitCoord, defaultY1, columnCoordWidth, columnXMode, columnYMode, isVertical, isPolar) { var _a, _b; var xVectorSize = xValues.size(); var halfColumn = columnCoordWidth / 2; var resIndex = -1; var resCoordDist = Number.MAX_VALUE; var resIsHit = false; var resXHitCoord = undefined; var resLeftDataBoundCoord = Number.MAX_VALUE; var resRightDataBoundCoord = Number.NEGATIVE_INFINITY; var calcDistFn = function (left$, right$, val$) { var a = right$ - val$; var b = val$ - left$; return a >= 0 && b >= 0 ? 0 : Math.min(Math.abs(a), Math.abs(b)); }; var testIsXHitFn = function (left$, right$) { var r = calcDistFn(left$, right$, xHitCoord); var dist$ = r; var xHitCoord$ = xHitCoord; if (isPolar && !isVertical) { var xHitCoordMinus2Pi = xHitCoord - 2 * Math.PI; var xHitCoordPlus2Pi = xHitCoord + 2 * Math.PI; [xHitCoordMinus2Pi, xHitCoordPlus2Pi].forEach(function (c) { var r = calcDistFn(left$, right$, c); if (r < dist$) { dist$ = r; xHitCoord$ = c; } }); } return { xCoordDist: dist$, xHitCoord: xHitCoord$, isHit: dist$ === 0 }; }; var updateResValuesFn = function (left$, right$, index$) { // Calculating data bounds if (left$ < resLeftDataBoundCoord) resLeftDataBoundCoord = left$; if (right$ > resRightDataBoundCoord) resRightDataBoundCoord = right$; var isYHit$ = testIsYHit(yValues, y1Values, yCoordinateCalculator, yHitCoord, defaultY1, index$, columnYMode); var _a = testIsXHitFn(left$, right$), isXHit$ = _a.isHit, xCoordDist$ = _a.xCoordDist, xHitCoord$ = _a.xHitCoord; var isBothHit$ = isXHit$ && isYHit$; if (resIsHit) { if (isBothHit$ && xCoordDist$ < resCoordDist) { resIndex = index$; resCoordDist = xCoordDist$; resXHitCoord = xHitCoord$; } } else { if (isBothHit$) { resIsHit = true; resIndex = index$; resCoordDist = xCoordDist$; resXHitCoord = xHitCoord$; } else { if (xCoordDist$ < resCoordDist) { resIndex = index$; resCoordDist = xCoordDist$; resXHitCoord = xHitCoord$; } } } }; var isFlippedX = xCoordinateCalculator.isFlipped; var xVectorView = (0, vectorToArray_1.vectorToArrayViewF64)(xValues, wasmContext); var x1VectorView = x1Values ? (0, vectorToArray_1.vectorToArrayViewF64)(x1Values, wasmContext) : undefined; switch (columnXMode) { case ColumnMode_1.EColumnMode.Mid: for (var i = 0; i < xVectorSize; i++) { var xValue_1 = xVectorView[i]; var xCoord = xCoordinateCalculator.getCoordinate(xValue_1); var left = xCoord - halfColumn; var right = xCoord + halfColumn; updateResValuesFn(left, right, i); } break; case ColumnMode_1.EColumnMode.Start: for (var i = 0; i < xVectorSize; i++) { var xValue_2 = xVectorView[i]; var xCoord = xCoordinateCalculator.getCoordinate(xValue_2); var left = isFlippedX ? xCoord - columnCoordWidth : xCoord; var right = isFlippedX ? xCoord : xCoord + columnCoordWidth; updateResValuesFn(left, right, i); } break; // case EColumnMode.Width: // let xSum = 0; // for (let i = 0; i < xVectorSize; i++) { // const xValue = xVectorView[i]; // const xLeft = xSum; // const xRight = xSum + xValue; // xSum += xValue; // const left = xCoordinateCalculator.getCoordinate(xLeft); // const right = xCoordinateCalculator.getCoordinate(xRight); // isFlippedX ? updateResValuesFn(right, left, i) : updateResValuesFn(left, right, i); // } // break; case ColumnMode_1.EColumnMode.MidWidth: for (var i = 0; i < xVectorSize; i++) { var xValue_3 = xVectorView[i]; var width = x1VectorView[i]; var left = xCoordinateCalculator.getCoordinate(xValue_3 - width / 2); var right = xCoordinateCalculator.getCoordinate(xValue_3 + width / 2); isFlippedX ? updateResValuesFn(right, left, i) : updateResValuesFn(left, right, i); } break; case ColumnMode_1.EColumnMode.StartWidth: for (var i = 0; i < xVectorSize; i++) { var xValue_4 = xVectorView[i]; var width = x1VectorView[i]; var left = xCoordinateCalculator.getCoordinate(xValue_4); var right = xCoordinateCalculator.getCoordinate(xValue_4 + width); isFlippedX ? updateResValuesFn(right, left, i) : updateResValuesFn(left, right, i); } break; case ColumnMode_1.EColumnMode.StartEnd: for (var i = 0; i < xVectorSize; i++) { var leftValue = xVectorView[i]; var rightValue = x1VectorView[i]; var left = xCoordinateCalculator.getCoordinate(leftValue); var right = xCoordinateCalculator.getCoordinate(rightValue); isFlippedX ? updateResValuesFn(right, left, i) : updateResValuesFn(left, right, i); } break; } if (resIndex === -1) return { isHit: false, nearestPointIndex: -1, isWithinDataBounds: false }; var isCategoryAxis = xCoordinateCalculator.isCategoryCoordinateCalculator; var xValue = isCategoryAxis ? resIndex : xValues.get(resIndex); var yValue = yValues.get(resIndex); var x1Value = isCategoryAxis ? resIndex : (_a = x1Values === null || x1Values === void 0 ? void 0 : x1Values.get) === null || _a === void 0 ? void 0 : _a.call(x1Values, resIndex); var y1Value = (_b = y1Values === null || y1Values === void 0 ? void 0 : y1Values.get) === null || _b === void 0 ? void 0 : _b.call(y1Values, resIndex); return { isHit: resCoordDist === 0 && testIsYHit(yValues, y1Values, yCoordinateCalculator, yHitCoord, defaultY1, resIndex, columnYMode), nearestPointIndex: resIndex, isWithinDataBounds: resLeftDataBoundCoord <= resXHitCoord && resXHitCoord <= resRightDataBoundCoord, xValue: xValue, x1Value: x1Value, yValue: yValue, y1Value: y1Value }; } /** * Hit-tests BoxSeries and Polar Column Series */ function hitTestForBox(wasmContext, xCoordinateCalculator, yCoordinateCalculator, xValues, x1Values, yValues, y1Values, xHitCoord, yHitCoord, defaultY1, columnCoordWidth, columnXMode, columnYMode, isVertical, isSorted, isPolar) { if (isVertical) { return hitTestForBoxUnsorted(wasmContext, xCoordinateCalculator, yCoordinateCalculator, xValues, x1Values, yValues, y1Values, xHitCoord, yHitCoord, defaultY1, columnCoordWidth, columnXMode, columnYMode, true, isPolar); } if (isSorted && (columnXMode === ColumnMode_1.EColumnMode.Mid || columnXMode === ColumnMode_1.EColumnMode.Start)) { return hitTestForBoxSorted(wasmContext, xCoordinateCalculator, yCoordinateCalculator, xValues, yValues, y1Values, xHitCoord, yHitCoord, defaultY1, columnCoordWidth, columnXMode, columnYMode, isPolar); } else { return hitTestForBoxUnsorted(wasmContext, xCoordinateCalculator, yCoordinateCalculator, xValues, x1Values, yValues, y1Values, xHitCoord, yHitCoord, defaultY1, columnCoordWidth, columnXMode, columnYMode, false, isPolar); } } exports.hitTestHelpersRectangleSeries = { hitTestForBoxSorted: hitTestForBoxSorted, hitTestForBoxUnsorted: hitTestForBoxUnsorted, hitTestForBox: hitTestForBox };