UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

353 lines (352 loc) 19.2 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.ExtremeResamplerHelper = void 0; var DeletableEntity_1 = require("../../../Core/DeletableEntity"); var Deleter_1 = require("../../../Core/Deleter"); var Guard_1 = require("../../../Core/Guard"); var hash_1 = require("../../../utils/hash"); var ResamplingMode_1 = require("./ResamplingMode"); var ResamplingParams_1 = require("./ResamplingParams"); /** * Helper class for functions which optimise drawing */ var ExtremeResamplerHelper = /** @class */ (function (_super) { __extends(ExtremeResamplerHelper, _super); function ExtremeResamplerHelper(wasmContext) { var _this = _super.call(this) || this; _this.isDeleted = false; _this.nativeMergeIndexParams = new wasmContext.SCRTDoubleResamplerMergeIndicesParams(); _this.wasmContext = wasmContext; _this.nativeResampler = new _this.wasmContext.SCRTDoubleResampler(); _this.xInput = new _this.wasmContext.SCRTXvaluesProvider(); _this.nativeArgs = new _this.wasmContext.ResamplingArgs(); _this.output = new _this.wasmContext.SCRTDoubleArraysXyResampleOutput(); return _this; } /** * Used internally * @param xAxis * @param rs * @param seriesViewRect */ ExtremeResamplerHelper.resampleSeries = function (xAxis, rs, seriesViewRect) { /** * Stacked series and Heatmap do not support resampling * If a series does not support resampling, the pointSeries is not used in the drawing provider. * For example, UniformHeatmapDrawingProvider does not use renderPassData.pointSeries, * but LineSeriesDrawingProvider use renderPassData.pointSeries in the draw() method! */ if (!rs.supportsResampling) return { pointSeries: rs.toPointSeries(), renderableSeries: rs, indicesRange: rs.isStacked ? undefined : rs.getIndicesRange(xAxis.visibleRange, xAxis.isCategoryAxis), resamplingHash: undefined }; var rp = rs.getResamplingParams(); var prevRPD = rs.getCurrentRenderPassData(); if (!rp || (rp.resampleRequired && !prevRPD)) { // in tests, renderPassData is not set back on the series. rp = new ResamplingParams_1.ResamplingParams(seriesViewRect, rs, xAxis); if (!rs.needsResampling(rp)) return { pointSeries: rs.toPointSeries(), renderableSeries: rs, indicesRange: rp.indexesRange, resamplingHash: undefined }; var resamplingHash = ExtremeResamplerHelper.calculateResamplingHash(rs, rp); var prevRPD_1 = rs.getCurrentRenderPassData(); var useFromCache = Boolean(prevRPD_1 && prevRPD_1.resamplingHash === resamplingHash); // console.log("resampling ..."); // console.log("useFromCache", useFromCache); var pointSeries = useFromCache ? prevRPD_1.pointSeries : rs.toPointSeries(rp); return { pointSeries: pointSeries, renderableSeries: rs, indicesRange: rp.indexesRange, resamplingHash: resamplingHash }; } else if (rp.resampleRequired) { return { pointSeries: prevRPD.pointSeries, renderableSeries: rs, indicesRange: rp.indexesRange, resamplingHash: rp.hash }; } else { return { pointSeries: rs.toPointSeries(), renderableSeries: rs, indicesRange: rp.indexesRange, resamplingHash: undefined }; } }; ExtremeResamplerHelper.calculateResamplingHash = function (rs, rp) { var hashes = []; var dataSeries = rs.dataSeries; if (dataSeries) { var dataSeriesHash = hash_1.hashUtils.generateHash(dataSeries.id); hashes.push(dataSeriesHash); var dataSeriesCountHash = hash_1.hashUtils.generateNumberHash(dataSeries.count()); hashes.push(dataSeriesCountHash); var dataSeriesSortedHash = hash_1.hashUtils.generateBooleanHash(dataSeries.dataDistributionCalculator.isSortedAscending); hashes.push(dataSeriesSortedHash); var dataSeriesChangeCountHash = hash_1.hashUtils.generateNumberHash(dataSeries.changeCount); hashes.push(dataSeriesChangeCountHash); } var resamplingParamsHash = hash_1.hashUtils.generateObjectHash(rp); hashes.push(resamplingParamsHash); rp.hash = hash_1.hashUtils.generateCombinedHash(hashes); return rp.hash; }; /** * Calls native RequiresReduction method to calculate if resampling is needed * @param rp The resampling params * @param xOriginalValues XValues * @param fillBasicNativeArgs Update nativeArgs if True * @param updateResamplingMode Update {@link ResamplingArgs.Resampling} property if True */ ExtremeResamplerHelper.prototype.needsResampling = function (rp, xOriginalValues, fillBasicNativeArgs, updateResamplingMode) { if (fillBasicNativeArgs === void 0) { fillBasicNativeArgs = true; } if (updateResamplingMode === void 0) { updateResamplingMode = false; } if (fillBasicNativeArgs) this.resetAndFillBasicNativeArgs(rp, xOriginalValues); var requiresReduction = this.nativeResampler.RequiresReduction(this.nativeArgs); var needsResampling = rp.dataIsFifo || requiresReduction; if ((updateResamplingMode && !needsResampling) || (needsResampling && !requiresReduction)) { this.nativeArgs.Resampling = this.getNativeResamplingMode(ResamplingMode_1.EResamplingMode.None); } return needsResampling; }; /** * This method calls does resampling by calling the native resampling methods. * It does similar things as WPF AvxExtremeResamplerDoubleDouble.ResampleInternal() method * The needsResampling() method must be called before, this is done in {@link SciChartRenderer.resampleSeries} * @param wasmContext The WebAssembly context * @param rp The resampling parameters * @param xOriginalValues The original not resampled X values * @param yOriginalValues The original not resampled Y values * @param indexesOut The indices output * @param xResampledValuesOut The resampled X values output * @param yResampledValuesOut The resampled Y values output * @param fillBasicNativeArgs If set to True resets and fill nativeArgs with basic properties, * you can set it to False if {@link needsResampling()} was called before this method * @returns indicesVector The resampled vector of indices */ ExtremeResamplerHelper.prototype.resampleIntoPointSeries = function (wasmContext, rp, xOriginalValues, yOriginalValues, indexesOut, indexesResampledOut, xResampledValuesOut, yResampledValuesOut, fillBasicNativeArgs) { if (fillBasicNativeArgs === void 0) { fillBasicNativeArgs = true; } if (this.isDeleted) { throw new Error("should not call resampleIntoPointSeries() if deleted"); } Guard_1.Guard.notNull(xOriginalValues, "xDataValues"); Guard_1.Guard.notNull(yOriginalValues, "yDataValues"); Guard_1.Guard.notNull(xOriginalValues, "xOriginalValues"); Guard_1.Guard.notNull(yOriginalValues, "yOriginalValues"); Guard_1.Guard.notNull(rp, "resamplingParams"); if (fillBasicNativeArgs) this.resetAndFillBasicNativeArgs(rp, xOriginalValues); // Set X Values this.xInput.SetInput(xOriginalValues); this.nativeArgs.ResamplingPrecision = rp.precision; this.nativeArgs.ZeroLineY = rp.zeroLineY; this.nativeArgs.NewDataPointCount = -1; if (fillBasicNativeArgs === true) { this.needsResampling(rp, xOriginalValues, false, true); } //this.debugParameters(rp, this.nativeArgs); // What does this method do??? var requestedSize = this.nativeResampler.UpdateIndices(indexesOut, this.xInput, yOriginalValues, this.nativeArgs.Resampling, this.nativeArgs); // SC-5145 Adds +1 to be sure that reserved Capacity is not less than the actual resampled count, // otherwise resampledXValues and resampledYValues will be recreated with default 0.0 values if (indexesResampledOut) { indexesResampledOut.resizeFast(requestedSize + 1); } xResampledValuesOut.resizeFast(requestedSize + 1); yResampledValuesOut.resizeFast(requestedSize + 1); if (indexesResampledOut) { this.output.ResetWithIndices(indexesResampledOut, xResampledValuesOut, yResampledValuesOut); } else { this.output.Reset(xResampledValuesOut, yResampledValuesOut); } // Execute resampling and update indexesOut vector this.nativeResampler.Execute(this.xInput, yOriginalValues, this.output, indexesOut, this.nativeArgs.Resampling, this.nativeArgs); var resultCount = indexesOut.size(); //console.log("indexes from rs",resultCount, indexesOut.get(resultCount - 2), indexesOut.get(resultCount - 1)); if (indexesResampledOut) { indexesResampledOut.resizeFast(resultCount); } xResampledValuesOut.resizeFast(resultCount); yResampledValuesOut.resizeFast(resultCount); return { OutputSplitIndex: this.output.OutputSplitIndex || this.nativeArgs.OutputSplitIndex }; }; ExtremeResamplerHelper.prototype.mergeIndexes = function (indices, size1, size2, mergedIndicesOut) { return this.nativeResampler.MergeIndices(indices, size1, size2, mergedIndicesOut); }; ExtremeResamplerHelper.prototype.copyValuesByIndexes = function (indices, xValues, yValues, y1Values, count, isCategoryAxis, isFifoSweeping, indicesOut, xValuesOut, yValuesOut, y1ValuesOut, y1Offset) { if (y1Offset === void 0) { y1Offset = 0; } var mp = this.nativeMergeIndexParams; mp.SetIndices(indices); mp.SetXInput(xValues); mp.SetYInput(yValues); mp.SetY1Input(y1Values); mp.SetY1Offset(y1Offset); mp.count = count; mp.isCategoryData = isCategoryAxis; mp.isFifoSweeping = isFifoSweeping; mp.SetIndicesOut(indicesOut); mp.SetXOut(xValuesOut); mp.SetYOut(yValuesOut); mp.SetY1Out(y1ValuesOut); this.nativeResampler.CopyValuesByIndices(mp); }; /** @inheritDoc */ ExtremeResamplerHelper.prototype.delete = function () { if (!this.isDeleted) { (0, Deleter_1.deleteSafe)(this.nativeResampler); (0, Deleter_1.deleteSafe)(this.xInput); (0, Deleter_1.deleteSafe)(this.nativeArgs); (0, Deleter_1.deleteSafe)(this.output); (0, Deleter_1.deleteSafe)(this.nativeMergeIndexParams); this.isDeleted = true; this.wasmContext = undefined; } }; ExtremeResamplerHelper.prototype.getNativeResamplingMode = function (resamplingMode) { switch (resamplingMode) { case ResamplingMode_1.EResamplingMode.Auto: return this.wasmContext.ResamplingMode.Auto; case ResamplingMode_1.EResamplingMode.Max: return this.wasmContext.ResamplingMode.Max; case ResamplingMode_1.EResamplingMode.Mid: return this.wasmContext.ResamplingMode.Mid; case ResamplingMode_1.EResamplingMode.Min: return this.wasmContext.ResamplingMode.Min; case ResamplingMode_1.EResamplingMode.MinMax: return this.wasmContext.ResamplingMode.MinMax; case ResamplingMode_1.EResamplingMode.MinOrMax: return this.wasmContext.ResamplingMode.MinOrMax; case ResamplingMode_1.EResamplingMode.None: return this.wasmContext.ResamplingMode.None; default: throw new Error("Unknown resamplingMode ".concat(resamplingMode)); } }; /** * Fills basic native args needed for {@link needsResampling()} and {@link resampleIntoPointSeries} methods */ ExtremeResamplerHelper.prototype.resetAndFillBasicNativeArgs = function (rp, xOriginalValues) { this.nativeArgs.Reset(); this.nativeArgs.Data = this.getDataDistribution(rp.dataEvenlySpaced, rp.isCategoryAxis); this.nativeArgs.StartIndex = rp.indexesRange.min; this.nativeArgs.EndIndex = rp.indexesRange.max; this.nativeArgs.MaxXInclusive = rp.xVisibleRange.max; this.nativeArgs.MinXInclusive = rp.xVisibleRange.min; this.nativeArgs.Resampling = this.getNativeResamplingMode(rp.resamplingMode); this.nativeArgs.ViewportWidth = rp.viewportSize; this.nativeArgs.FifoCapacity = rp.fifoCapacity || 0; this.nativeArgs.HasNaN = rp.dataHasNaN; this.nativeArgs.IsFifo = rp.dataIsFifo; this.nativeArgs.InputBaseIndex = rp.fifoStartIndex || 0; if (rp.isCategoryAxis) { this.nativeArgs.MinXInclusive = rp.indexesRange.min; this.nativeArgs.MaxXInclusive = rp.indexesRange.max; } else if (rp.fifoCapacity && !rp.dataIsFifo) { // Sweeping on numeric axis, which requires x values to be sorted wrt the raw data, eg x % fifoCapactiy var firstPoint = xOriginalValues.getRaw(rp.indexesRange.min); var lastPoint = xOriginalValues.getRaw(rp.indexesRange.max); this.nativeArgs.MinXInclusive = Math.max(firstPoint, rp.xVisibleRange.min); this.nativeArgs.MaxXInclusive = Math.min(lastPoint, rp.xVisibleRange.max); } else { var firstPoint = xOriginalValues.get(rp.indexesRange.min); var lastPoint = xOriginalValues.get(rp.indexesRange.max); this.nativeArgs.MinXInclusive = Math.max(firstPoint, rp.xVisibleRange.min); this.nativeArgs.MaxXInclusive = Math.min(lastPoint, rp.xVisibleRange.max); } }; ExtremeResamplerHelper.prototype.debugParameters = function (rp, nativeArgs) { console.log(31415); console.log("ResamplingParams:"); console.log(".. zeroLineY: ".concat(rp.zeroLineY)); console.log(".. resamplingPrecision: ".concat(rp.precision)); console.log(".. xVisibleRange: ".concat(rp.xVisibleRange)); console.log(".. indicesRange: ".concat(rp.indexesRange)); console.log(".. viewportSize: ".concat(rp.viewportSize)); console.log(".. isCategoryAxis: ".concat(rp.isCategoryAxis)); console.log(".. isXAxisAutoRanged: ".concat(rp.isXAxisAutoRanged)); console.log(".. resamplingMode: ".concat(rp.resamplingMode)); //console.log(`.. renderableSeriesHash: ${rp.renderableSeriesHash}`); console.log(".. enableExperimentalResampling: ".concat(rp.enableExperimentalResampling)); console.log(".. dataHasNan: ".concat(rp.dataHasNaN)); console.log(".. dataIsFifo: ".concat(rp.dataIsFifo)); console.log(".. fifoCapacity: ".concat(rp.fifoCapacity)); console.log(".. dataEvenlySpaced: ".concat(rp.dataEvenlySpaced)); console.log("native Resampling Args:"); console.log(".. ResamplingData: ".concat(this.debugResamplingDataEnum(nativeArgs.Data))); console.log(".. StartIndex: ".concat(nativeArgs.StartIndex)); console.log(".. EndIndex: ".concat(nativeArgs.EndIndex)); console.log(".. FifoCapacity: ".concat(nativeArgs.FifoCapacity)); console.log(".. HasNaN: ".concat(nativeArgs.HasNaN)); console.log(".. IsFifo: ".concat(nativeArgs.IsFifo)); console.log(".. MaxXInclusive: ".concat(nativeArgs.MaxXInclusive)); console.log(".. MinXInclusive: ".concat(nativeArgs.MinXInclusive)); console.log(".. ResamplingMode: ".concat(this.debugResamplingModeEnum(nativeArgs.Resampling))); console.log(".. ResamplingPrecision: ".concat(nativeArgs.ResamplingPrecision)); console.log(".. ViewportWidth: ".concat(nativeArgs.ViewportWidth)); console.log(".. ZeroLineY: ".concat(nativeArgs.ZeroLineY)); console.log(".. NewDataPointCount: ".concat(nativeArgs.NewDataPointCount)); console.log(".. InputBaseIndex: ".concat(nativeArgs.InputBaseIndex)); }; ExtremeResamplerHelper.prototype.debugRect = function (rect) { return "X ".concat(rect.x, " Y ").concat(rect.y, " Width ").concat(rect.width, " Height ").concat(rect.height); }; ExtremeResamplerHelper.prototype.debugResamplingDataEnum = function (resamplingData) { return resamplingData === this.wasmContext.ResamplingData.LinearData ? "LinearData" : resamplingData === this.wasmContext.ResamplingData.CategoryData ? "CategoryData" : resamplingData === this.wasmContext.ResamplingData.UnsortedData ? "UnsortedData" : resamplingData === this.wasmContext.ResamplingData.UnevenlySpacedData ? "UnevenlySpacedData" : "Unknown"; }; ExtremeResamplerHelper.prototype.debugResamplingModeEnum = function (resamplingMode) { return resamplingMode === this.wasmContext.ResamplingMode.MinMax ? "MinMax" : resamplingMode === this.wasmContext.ResamplingMode.Auto ? "Auto" : "Unknown"; }; ExtremeResamplerHelper.prototype.getDataDistribution = function (dataEvenlySpaced, isCategoryAxis) { if (isCategoryAxis) { return this.wasmContext.ResamplingData.CategoryData; } return dataEvenlySpaced ? this.wasmContext.ResamplingData.LinearData : this.wasmContext.ResamplingData.UnevenlySpacedData; }; return ExtremeResamplerHelper; }(DeletableEntity_1.DeletableEntity)); exports.ExtremeResamplerHelper = ExtremeResamplerHelper;