scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
331 lines (330 loc) • 23.4 kB
JavaScript
"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;