@wcardinal/wcardinal-geditor
Version:
WebGL-based graphic editor, tester and viewer for supervisory systems
463 lines • 19.3 kB
JavaScript
import { __extends } from "tslib";
import { NumberFormatters, EShapeActionRuntimeBase, EShapeLockPart } from "@wcardinal/wcardinal-ui";
import { EShapeChartLine } from "./e-shape-chart-line";
import { EShapeChartLineIds } from "./e-shape-chart-line-ids";
import { UtilShapeSearch } from "../../util/util-shape-search";
var EShapeChartLineActionRuntime = /** @class */ (function (_super) {
__extends(EShapeChartLineActionRuntime, _super);
function EShapeChartLineActionRuntime(shape) {
var _this = _super.call(this) || this;
// Lines
var line = UtilShapeSearch.findChildById(shape, "line");
if (line != null) {
var data = shape.data;
if (data.size() <= 0) {
line.detach();
_this.lines = [];
}
else {
var lines = [line];
for (var i = 1, imax = data.size(); i < imax; ++i) {
var cloned = line.clone();
cloned.attach(shape);
lines.push(cloned);
}
_this.lines = lines;
}
}
else {
_this.lines = [];
}
// Ticks
var xmajorCount = 3;
var ymajorCount = 3;
var xminorCount = 3;
var yminorCount = 3;
if (shape instanceof EShapeChartLine) {
xmajorCount = shape.axis.x.tick.major.count;
ymajorCount = shape.axis.y.tick.major.count;
xminorCount = shape.axis.x.tick.minor.count;
yminorCount = shape.axis.y.tick.minor.count;
}
_this.xmajorCount = xmajorCount;
_this.ymajorCount = ymajorCount;
_this.xminorCount = xminorCount;
_this.yminorCount = yminorCount;
_this.xmajors = _this.initTicks(shape, EShapeChartLineIds.X_AXIS_TICK_MAJOR_ID, xmajorCount);
_this.ymajors = _this.initTicks(shape, EShapeChartLineIds.Y_AXIS_TICK_MAJOR_ID, ymajorCount);
_this.xminors = _this.initTicks(shape, EShapeChartLineIds.X_AXIS_TICK_MINOR_ID, (xmajorCount + 1) * xminorCount);
_this.yminors = _this.initTicks(shape, EShapeChartLineIds.Y_AXIS_TICK_MINOR_ID, (ymajorCount + 1) * yminorCount);
_this.workMajorPositions = new Float64Array(Math.max(xmajorCount, ymajorCount));
// Tick format
var xtick = UtilShapeSearch.findChildById(shape, EShapeChartLineIds.X_AXIS_TICK_MAJOR_ID);
_this.xformatter = NumberFormatters.create(xtick != null ? xtick.text.value : "");
var ytick = UtilShapeSearch.findChildById(shape, EShapeChartLineIds.Y_AXIS_TICK_MAJOR_ID);
_this.yformatter = NumberFormatters.create(ytick != null ? ytick.text.value : "");
// Plot area
_this.plotArea = UtilShapeSearch.findChildById(shape, "plot-area");
// Padding
var xpadding = 10;
var ypadding = 10;
if (shape instanceof EShapeChartLine) {
xpadding = shape.axis.x.padding;
ypadding = shape.axis.y.padding;
}
_this.xpadding = xpadding;
_this.ypadding = ypadding;
return _this;
}
EShapeChartLineActionRuntime.prototype.initTicks = function (shape, id, count) {
var tick = UtilShapeSearch.findChildById(shape, id);
if (tick != null) {
if (count <= 0) {
tick.detach();
return [];
}
else {
var ticks = [tick];
for (var i = 1; i < count; ++i) {
var cloned = tick.clone();
cloned.attach(shape);
ticks.push(cloned);
}
return ticks;
}
}
else {
return [];
}
};
EShapeChartLineActionRuntime.prototype.toStepScale = function (scale) {
if (5.5 <= scale) {
return 10;
}
else if (2.2 <= scale) {
return 5;
}
else if (1.1 <= scale) {
return 2;
}
return 1;
};
EShapeChartLineActionRuntime.prototype.getStep = function (min, max, count) {
if (count <= 0 || max <= min) {
return -1;
}
// Calculate the step
var span = (max - min) / count;
var power = Math.floor(Math.log(span) / Math.LN10);
var base = Math.pow(10, power);
return this.toStepScale(span / base) * base;
};
EShapeChartLineActionRuntime.prototype.getTickPositions = function (min, max, count, step, padding, ratio, result) {
if (count <= 0) {
return result;
}
if (max <= min || step <= 0) {
result[0] = min;
for (var i = 1; i < count; ++i) {
result[i] = NaN;
}
return result;
}
// Set positions
var start = min / step;
var istart = Math.floor(start);
var dstart = start - istart;
if (padding < dstart * step * ratio) {
istart = Math.ceil(start);
}
var stop = max / step;
var istop = Math.ceil(stop);
var dstop = istop - stop;
if (padding < dstop * step * ratio) {
istop = Math.floor(stop);
}
var nticks = Math.min(count, Math.ceil(istop - istart + 1));
for (var i = 0; i < nticks; ++i) {
result[i] = (istart + i) * step;
}
for (var i = nticks; i < count; ++i) {
result[i] = NaN;
}
//
return result;
};
EShapeChartLineActionRuntime.prototype.updateTicksXMinor = function (mstep, index, position, min, ratio, lmin, lmax) {
var mticks = this.xminors;
if (0 < mticks.length) {
var minorCount = this.xminorCount;
if (0 < mstep) {
var padding = this.xpadding;
if (index < 0) {
for (var i = 0, j = (index + 1) * minorCount; i < minorCount; i += 1, j += 1) {
var mtick = mticks[j];
var x = (position - (minorCount - i) * mstep - min) * ratio + lmin;
if (lmin - padding <= x) {
mtick.lock(EShapeLockPart.UPLOADED);
mtick.visible = true;
mtick.transform.position.x = x;
mtick.unlock(EShapeLockPart.UPLOADED, true);
}
else {
mtick.visible = false;
}
}
}
else {
for (var i = 0, j = (index + 1) * minorCount; i < minorCount; i += 1, j += 1) {
var mtick = mticks[j];
var x = (position + (i + 1) * mstep - min) * ratio + lmin;
if (x <= lmax + padding) {
mtick.lock(EShapeLockPart.UPLOADED);
mtick.visible = true;
mtick.transform.position.x = x;
mtick.unlock(EShapeLockPart.UPLOADED, true);
}
else {
mtick.visible = false;
}
}
}
}
else {
for (var i = (index + 1) * minorCount, imax = i + minorCount; i < imax; ++i) {
mticks[i].visible = false;
}
}
}
};
EShapeChartLineActionRuntime.prototype.toStepMinor = function (step, minorCount) {
if (0 <= step) {
return step / (minorCount + 1);
}
else {
return -1;
}
};
EShapeChartLineActionRuntime.prototype.updateTicksX = function (min, max, ratio, lmin, lmax) {
var ticks = this.xmajors;
var mticks = this.xminors;
var minorCount = this.xminorCount;
var padding = this.xpadding;
// Major tick positions
var step = this.getStep(min, max, ticks.length);
var positions = this.getTickPositions(min, max, ticks.length, step, padding, ratio, this.workMajorPositions);
// First minors
var mstep = this.toStepMinor(step, minorCount);
this.updateTicksXMinor(mstep, -1, positions[0], min, ratio, lmin, lmax);
// Major and minor ticks
for (var i = 0, imax = ticks.length; i < imax; ++i) {
var tick = ticks[i];
var position = positions[i];
if (position === position) {
// Major tick
tick.lock(EShapeLockPart.UPLOADED);
tick.visible = true;
tick.transform.position.x = (position - min) * ratio + lmin;
tick.text.value = this.xformatter.format(position, step);
tick.unlock(EShapeLockPart.UPLOADED, true);
// Minor ticks
this.updateTicksXMinor(mstep, i, positions[i], min, ratio, lmin, lmax);
}
else {
// Major tick
tick.visible = false;
// Minor ticks
if (0 < mticks.length) {
for (var j = (i + 1) * minorCount, jmax = j + minorCount; j < jmax; ++j) {
mticks[j].visible = false;
}
}
}
}
};
EShapeChartLineActionRuntime.prototype.updateTicksYMinor = function (mstep, index, position, min, ratio, lmin, lmax) {
var mticks = this.yminors;
if (0 < mticks.length) {
var minorCount = this.yminorCount;
if (0 < mstep) {
var padding = this.ypadding;
if (index < 0) {
for (var i = 0, j = (index + 1) * minorCount; i < minorCount; i += 1, j += 1) {
var mtick = mticks[j];
var y = lmax - (position - (minorCount - i) * mstep - min) * ratio;
if (y <= lmax + padding) {
mtick.lock(EShapeLockPart.UPLOADED);
mtick.visible = true;
mtick.transform.position.y = y;
mtick.unlock(EShapeLockPart.UPLOADED, true);
}
else {
mtick.visible = false;
}
}
}
else {
for (var i = 0, j = (index + 1) * minorCount; i < minorCount; i += 1, j += 1) {
var mtick = mticks[j];
var y = lmax - (position + (i + 1) * mstep - min) * ratio;
if (lmin - padding <= y) {
mtick.lock(EShapeLockPart.UPLOADED);
mtick.visible = true;
mtick.transform.position.y = y;
mtick.unlock(EShapeLockPart.UPLOADED, true);
}
else {
mtick.visible = false;
}
}
}
}
else {
for (var i = (index + 1) * minorCount, imax = i + minorCount; i < imax; ++i) {
mticks[i].visible = false;
}
}
}
};
EShapeChartLineActionRuntime.prototype.updateTicksY = function (min, max, ratio, lmin, lmax) {
var ticks = this.ymajors;
var mticks = this.yminors;
var minorCount = this.yminorCount;
var padding = this.ypadding;
// Major tick positions
var step = this.getStep(min, max, ticks.length);
var positions = this.getTickPositions(min, max, ticks.length, step, padding, ratio, this.workMajorPositions);
// First minors
var mstep = this.toStepMinor(step, minorCount);
this.updateTicksYMinor(mstep, -1, positions[0], min, ratio, lmin, lmax);
// Major and minor ticks
for (var i = 0, imax = ticks.length; i < imax; ++i) {
var tick = ticks[i];
var position = positions[i];
if (position === position) {
// Major tick
tick.lock(EShapeLockPart.UPLOADED);
tick.visible = true;
tick.transform.position.y = lmax - (position - min) * ratio;
tick.text.value = this.yformatter.format(position, step);
tick.unlock(EShapeLockPart.UPLOADED, true);
// Minor ticks
this.updateTicksYMinor(mstep, i, positions[i], min, ratio, lmin, lmax);
}
else {
// Major tick
tick.visible = false;
// Minor ticks
if (0 < mticks.length) {
for (var j = (i + 1) * minorCount, jmax = j + minorCount; j < jmax; ++j) {
mticks[j].visible = false;
}
}
}
}
};
EShapeChartLineActionRuntime.prototype.updateLines = function (data, xmin, xratio, lxmin, ymin, yratio, lymax) {
var lines = this.lines;
for (var i = 0, imax = Math.min(lines.length, data.size()); i < imax; ++i) {
var value = data.get(i);
if (value != null) {
var line = lines[i];
var points = line.points;
if (points != null) {
var pointsValues = points.values;
var valueValues = value.values;
var valueValuesLength = valueValues.length;
if (2 <= valueValuesLength) {
var valueTimes = value.times;
var valueTimesLength = valueTimes.length;
if (valueTimesLength < valueValuesLength) {
// Index mode
for (var j = 0; j < valueValuesLength; ++j) {
var index = j << 1;
pointsValues[index + 0] = (j + 1 - xmin) * xratio + lxmin;
pointsValues[index + 1] = lymax - (valueValues[j] - ymin) * yratio;
}
}
else {
// Time mode
for (var j = 0; j < valueValuesLength; ++j) {
var index = j << 1;
pointsValues[index + 0] = (valueTimes[j] - xmin) * xratio + lxmin;
pointsValues[index + 1] = lymax - (valueValues[j] - ymin) * yratio;
}
}
line.lock(EShapeLockPart.UPLOADED);
line.visible = true;
points.values = pointsValues;
line.unlock(EShapeLockPart.UPLOADED, true);
}
else {
line.visible = false;
}
}
}
}
};
EShapeChartLineActionRuntime.prototype.execute = function (shape, runtime, time) {
var data = shape.data;
if (data.isChanged) {
// Calculate the plot range in the time-value coordinate
var xmin = +Infinity;
var xmax = -Infinity;
var ymin = +Infinity;
var ymax = -Infinity;
for (var i = 0, imax = data.size(); i < imax; ++i) {
var value = data.get(i);
if (value != null) {
var values = value.values;
var valuesLength = values.length;
var times = value.times;
var timesLength = times.length;
// X
if (timesLength < valuesLength) {
// Index mode
if (1 < xmin) {
xmin = 1;
}
if (xmax < valuesLength) {
xmax = valuesLength;
}
}
else {
// Time mode
for (var j = 0; j < timesLength; ++j) {
var t = times[j];
if (t < xmin) {
xmin = t;
}
if (xmax < t) {
xmax = t;
}
}
}
// Y
for (var j = 0; j < valuesLength; ++j) {
var v = values[j];
if (v < ymin) {
ymin = v;
}
if (ymax < v) {
ymax = v;
}
}
}
}
if (xmax < xmin) {
xmin = 0;
xmax = 1;
}
else if (xmax <= xmin) {
xmax = xmin + 1;
}
if (ymax < ymin) {
ymax = 1;
ymin = 0;
}
else if (ymax <= ymin) {
ymax = ymin + 1;
}
var xspan = xmax - xmin;
var yspan = ymax - ymin;
// Calculate plot range in the local coordinate
var plotArea = this.plotArea;
var size = plotArea != null ? plotArea.size : shape.size;
var sx = size.x * 0.5;
var sy = size.y * 0.5;
var xpadding = this.xpadding;
var ypadding = this.ypadding;
var lxmin = -sx + xpadding;
var lxmax = +sx - xpadding;
var lymin = -sy + ypadding;
var lymax = +sy - ypadding;
if (lxmax <= lxmin) {
lxmax = lxmin + 1;
}
if (lymax <= lymin) {
lymax = lymin + 1;
}
var lxspan = lxmax - lxmin;
var lyspan = lymax - lymin;
// x (in the time-value coordinate)
// lx (in the local coordinate)
// lx = (x - xmin) / (xmax - xmin) * (lxmax - lxmin) + lxmin
// = (x - xmin) * xratio + lxmin
// where xratio := (lxmax - lxmin) / (xmax - xmin)
//
// Please note thay the y coordinate in the local coordinate is upside down.
// Namely, ly = lymax - (y - ymin) * yratio.
var xratio = lxspan / xspan;
var yratio = lyspan / yspan;
// X ticks
this.updateTicksX(xmin, xmax, xratio, lxmin, lxmax);
// Y ticks
this.updateTicksY(ymin, ymax, yratio, lymin, lymax);
// Lines
this.updateLines(data, xmin, xratio, lxmin, ymin, yratio, lymax);
}
};
return EShapeChartLineActionRuntime;
}(EShapeActionRuntimeBase));
export { EShapeChartLineActionRuntime };
//# sourceMappingURL=e-shape-chart-line-action-runtime.js.map