UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

310 lines (309 loc) 16.7 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.StackedXyCollection = void 0; var NumberRange_1 = require("../../../Core/NumberRange"); var SearchMode_1 = require("../../../types/SearchMode"); var copyVector_1 = require("../../../utils/copyVector"); var performance_1 = require("../../../utils/performance"); var vectorToArray_1 = require("../../../utils/vectorToArray"); var BaseDataSeries_1 = require("../../Model/BaseDataSeries"); var XyyPointSeriesWrapped_1 = require("../../Model/PointSeries/XyyPointSeriesWrapped"); var RenderPassData_1 = require("../../Services/RenderPassData"); var BaseStackedCollection_1 = require("./BaseStackedCollection"); var constants_1 = require("./constants"); var StackedXyCollection = /** @class */ (function (_super) { __extends(StackedXyCollection, _super); /** * Creates an instance of the {@link StackedMountainCollection} * @param webAssemblyContext The {@link TSciChart | SciChart WebAssembly Context} containing * native methods and access to our WebGL2 WebAssembly Drawing Engine * @param options Optional parameters of type {@link IStackedXyCollectionOptions} to configure the series */ function StackedXyCollection(webAssemblyContext, options) { var _this = this; var _a; _this = _super.call(this, webAssemblyContext, options) || this; _this.separatePositiveNegativeStacksProperty = true; _this.separatePositiveNegativeStacksProperty = (_a = options === null || options === void 0 ? void 0 : options.separatePositiveNegativeStacks) !== null && _a !== void 0 ? _a : _this.separatePositiveNegativeStacksProperty; _this.detachChildSeries = _this.detachChildSeries.bind(_this); _this.attachChildSeries = _this.attachChildSeries.bind(_this); _this.collectionChanged.subscribe(function (arg) { var _a, _b; (_a = arg.getOldItems()) === null || _a === void 0 ? void 0 : _a.forEach(_this.detachChildSeries); (_b = arg.getNewItems()) === null || _b === void 0 ? void 0 : _b.forEach(_this.attachChildSeries); }); return _this; } /** @inheritDoc */ StackedXyCollection.prototype.updateAccumulatedVectors = function () { var _this = this; var dataValuesCount = this.getDataSeriesValuesCount(); if (!this.isAccumulatedVectorDirty || !dataValuesCount) { return; } this.checkXValuesCorrect(); this.isAccumulatedVectorDirty = false; this.clearAccumulatedVectors(dataValuesCount); var yValueArrayViews = this.getVisibleSeries().map(function (cur) { return (0, vectorToArray_1.vectorToArrayViewF64)(cur.dataSeries.getNativeYValues(), _this.webAssemblyContext); }); var _loop_1 = function (i) { this_1.accumulatedValues0.push_back(0); if (this_1.separatePositiveNegativeStacksProperty) { // Compute separate positive/negative totals for 100% normalization. var positiveTotal_1 = 0; var negativeTotal_1 = 0; if (this_1.isOneHundredPercent) { this_1.getVisibleSeries().forEach(function (rs, index) { var y = yValueArrayViews[index][i]; if (y >= 0) positiveTotal_1 += y; else negativeTotal_1 += y; }); } // Positive values stack upward from zero; negative values stack downward independently. var positiveAccum_1 = 0; var negativeAccum_1 = 0; this_1.getVisibleSeries().forEach(function (rs, index) { var currentY = yValueArrayViews[index][i]; if (_this.isOneHundredPercent) { currentY = currentY >= 0 ? (positiveTotal_1 !== 0 ? (currentY / positiveTotal_1) * 100 : 0) : (negativeTotal_1 !== 0 ? (currentY / Math.abs(negativeTotal_1)) * 100 : 0); } if (currentY >= 0) { rs.bottomAccumulatedValues.push_back(positiveAccum_1); var top_1 = positiveAccum_1 + currentY; rs.accumulatedValues.push_back(top_1); positiveAccum_1 = top_1; } else { var bottom = negativeAccum_1 + currentY; rs.bottomAccumulatedValues.push_back(bottom); rs.accumulatedValues.push_back(negativeAccum_1); negativeAccum_1 = bottom; } if (rs.renderDataTransform) { rs.renderDataTransform.requiresTransform = true; } }); } else { var totalSum_1; if (this_1.isOneHundredPercent) { totalSum_1 = this_1.getVisibleSeries().reduce(function (prev, cur, index) { return prev + yValueArrayViews[index][i]; }, 0); } var previous_1 = 0; this_1.getVisibleSeries().forEach(function (rs, index) { var currentY = yValueArrayViews[index][i]; if (_this.isOneHundredPercent) { currentY = (currentY * 100) / totalSum_1; } var current = previous_1 + currentY; rs.accumulatedValues.push_back(current); previous_1 = current; if (rs.renderDataTransform) { rs.renderDataTransform.requiresTransform = true; } }); } }; var this_1 = this; for (var i = 0; i < dataValuesCount; i++) { _loop_1(i); } }; /** @inheritDoc */ StackedXyCollection.prototype.draw = function (renderContext, renderPassData) { var _this = this; var _a, _b, _c, _d; if (this.canDraw) { this.updateHitTestProviders(renderPassData); if (!this.isEnoughDataToDraw()) { return; } if ((_a = this.getFirstSeries().dataSeries) === null || _a === void 0 ? void 0 : _a.fifoCapacity) { throw new Error("Sorry, fifo is not currently supported for stacked series"); } var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawCollectionSeriesStart, { contextId: this.id, parentContextId: (_b = this.parentSurface) === null || _b === void 0 ? void 0 : _b.id, level: performance_1.EPerformanceDebugLevel.Verbose }); this.updateAccumulatedVectors(); var xAxis_1 = this.xAxis; var visibleSeries_1 = this.getVisibleSeries(); // draw Stacked Series in reverse order to prevent overlapping with Point Markers visibleSeries_1.reduceRight(function (nextSeries, series, index, collection) { var accumulatedValues1 = series.accumulatedValues; var accumulatedValues = _this.separatePositiveNegativeStacksProperty ? series.bottomAccumulatedValues : index === 0 ? _this.accumulatedValues0 : collection[index - 1].accumulatedValues; // wrap XyDataSeries as XyyDataSeries var xyyPointSeries = new XyyPointSeriesWrapped_1.XyyPointSeriesWrapped(series.dataSeries, accumulatedValues, accumulatedValues1); var renderData = new RenderPassData_1.RenderPassData(series.getIndicesRange(xAxis_1.visibleRange), renderPassData.getxCoordinateCalculator, renderPassData.getyCoordinateCalculator, xAxis_1.isVerticalChart, xyyPointSeries); if (series.renderDataTransform) { var transRenderData = new RenderPassData_1.RenderPassData(series.getIndicesRange(xAxis_1.visibleRange), renderPassData.getxCoordinateCalculator, renderPassData.getyCoordinateCalculator, xAxis_1.isVerticalChart, xyyPointSeries); transRenderData = series.renderDataTransform.runTransform(transRenderData); if (index < visibleSeries_1.length - 1) { (0, copyVector_1.copyDoubleVector)(collection[index + 1].renderDataTransform.pointSeries.yValues, transRenderData.pointSeries.y1Values, _this.webAssemblyContext); } if ("strokeY1" in series) { // @ts-ignore series.strokeY1 = index === 0 ? "transparent" : collection[index - 1].stroke; // @ts-ignore series.strokeY1DashArray = index === 0 ? [] : collection[index - 1].strokeDashArray; } series.drawingProviders[0].draw(renderContext, transRenderData); return series; } if ("strokeY1" in series) { // @ts-ignore series.strokeY1 = index === 0 ? "transparent" : collection[index - 1].stroke; // @ts-ignore series.strokeY1DashArray = index === 0 ? [] : collection[index - 1].strokeDashArray; } series.draw(renderContext, renderData); return series; }, undefined); performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawCollectionSeriesEnd, { contextId: this.id, parentContextId: (_c = this.parentSurface) === null || _c === void 0 ? void 0 : _c.id, relatedId: (_d = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _d === void 0 ? void 0 : _d.relatedId, level: performance_1.EPerformanceDebugLevel.Verbose }); } }; /** @inheritDoc */ StackedXyCollection.prototype.getXRange = function () { if (!this.isEnoughDataToDraw()) { return new NumberRange_1.NumberRange(); } return this.getFirstSeries().dataSeries.xRange; }; /** @inheritDoc */ StackedXyCollection.prototype.getYRange = function (xVisibleRange, isXCategoryAxis) { var _this = this; var yRange = _super.prototype.getYRange.call(this, xVisibleRange, isXCategoryAxis); if (this.separatePositiveNegativeStacksProperty) { // accumulatedValues only contains the tops; also union with bottomAccumulatedValues // so that negatively-stacked bands are included in the visible range. this.getVisibleSeries().forEach(function (rs) { var _a; var bottomSize = rs.bottomAccumulatedValues.size(); if (bottomSize > 0 && bottomSize === ((_a = _this.getNativeXValues()) === null || _a === void 0 ? void 0 : _a.size())) { var bottomRange = (0, BaseDataSeries_1.getWindowedYRange)(_this.webAssemblyContext, _this.getNativeXValues(), rs.bottomAccumulatedValues, xVisibleRange, true, isXCategoryAxis, rs.dataSeries.dataDistributionCalculator.isSortedAscending, true, SearchMode_1.ESearchMode.RoundUp, SearchMode_1.ESearchMode.RoundDown); if (bottomRange) { yRange = yRange.union(bottomRange); } } }); } return yRange; }; /** @inheritDoc */ StackedXyCollection.prototype.onAttach = function (scs) { _super.prototype.onAttach.call(this, scs); this.getVisibleSeries().forEach(function (series) { series.onAttach(scs); }); }; /** @inheritDoc */ StackedXyCollection.prototype.onDetach = function () { this.getVisibleSeries().forEach(function (series) { series.onDetach(); }); _super.prototype.onDetach.call(this); }; /** @inheritDoc */ StackedXyCollection.prototype.notifyPropertyChanged = function (propertyName) { _super.prototype.notifyPropertyChanged.call(this, propertyName); if (propertyName === constants_1.PROPERTY.DATA_SERIES || propertyName === constants_1.PROPERTY.IS_VISIBLE || propertyName === constants_1.PROPERTY.IS_ONE_HUNDRED_PERCENT || propertyName === constants_1.PROPERTY.SEPARATE_POSITIVE_NEGATIVE_STACKS) { this.isAccumulatedVectorDirty = true; } }; Object.defineProperty(StackedXyCollection.prototype, "separatePositiveNegativeStacks", { /** * When true (default), positive values stack upward from the zero line and negative values stack downward independently. * When false, all values accumulate continuously from the previous series top, preserving legacy behaviour. */ get: function () { return this.separatePositiveNegativeStacksProperty; }, /** * When true (default), positive values stack upward from the zero line and negative values stack downward independently. * When false, all values accumulate continuously from the previous series top, preserving legacy behaviour. */ set: function (value) { this.separatePositiveNegativeStacksProperty = value; this.notifyPropertyChanged(constants_1.PROPERTY.SEPARATE_POSITIVE_NEGATIVE_STACKS); }, enumerable: false, configurable: true }); /** @inheritDoc */ StackedXyCollection.prototype.hasDataSeriesValues = function () { return this.isEnoughDataToDraw(); }; // PROTECTED // PRIVATE StackedXyCollection.prototype.detachChildSeries = function (series) { series.onDetachFromParentCollection(); this.isAccumulatedVectorDirty = true; this.invalidateParent(); }; StackedXyCollection.prototype.attachChildSeries = function (series) { series.onAttachToParentCollection(this, this.getParentSurface, this.notifyPropertyChanged); if (this.parentSurface) { series.onAttach(this.parentSurface); } this.isAccumulatedVectorDirty = true; this.invalidateParent(); }; StackedXyCollection.prototype.checkXValuesCorrect = function () { var length = this.getDataSeriesValuesCount(); this.getVisibleSeries().forEach(function (el) { if (!(el.dataSeries.count() === length)) { throw Error("All stacked series in on collection should have the same amount of X Values"); } }); }; /** * @param numberOfElements - number of element expected is used for performance to reserve memory */ StackedXyCollection.prototype.clearAccumulatedVectors = function (numberOfElements) { this.accumulatedValues0.clear(); this.accumulatedValues0.reserve(numberOfElements); this.asArray().forEach(function (el) { el.accumulatedValues.clear(); el.accumulatedValues.reserve(numberOfElements); el.bottomAccumulatedValues.clear(); el.bottomAccumulatedValues.reserve(numberOfElements); }); }; StackedXyCollection.prototype.getLastVisibleSeries = function () { var lastItem = this.getVisibleSeries().slice(-1)[0]; return lastItem; }; return StackedXyCollection; }(BaseStackedCollection_1.BaseStackedCollection)); exports.StackedXyCollection = StackedXyCollection;