scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
285 lines (284 loc) • 14.1 kB
JavaScript
"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
};