UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

331 lines (330 loc) 23.4 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.BoxPlotSeriesDrawingProvider = void 0; var Deleter_1 = require("../../../../Core/Deleter"); var ColumnMode_1 = require("../../../../types/ColumnMode"); var vectorToArray_1 = require("../../../../utils/vectorToArray"); var BrushCache_1 = require("../../../Drawing/BrushCache"); var Pen2DCache_1 = require("../../../Drawing/Pen2DCache"); var SciChartSurfaceBase_1 = require("../../SciChartSurfaceBase"); var constants_1 = require("../constants"); var BaseSeriesDrawingProvider_1 = require("./BaseSeriesDrawingProvider"); /** * Used internally - a drawing provider performs drawing for a {@link FastBoxPlotRenderableSeries} using * our WebAssembly WebGL rendering engine */ var BoxPlotSeriesDrawingProvider = /** @class */ (function (_super) { __extends(BoxPlotSeriesDrawingProvider, _super); /** * Creates an instance of the {@link BoxPlotSeriesDrawingProvider} * @param webAssemblyContext The {@link TSciChart | SciChart 2D WebAssembly Context} containing native methods and * access to our WebGL2 Engine and WebAssembly numerical methods * @param parentSeries the parent {@link FastBoxPlotRenderableSeries} which this drawing provider is attached to */ function BoxPlotSeriesDrawingProvider(webAssemblyContext, parentSeries, ySelector, xSelector) { return _super.call(this, webAssemblyContext, parentSeries, ySelector, xSelector) || this; } /** @inheritDoc */ BoxPlotSeriesDrawingProvider.prototype.onAttachSeries = function () { _super.prototype.onAttachSeries.call(this); this.capPenCache = new Pen2DCache_1.Pen2DCache(this.webAssemblyContext); this.whiskersPenCache = new Pen2DCache_1.Pen2DCache(this.webAssemblyContext); this.medianLinePenCache = new Pen2DCache_1.Pen2DCache(this.webAssemblyContext); this.boxPenCache = new Pen2DCache_1.Pen2DCache(this.webAssemblyContext); this.boxFillBrushCache = new BrushCache_1.BrushCache(this.webAssemblyContext); this.nativeBoxDrawingProvider = new this.webAssemblyContext.SCRTRectangleSeriesDrawingProvider(); this.boxArgs = new this.webAssemblyContext.SCRTRectangleDrawingParams(); this.nativeLineDrawingProvider = new this.webAssemblyContext.SCRTLineSegmentDrawingProvider(); this.lineArgs = new this.webAssemblyContext.SCRTLineDrawingParams(); this.tempXVec = new this.webAssemblyContext.SCRTDoubleVector(); this.tempYVec = new this.webAssemblyContext.SCRTDoubleVector(); var _a = this.getProperties(), capStroke = _a.capStroke, capStrokeDashArray = _a.capStrokeDashArray, capStrokeThickness = _a.capStrokeThickness, whiskersStroke = _a.whiskersStroke, whiskersStrokeDashArray = _a.whiskersStrokeDashArray, whiskersStrokeThickness = _a.whiskersStrokeThickness, medianStroke = _a.medianStroke, medianStrokeDashArray = _a.medianStrokeDashArray, medianStrokeThickness = _a.medianStrokeThickness, boxStroke = _a.boxStroke, boxStrokeThickness = _a.boxStrokeThickness, boxStrokeDashArray = _a.boxStrokeDashArray, opacity = _a.opacity; (0, Pen2DCache_1.createPenInCache)(this.capPenCache, capStroke, capStrokeThickness, opacity, capStrokeDashArray, false); (0, Pen2DCache_1.createPenInCache)(this.whiskersPenCache, whiskersStroke, whiskersStrokeThickness, opacity, whiskersStrokeDashArray, false); (0, Pen2DCache_1.createPenInCache)(this.medianLinePenCache, medianStroke, medianStrokeThickness, opacity, medianStrokeDashArray, false); (0, Pen2DCache_1.createPenInCache)(this.boxPenCache, boxStroke, boxStrokeThickness, opacity, boxStrokeDashArray, false); this.createBoxBrush(); }; /** @inheritDoc */ BoxPlotSeriesDrawingProvider.prototype.onDetachSeries = function () { _super.prototype.onDetachSeries.call(this); this.delete(); }; BoxPlotSeriesDrawingProvider.prototype.getProperties = function () { var _a = this.parentSeries, dataPointWidthMode = _a.dataPointWidthMode, _b = _a.cap, capDataPointWidth = _b.dataPointWidth, capStroke = _b.stroke, capStrokeDashArray = _b.strokeDashArray, capStrokeThickness = _b.strokeThickness, _c = _a.whiskers, whiskersStroke = _c.stroke, whiskersStrokeDashArray = _c.strokeDashArray, whiskersStrokeThickness = _c.strokeThickness, _d = _a.medianLine, medianStroke = _d.stroke, medianStrokeDashArray = _d.strokeDashArray, medianStrokeThickness = _d.strokeThickness, boxDataPointWidth = _a.dataPointWidth, boxStroke = _a.stroke, boxStrokeThickness = _a.strokeThickness, boxStrokeDashArray = _a.strokeDashArray, boxFill = _a.fill, boxFillLinearGradient = _a.fillLinearGradient, opacity = _a.opacity; return { dataPointWidthMode: dataPointWidthMode, capDataPointWidth: capDataPointWidth, capStroke: capStroke, capStrokeDashArray: capStrokeDashArray, capStrokeThickness: capStrokeThickness, whiskersStroke: whiskersStroke, whiskersStrokeDashArray: whiskersStrokeDashArray, whiskersStrokeThickness: whiskersStrokeThickness, medianStroke: medianStroke, medianStrokeDashArray: medianStrokeDashArray, medianStrokeThickness: medianStrokeThickness, boxDataPointWidth: boxDataPointWidth, boxStroke: boxStroke, boxStrokeThickness: boxStrokeThickness, boxStrokeDashArray: boxStrokeDashArray, boxFill: boxFill, boxFillLinearGradient: boxFillLinearGradient, opacity: opacity !== null && opacity !== void 0 ? opacity : 1 }; }; /** @inheritDoc */ BoxPlotSeriesDrawingProvider.prototype.delete = function () { this.capPenCache = (0, Deleter_1.deleteSafe)(this.capPenCache); this.whiskersPenCache = (0, Deleter_1.deleteSafe)(this.whiskersPenCache); this.medianLinePenCache = (0, Deleter_1.deleteSafe)(this.medianLinePenCache); this.boxPenCache = (0, Deleter_1.deleteSafe)(this.boxPenCache); this.boxFillBrushCache = (0, Deleter_1.deleteSafe)(this.boxFillBrushCache); this.nativeBoxDrawingProvider = (0, Deleter_1.deleteSafe)(this.nativeBoxDrawingProvider); this.boxArgs = (0, Deleter_1.deleteSafe)(this.boxArgs); this.nativeLineDrawingProvider = (0, Deleter_1.deleteSafe)(this.nativeLineDrawingProvider); this.lineArgs = (0, Deleter_1.deleteSafe)(this.lineArgs); this.tempXVec = (0, Deleter_1.deleteSafe)(this.tempXVec); this.tempYVec = (0, Deleter_1.deleteSafe)(this.tempYVec); _super.prototype.delete.call(this); }; BoxPlotSeriesDrawingProvider.prototype.drawBoxes = function (renderContext, renderPassData) { var pointSeries = renderPassData.pointSeries; var viewRect = this.parentSeries.parentSurface.seriesViewRect; var _a = this.getProperties(), boxStroke = _a.boxStroke, boxFill = _a.boxFill, opacity = _a.opacity, boxFillLinearGradient = _a.boxFillLinearGradient; this.boxArgs.Reset(); this.boxArgs.verticalChart = renderPassData.isVerticalChart; this.boxArgs.columnWidth = this.parentSeries.getDataPointWidth(renderPassData.xCoordinateCalculator, this.parentSeries.dataPointWidth, this.parentSeries.dataPointWidthMode); this.boxArgs.xMode = (0, ColumnMode_1.convertColumnMode)(ColumnMode_1.EColumnMode.Mid, this.webAssemblyContext); this.boxArgs.yMode = (0, ColumnMode_1.convertYColumnMode)(ColumnMode_1.EColumnYMode.TopBottom, this.webAssemblyContext); var linesPen = (0, Pen2DCache_1.getScrtPenFromCache)(this.boxPenCache); if (linesPen) { this.boxArgs.SetLinesPen(linesPen); } var fillBrush = (0, BrushCache_1.getScrtBrushFromCache)(this.boxFillBrushCache); if (fillBrush) { this.boxArgs.SetFillBrush(fillBrush); } this.boxArgs.viewportWidth = viewRect.width; this.boxArgs.viewportHeight = viewRect.height; // Paletting per point _super.prototype.applyStrokeFillPaletting.call(this, boxStroke, linesPen, boxFill, fillBrush, opacity, false, boxFillLinearGradient !== undefined); this.boxArgs.SetPalettedColors(this.palettingState.palettedColors); this.boxArgs.paletteStart = this.palettingState.paletteStartIndex; var isCategoryAxis = renderPassData.xCoordinateCalculator.isCategoryCoordinateCalculator; var xValues = pointSeries.xValues; var yTop = pointSeries.upperQuartileValues; var yBottom = pointSeries.lowerQuartileValues; var xDrawValues = isCategoryAxis ? pointSeries.indexes : xValues; var _b = this.getStartAndCount(renderPassData, xDrawValues), startIndex = _b.startIndex, count = _b.count; this.boxArgs.count = count; this.boxArgs.startIndex = startIndex; this.boxArgs.SetXValues(xDrawValues); this.boxArgs.SetYValues(yTop); this.boxArgs.SetWValues(yBottom); var _c = this.parentSeries.dataSeries, fifoCapacity = _c.fifoCapacity, fifoSweeping = _c.fifoSweeping, fifoSweepingGap = _c.fifoSweepingGap; var fifoStartIndex = pointSeries.fifoStartIndex; if (fifoSweeping && fifoCapacity === this.parentSeries.dataSeries.count()) { this.boxArgs.count = fifoStartIndex; } var nativeContext = renderContext.getNativeContext(); this.boxArgs.SetNativeContext(nativeContext); this.boxArgs.SetXCoordinateCalculator(renderPassData.xCoordinateCalculator.nativeCalculator); this.boxArgs.SetYCoordinateCalculator(renderPassData.yCoordinateCalculator.nativeCalculator); this.nativeBoxDrawingProvider.DrawPoints(this.boxArgs); if (fifoSweeping && fifoCapacity === this.parentSeries.dataSeries.count()) { this.boxArgs.startIndex = Math.min(yTop.size(), fifoStartIndex + fifoSweepingGap); this.boxArgs.count = Math.max(0, yTop.size() - fifoStartIndex - fifoSweepingGap); if (this.boxArgs.count > 0) { this.nativeBoxDrawingProvider.DrawPoints(this.boxArgs); } } }; BoxPlotSeriesDrawingProvider.prototype.drawWhiskers = function (renderContext, renderPassData, yValues, y1Values) { var pointSeries = renderPassData.pointSeries; var isCategoryAxis = renderPassData.xCoordinateCalculator.isCategoryCoordinateCalculator; var _a = this.getStartAndCount(renderPassData, pointSeries.xValues), startIndex = _a.startIndex, count = _a.count; var xValues = isCategoryAxis ? pointSeries.indexes : pointSeries.xValues; var linesPen = (0, Pen2DCache_1.getScrtPenFromCache)(this.whiskersPenCache); if (!linesPen) return; this.lineArgs.Reset(); this.lineArgs.fourVectorsMode = true; this.lineArgs.SetWValues(y1Values); this.lineArgs.SetLinesPen(linesPen); this.lineArgs.forceShaderMethod = true; this.lineArgs.verticalChart = renderPassData.isVerticalChart; this.lineArgs.count = count; this.lineArgs.startIndex = startIndex; this.lineArgs.SetNativeContext(renderContext.getNativeContext()); this.lineArgs.SetXValues(xValues); this.lineArgs.SetYValues(yValues); this.lineArgs.SetXCoordinateCalculator(renderPassData.xCoordinateCalculator.nativeCalculator); this.lineArgs.SetYCoordinateCalculator(renderPassData.yCoordinateCalculator.nativeCalculator); this.nativeLineDrawingProvider.DrawLinesVec(this.lineArgs); }; BoxPlotSeriesDrawingProvider.prototype.drawLines = function (renderContext, renderPassData, linesPen, count) { if (!linesPen) return; this.lineArgs.Reset(); this.lineArgs.SetLinesPen(linesPen); this.lineArgs.forceShaderMethod = true; this.lineArgs.forceClamp = true; this.lineArgs.verticalChart = renderPassData.isVerticalChart; this.lineArgs.count = count; this.lineArgs.startIndex = 0; // TODO: Do we need to provide paletting support for caps and whiskers? If yes, how it should work? this.lineArgs.SetNativeContext(renderContext.getNativeContext()); this.lineArgs.SetXValues(this.tempXVec); this.lineArgs.SetYValues(this.tempYVec); this.lineArgs.SetXCoordinateCalculator(renderPassData.xCoordinateCalculator.nativeCalculator); this.lineArgs.SetYCoordinateCalculator(renderPassData.yCoordinateCalculator.nativeCalculator); this.nativeLineDrawingProvider.DrawLinesVec(this.lineArgs); }; /** * To remove this and prepareTempMedianVectors() we need to update native SCRTLineSegmentDrawingProvider to support * input of three vectors xVals, yVals, x1Vals where x1Vals are treated as length of the line segment in X direction centered in x,y */ BoxPlotSeriesDrawingProvider.prototype.prepareTempCapVectors = function (startIndex, count, pointSeries, xCoordCalc, isCategoryAxis) { this.tempXVec.resizeFast(count * 4); this.tempYVec.resizeFast(count * 4); var _a = this.getProperties(), capDataPointWidth = _a.capDataPointWidth, dataPointWidthMode = _a.dataPointWidthMode; var dataPointWidthPx = this.parentSeries.getDataPointWidth(xCoordCalc, capDataPointWidth, dataPointWidthMode); var dataPointWidth = xCoordCalc.getDataWidth(dataPointWidthPx); var halfRange = dataPointWidth * 0.5; var minimumValues = pointSeries.minimumValues, maximumValues = pointSeries.maximumValues; var xValues = isCategoryAxis ? pointSeries.indexes : pointSeries.xValues; var xView = (0, vectorToArray_1.vectorToArrayViewF64)(xValues, this.webAssemblyContext); var minView = (0, vectorToArray_1.vectorToArrayViewF64)(minimumValues, this.webAssemblyContext); var maxView = (0, vectorToArray_1.vectorToArrayViewF64)(maximumValues, this.webAssemblyContext); var tempXView = (0, vectorToArray_1.vectorToArrayViewF64)(this.tempXVec, this.webAssemblyContext); var tempYView = (0, vectorToArray_1.vectorToArrayViewF64)(this.tempYVec, this.webAssemblyContext); for (var i = startIndex; i < startIndex + count; i++) { var x = xView[i]; var min = minView[i]; var max = maxView[i]; var outI = i * 4; tempXView[outI] = x - halfRange; tempYView[outI] = max; tempXView[outI + 1] = x + halfRange; tempYView[outI + 1] = max; tempXView[outI + 2] = x - halfRange; tempYView[outI + 2] = min; tempXView[outI + 3] = x + halfRange; tempYView[outI + 3] = min; } return count * 4; }; /** * It would be nice to have a strokePosition parameter (above, equal, below) for horizontal and vertical lines for SCRTLineSegmentDrawingProvider * to support positioning the line above, below or equal to the value */ BoxPlotSeriesDrawingProvider.prototype.prepareTempMedianVectors = function (startIndex, count, pointSeries, xCoordCalc, isCategoryAxis) { this.tempXVec.resizeFast(count * 2); this.tempYVec.resizeFast(count * 2); var _a = this.getProperties(), boxDataPointWidth = _a.boxDataPointWidth, dataPointWidthMode = _a.dataPointWidthMode; var dataPointWidthPx = this.parentSeries.getDataPointWidth(xCoordCalc, boxDataPointWidth, dataPointWidthMode); var dataPointWidth = xCoordCalc.getDataWidth(dataPointWidthPx); var halfRange = dataPointWidth * 0.5; var medianValues = pointSeries.medianValues; var xValues = isCategoryAxis ? pointSeries.indexes : pointSeries.xValues; var xView = (0, vectorToArray_1.vectorToArrayViewF64)(xValues, this.webAssemblyContext); var medView = (0, vectorToArray_1.vectorToArrayViewF64)(medianValues, this.webAssemblyContext); var tempXView = (0, vectorToArray_1.vectorToArrayViewF64)(this.tempXVec, this.webAssemblyContext); var tempYView = (0, vectorToArray_1.vectorToArrayViewF64)(this.tempYVec, this.webAssemblyContext); for (var i = startIndex; i < startIndex + count; i++) { var x = xView[i]; var y = medView[i]; var outI = i * 2; tempXView[outI] = x - halfRange; tempYView[outI] = y; tempXView[outI + 1] = x + halfRange; tempYView[outI + 1] = y; } return count * 2; }; /** @inheritDoc */ BoxPlotSeriesDrawingProvider.prototype.draw = function (renderContext, renderPassData) { var _a, _b, _c, _d; var _e = this.parentSeries.parentSurface, clipRect = _e.clipRect, seriesViewRect = _e.seriesViewRect; var pointSeries = renderPassData.pointSeries; var isCategoryAxis = renderPassData.xCoordinateCalculator.isCategoryCoordinateCalculator; var _f = this.getStartAndCount(renderPassData, pointSeries.xValues), startIndex = _f.startIndex, count = _f.count; this.drawWhiskers(renderContext, renderPassData, pointSeries.lowerQuartileValues, pointSeries.minimumValues); if ((_a = this.parentSeries.xAxis) === null || _a === void 0 ? void 0 : _a.isVerticalChart) { renderContext.setTranslationRotationAndClip(clipRect, seriesViewRect.x, seriesViewRect.y); } this.drawWhiskers(renderContext, renderPassData, pointSeries.upperQuartileValues, pointSeries.maximumValues); if ((_b = this.parentSeries.xAxis) === null || _b === void 0 ? void 0 : _b.isVerticalChart) { renderContext.setTranslationRotationAndClip(clipRect, seriesViewRect.x, seriesViewRect.y); } this.drawLines(renderContext, renderPassData, (0, Pen2DCache_1.getScrtPenFromCache)(this.capPenCache), this.prepareTempCapVectors(startIndex, count, pointSeries, renderPassData.xCoordinateCalculator, isCategoryAxis)); if ((_c = this.parentSeries.xAxis) === null || _c === void 0 ? void 0 : _c.isVerticalChart) { renderContext.setTranslationRotationAndClip(clipRect, seriesViewRect.x, seriesViewRect.y); } this.drawBoxes(renderContext, renderPassData); if ((_d = this.parentSeries.xAxis) === null || _d === void 0 ? void 0 : _d.isVerticalChart) { renderContext.setTranslationRotationAndClip(clipRect, seriesViewRect.x, seriesViewRect.y); } this.drawLines(renderContext, renderPassData, (0, Pen2DCache_1.getScrtPenFromCache)(this.medianLinePenCache), this.prepareTempMedianVectors(startIndex, count, pointSeries, renderPassData.xCoordinateCalculator, isCategoryAxis)); }; /** @inheritDoc */ BoxPlotSeriesDrawingProvider.prototype.onDpiChanged = function (args) { _super.prototype.onDpiChanged.call(this, args); // Passing the opacity to update all caches this.onSeriesPropertyChange(constants_1.PROPERTY.OPACITY); }; /** @inheritDoc */ BoxPlotSeriesDrawingProvider.prototype.onSeriesPropertyChange = function (propertyName) { _super.prototype.onSeriesPropertyChange.call(this, propertyName); var _a = this.getProperties(), boxStroke = _a.boxStroke, boxStrokeThickness = _a.boxStrokeThickness, opacity = _a.opacity, boxStrokeDashArray = _a.boxStrokeDashArray, capStroke = _a.capStroke, capStrokeThickness = _a.capStrokeThickness, capStrokeDashArray = _a.capStrokeDashArray, whiskersStroke = _a.whiskersStroke, whiskersStrokeDashArray = _a.whiskersStrokeDashArray, whiskersStrokeThickness = _a.whiskersStrokeThickness, medianStroke = _a.medianStroke, medianStrokeDashArray = _a.medianStrokeDashArray, medianStrokeThickness = _a.medianStrokeThickness; if (propertyName === constants_1.PROPERTY.STROKE || propertyName === constants_1.PROPERTY.STROKE_THICKNESS || propertyName === constants_1.PROPERTY.OPACITY || propertyName === constants_1.PROPERTY.STROKE_DASH_ARRAY) { (0, Pen2DCache_1.createPenInCache)(this.boxPenCache, boxStroke, boxStrokeThickness, opacity, boxStrokeDashArray, false); } if (propertyName === constants_1.PROPERTY.OPACITY || propertyName === constants_1.PROPERTY.FILL || propertyName === constants_1.PROPERTY.FILL_LINEAR_GRADIENT) { this.createBoxBrush(); } if (propertyName === constants_1.PROPERTY.OPACITY || propertyName === constants_1.PROPERTY.BOX_SERIES_CAP) { (0, Pen2DCache_1.createPenInCache)(this.capPenCache, capStroke, capStrokeThickness, opacity, capStrokeDashArray, false); } if (propertyName === constants_1.PROPERTY.OPACITY || propertyName === constants_1.PROPERTY.BOX_SERIES_WHISKERS) { (0, Pen2DCache_1.createPenInCache)(this.whiskersPenCache, whiskersStroke, whiskersStrokeThickness, opacity, whiskersStrokeDashArray, false); } if (propertyName === constants_1.PROPERTY.OPACITY || propertyName === constants_1.PROPERTY.BOX_SERIES_MEDIAN) { (0, Pen2DCache_1.createPenInCache)(this.medianLinePenCache, medianStroke, medianStrokeThickness, opacity, medianStrokeDashArray, false); } }; BoxPlotSeriesDrawingProvider.prototype.createBoxBrush = function () { var parentSurface = this.parentSeries.parentSurface; var _a = this.getProperties(), opacity = _a.opacity, boxFill = _a.boxFill, boxFillLinearGradient = _a.boxFillLinearGradient; var textureHeightRatio = (parentSurface === null || parentSurface === void 0 ? void 0 : parentSurface.isCopyCanvasSurface) ? parentSurface.domCanvas2D.height / SciChartSurfaceBase_1.SciChartSurfaceBase.domMasterCanvas.height : 1; var textureWidthRatio = (parentSurface === null || parentSurface === void 0 ? void 0 : parentSurface.isCopyCanvasSurface) ? parentSurface.domCanvas2D.width / SciChartSurfaceBase_1.SciChartSurfaceBase.domMasterCanvas.width : 1; return (0, BrushCache_1.createBrushInCache)(this.boxFillBrushCache, boxFill, opacity, textureHeightRatio, textureWidthRatio, boxFillLinearGradient); }; return BoxPlotSeriesDrawingProvider; }(BaseSeriesDrawingProvider_1.BaseSeriesDrawingProvider)); exports.BoxPlotSeriesDrawingProvider = BoxPlotSeriesDrawingProvider;