ag-grid-enterprise
Version:
AG Grid Enterprise Features
250 lines • 9.71 kB
JavaScript
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Path2D = void 0;
var intersection_1 = require("./intersection");
var Command;
(function (Command) {
Command[Command["Move"] = 0] = "Move";
Command[Command["Line"] = 1] = "Line";
Command[Command["Arc"] = 2] = "Arc";
Command[Command["Curve"] = 3] = "Curve";
Command[Command["ClosePath"] = 4] = "ClosePath";
})(Command || (Command = {}));
var Path2D = /** @class */ (function () {
function Path2D() {
// The methods of this class will likely be called many times per animation frame,
// and any allocation can trigger a GC cycle during animation, so we attempt
// to minimize the number of allocations.
this.previousCommands = [];
this.previousParams = [];
this.previousClosedPath = false;
this.commands = [];
this.params = [];
this._closedPath = false;
}
Path2D.prototype.isDirty = function () {
if (this._closedPath !== this.previousClosedPath) {
return true;
}
if (this.previousCommands.length !== this.commands.length) {
return true;
}
if (this.previousParams.length !== this.params.length) {
return true;
}
for (var i = 0; i < this.commands.length; i++) {
if (this.commands[i] !== this.previousCommands[i]) {
return true;
}
}
for (var i = 0; i < this.params.length; i++) {
if (this.params[i] !== this.previousParams[i]) {
return true;
}
}
return false;
};
Path2D.prototype.draw = function (ctx) {
var e_1, _a;
var commands = this.commands;
var params = this.params;
var j = 0;
ctx.beginPath();
try {
for (var commands_1 = __values(commands), commands_1_1 = commands_1.next(); !commands_1_1.done; commands_1_1 = commands_1.next()) {
var command = commands_1_1.value;
switch (command) {
case Command.Move:
ctx.moveTo(params[j++], params[j++]);
break;
case Command.Line:
ctx.lineTo(params[j++], params[j++]);
break;
case Command.Curve:
ctx.bezierCurveTo(params[j++], params[j++], params[j++], params[j++], params[j++], params[j++]);
break;
case Command.Arc:
ctx.arc(params[j++], params[j++], params[j++], params[j++], params[j++], params[j++] === 1);
break;
case Command.ClosePath:
ctx.closePath();
break;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (commands_1_1 && !commands_1_1.done && (_a = commands_1.return)) _a.call(commands_1);
}
finally { if (e_1) throw e_1.error; }
}
if (commands.length === 0) {
ctx.closePath();
}
};
Path2D.prototype.moveTo = function (x, y) {
if (this.xy) {
this.xy[0] = x;
this.xy[1] = y;
}
else {
this.xy = [x, y];
}
this.commands.push(Command.Move);
this.params.push(x, y);
};
Path2D.prototype.lineTo = function (x, y) {
if (this.xy) {
this.commands.push(Command.Line);
this.params.push(x, y);
this.xy[0] = x;
this.xy[1] = y;
}
else {
this.moveTo(x, y);
}
};
Path2D.prototype.rect = function (x, y, width, height) {
this.moveTo(x, y);
this.lineTo(x + width, y);
this.lineTo(x + width, y + height);
this.lineTo(x, y + height);
this.closePath();
};
Path2D.prototype.arc = function (x, y, r, sAngle, eAngle, antiClockwise) {
if (antiClockwise === void 0) { antiClockwise = false; }
var endX = x + r * Math.cos(eAngle);
var endY = y + r * Math.sin(eAngle);
if (this.xy) {
this.xy[0] = endX;
this.xy[1] = endY;
}
else {
this.xy = [endX, endY];
}
this.commands.push(Command.Arc);
this.params.push(x, y, r, sAngle, eAngle, antiClockwise ? 1 : 0);
};
Path2D.prototype.cubicCurveTo = function (cx1, cy1, cx2, cy2, x, y) {
if (!this.xy) {
this.moveTo(cx1, cy1);
}
this.commands.push(Command.Curve);
this.params.push(cx1, cy1, cx2, cy2, x, y);
if (this.xy) {
this.xy[0] = x;
this.xy[1] = y;
}
};
Object.defineProperty(Path2D.prototype, "closedPath", {
get: function () {
return this._closedPath;
},
enumerable: false,
configurable: true
});
Path2D.prototype.closePath = function () {
if (this.xy) {
this.xy = undefined;
this.commands.push(Command.ClosePath);
this._closedPath = true;
}
};
Path2D.prototype.clear = function (_a) {
var _b = _a === void 0 ? { trackChanges: false } : _a, trackChanges = _b.trackChanges;
if (trackChanges) {
this.previousCommands = this.commands;
this.previousParams = this.params;
this.previousClosedPath = this._closedPath;
this.commands = [];
this.params = [];
}
else {
this.commands.length = 0;
this.params.length = 0;
}
this.xy = undefined;
this._closedPath = false;
};
Path2D.prototype.isPointInPath = function (x, y) {
var commands = this.commands;
var params = this.params;
var cn = commands.length;
// Hit testing using ray casting method, where the ray's origin is some point
// outside the path. In this case, an offscreen point that is remote enough, so that
// even if the path itself is large and is partially offscreen, the ray's origin
// will likely be outside the path anyway. To test if the given point is inside the
// path or not, we cast a ray from the origin to the given point and check the number
// of intersections of this segment with the path. If the number of intersections is
// even, then the ray both entered and exited the path an equal number of times,
// therefore the point is outside the path, and inside the path, if the number of
// intersections is odd. Since the path is compound, we check if the ray segment
// intersects with each of the path's segments, which can be either a line segment
// (one or no intersection points) or a Bézier curve segment (up to 3 intersection
// points).
var ox = -10000;
var oy = -10000;
// the starting point of the current path
var sx = NaN;
var sy = NaN;
// the previous point of the current path
var px = 0;
var py = 0;
var intersectionCount = 0;
for (var ci = 0, pi = 0; ci < cn; ci++) {
switch (commands[ci]) {
case Command.Move:
if (!isNaN(sx)) {
if (intersection_1.segmentIntersection(sx, sy, px, py, ox, oy, x, y)) {
intersectionCount++;
}
}
px = params[pi++];
sx = px;
py = params[pi++];
sy = py;
break;
case Command.Line:
if (intersection_1.segmentIntersection(px, py, params[pi++], params[pi++], ox, oy, x, y)) {
intersectionCount++;
}
px = params[pi - 2];
py = params[pi - 1];
break;
case Command.Curve:
intersectionCount += intersection_1.cubicSegmentIntersections(px, py, params[pi++], params[pi++], params[pi++], params[pi++], params[pi++], params[pi++], ox, oy, x, y).length;
px = params[pi - 2];
py = params[pi - 1];
break;
case Command.Arc:
intersectionCount += intersection_1.arcIntersections(params[pi++], params[pi++], params[pi++], params[pi++], params[pi++], Boolean(params[pi++]), ox, oy, x, y).length;
px = params[pi - 2];
py = params[pi - 1];
break;
case Command.ClosePath:
if (!isNaN(sx)) {
if (intersection_1.segmentIntersection(sx, sy, px, py, ox, oy, x, y)) {
intersectionCount++;
}
}
break;
}
}
return intersectionCount % 2 === 1;
};
return Path2D;
}());
exports.Path2D = Path2D;
//# sourceMappingURL=path2D.js.map