@bpgraph/core
Version:
**bpgraph** is a lightweight node-based visual programming library. It allows you to easily build interactive flow editors for low-code platforms, AI pipelines, or data processing systems.
1,664 lines (1,652 loc) • 764 kB
JavaScript
import { __export } from "./rolldown-runtime-BusqVNde.js";
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/geometry.helpers.mjs
const { round: round$4, floor, PI: PI$1 } = Math;
const scale = { linear: function(domain, range, value) {
var domainSpan = domain[1] - domain[0];
var rangeSpan = range[1] - range[0];
return (value - domain[0]) / domainSpan * rangeSpan + range[0] || 0;
} };
const normalizeAngle = function(angle) {
return angle % 360 + (angle < 0 ? 360 : 0);
};
const snapToGrid = function(value, gridSize) {
return gridSize * round$4(value / gridSize);
};
const toDeg = function(rad) {
return 180 * rad / PI$1 % 360;
};
const toRad = function(deg, over360) {
over360 = over360 || false;
deg = over360 ? deg : deg % 360;
return deg * PI$1 / 180;
};
const random = function(min$4, max$4) {
if (max$4 === void 0) {
max$4 = min$4 === void 0 ? 1 : min$4;
min$4 = 0;
} else if (max$4 < min$4) {
const temp = min$4;
min$4 = max$4;
max$4 = temp;
}
return floor(Math.random() * (max$4 - min$4 + 1) + min$4);
};
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/line.bearing.mjs
const { cos: cos$2, sin: sin$2, atan2: atan2$1 } = Math;
const bearing = function(p, q) {
var lat1 = toRad(p.y);
var lat2 = toRad(q.y);
var lon1 = p.x;
var lon2 = q.x;
var dLon = toRad(lon2 - lon1);
var y = sin$2(dLon) * cos$2(lat2);
var x = cos$2(lat1) * sin$2(lat2) - sin$2(lat1) * cos$2(lat2) * cos$2(dLon);
var brng = toDeg(atan2$1(y, x));
var bearings = [
"NE",
"E",
"SE",
"S",
"SW",
"W",
"NW",
"N"
];
var index = brng - 22.5;
if (index < 0) index += 360;
index = parseInt(index / 45);
return bearings[index];
};
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/line.squaredLength.mjs
const squaredLength = function(start, end) {
var x0 = start.x;
var y0 = start.y;
var x1 = end.x;
var y1 = end.y;
return (x0 -= x1) * x0 + (y0 -= y1) * y0;
};
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/line.length.mjs
const length = function(start, end) {
return Math.sqrt(squaredLength(start, end));
};
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/types.mjs
const types = {
Point: 1,
Line: 2,
Ellipse: 3,
Rect: 4,
Polyline: 5,
Polygon: 6,
Curve: 7,
Path: 8
};
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/point.mjs
const { abs: abs$2, cos: cos$1, sin: sin$1, sqrt: sqrt$2, min: min$3, max: max$3, atan2, round: round$3, pow: pow$3, PI } = Math;
const Point = function(x, y) {
if (!(this instanceof Point)) return new Point(x, y);
if (typeof x === "string") {
var xy = x.split(x.indexOf("@") === -1 ? " " : "@");
x = parseFloat(xy[0]);
y = parseFloat(xy[1]);
} else if (Object(x) === x) {
y = x.y;
x = x.x;
}
this.x = x === void 0 ? 0 : x;
this.y = y === void 0 ? 0 : y;
};
Point.fromPolar = function(distance, angle, origin) {
origin = new Point(origin);
var x = abs$2(distance * cos$1(angle));
var y = abs$2(distance * sin$1(angle));
var deg = normalizeAngle(toDeg(angle));
if (deg < 90) y = -y;
else if (deg < 180) {
x = -x;
y = -y;
} else if (deg < 270) x = -x;
return new Point(origin.x + x, origin.y + y);
};
Point.random = function(x1, x2, y1, y2) {
return new Point(random(x1, x2), random(y1, y2));
};
Point.prototype = {
type: types.Point,
chooseClosest: function(points) {
var n = points.length;
if (n === 1) return new Point(points[0]);
var closest$1 = null;
var minSqrDistance = Infinity;
for (var i = 0; i < n; i++) {
var p = new Point(points[i]);
var sqrDistance = this.squaredDistance(p);
if (sqrDistance < minSqrDistance) {
closest$1 = p;
minSqrDistance = sqrDistance;
}
}
return closest$1;
},
adhereToRect: function(r) {
if (r.containsPoint(this)) return this;
this.x = min$3(max$3(this.x, r.x), r.x + r.width);
this.y = min$3(max$3(this.y, r.y), r.y + r.height);
return this;
},
angleBetween: function(p1, p2) {
var angleBetween = this.equals(p1) || this.equals(p2) ? NaN : this.theta(p2) - this.theta(p1);
if (angleBetween < 0) angleBetween += 360;
return angleBetween;
},
bearing: function(point$1) {
return bearing(this, point$1);
},
changeInAngle: function(dx, dy, ref) {
return this.clone().offset(-dx, -dy).theta(ref) - this.theta(ref);
},
clone: function() {
return new Point(this);
},
cross: function(p1, p2) {
return p1 && p2 ? (p2.x - this.x) * (p1.y - this.y) - (p2.y - this.y) * (p1.x - this.x) : NaN;
},
difference: function(dx, dy) {
if (Object(dx) === dx) {
dy = dx.y;
dx = dx.x;
}
return new Point(this.x - (dx || 0), this.y - (dy || 0));
},
distance: function(p) {
return length(this, p);
},
dot: function(p) {
return p ? this.x * p.x + this.y * p.y : NaN;
},
equals: function(p) {
return !!p && this.x === p.x && this.y === p.y;
},
lerp: function(p, t) {
var x = this.x;
var y = this.y;
return new Point((1 - t) * x + t * p.x, (1 - t) * y + t * p.y);
},
magnitude: function() {
return sqrt$2(this.x * this.x + this.y * this.y) || .01;
},
manhattanDistance: function(p) {
return abs$2(p.x - this.x) + abs$2(p.y - this.y);
},
move: function(ref, distance) {
var theta = toRad(new Point(ref).theta(this));
var offset$1 = this.offset(cos$1(theta) * distance, -sin$1(theta) * distance);
return offset$1;
},
normalize: function(length$1) {
var scale$1 = (length$1 || 1) / this.magnitude();
return this.scale(scale$1, scale$1);
},
offset: function(dx, dy) {
if (Object(dx) === dx) {
dy = dx.y;
dx = dx.x;
}
this.x += dx || 0;
this.y += dy || 0;
return this;
},
reflection: function(ref) {
return new Point(ref).move(this, this.distance(ref));
},
rotate: function(origin, angle) {
if (angle === 0) return this;
origin = origin || new Point(0, 0);
angle = toRad(normalizeAngle(-angle));
var cosAngle = cos$1(angle);
var sinAngle = sin$1(angle);
var x = cosAngle * (this.x - origin.x) - sinAngle * (this.y - origin.y) + origin.x;
var y = sinAngle * (this.x - origin.x) + cosAngle * (this.y - origin.y) + origin.y;
this.x = x;
this.y = y;
return this;
},
round: function(precision) {
let f = 1;
if (precision) switch (precision) {
case 1:
f = 10;
break;
case 2:
f = 100;
break;
case 3:
f = 1e3;
break;
default:
f = pow$3(10, precision);
break;
}
this.x = round$3(this.x * f) / f;
this.y = round$3(this.y * f) / f;
return this;
},
scale: function(sx, sy, origin) {
origin = origin && new Point(origin) || new Point(0, 0);
this.x = origin.x + sx * (this.x - origin.x);
this.y = origin.y + sy * (this.y - origin.y);
return this;
},
snapToGrid: function(gx, gy) {
this.x = snapToGrid(this.x, gx);
this.y = snapToGrid(this.y, gy || gx);
return this;
},
squaredDistance: function(p) {
return squaredLength(this, p);
},
theta: function(p) {
p = new Point(p);
var y = -(p.y - this.y);
var x = p.x - this.x;
var rad = atan2(y, x);
if (rad < 0) rad = 2 * PI + rad;
return 180 * rad / PI;
},
toJSON: function() {
return {
x: this.x,
y: this.y
};
},
toPolar: function(o) {
o = o && new Point(o) || new Point(0, 0);
var x = this.x;
var y = this.y;
this.x = sqrt$2((x - o.x) * (x - o.x) + (y - o.y) * (y - o.y));
this.y = toRad(o.theta(new Point(x, y)));
return this;
},
toString: function() {
return this.x + "@" + this.y;
},
serialize: function() {
return this.x + "," + this.y;
},
update: function(x, y) {
if (Object(x) === x) {
y = x.y;
x = x.x;
}
this.x = x || 0;
this.y = y || 0;
return this;
},
vectorAngle: function(p) {
var zero = new Point(0, 0);
return zero.angleBetween(this, p);
}
};
Point.prototype.translate = Point.prototype.offset;
const point = Point;
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/line.mjs
const { max: max$2, min: min$2 } = Math;
const Line = function(p1, p2) {
if (!(this instanceof Line)) return new Line(p1, p2);
if (p1 instanceof Line) return new Line(p1.start, p1.end);
this.start = new Point(p1);
this.end = new Point(p2);
};
Line.prototype = {
type: types.Line,
angle: function() {
var horizontalPoint = new Point(this.start.x + 1, this.start.y);
return this.start.angleBetween(this.end, horizontalPoint);
},
bbox: function() {
var left$3 = min$2(this.start.x, this.end.x);
var top$3 = min$2(this.start.y, this.end.y);
var right$3 = max$2(this.start.x, this.end.x);
var bottom$3 = max$2(this.start.y, this.end.y);
return new Rect(left$3, top$3, right$3 - left$3, bottom$3 - top$3);
},
bearing: function() {
return bearing(this.start, this.end);
},
clone: function() {
return new Line(this.start, this.end);
},
closestPoint: function(p) {
return this.pointAt(this.closestPointNormalizedLength(p));
},
closestPointLength: function(p) {
return this.closestPointNormalizedLength(p) * this.length();
},
closestPointNormalizedLength: function(p) {
var product = this.vector().dot(new Line(this.start, p).vector());
var cpNormalizedLength = min$2(1, max$2(0, product / this.squaredLength()));
if (cpNormalizedLength !== cpNormalizedLength) return 0;
return cpNormalizedLength;
},
closestPointTangent: function(p) {
return this.tangentAt(this.closestPointNormalizedLength(p));
},
containsPoint: function(p) {
var start = this.start;
var end = this.end;
if (start.cross(p, end) !== 0) return false;
var length$1 = this.length();
if (new Line(start, p).length() > length$1) return false;
if (new Line(p, end).length() > length$1) return false;
return true;
},
divideAt: function(ratio) {
var dividerPoint = this.pointAt(ratio);
return [new Line(this.start, dividerPoint), new Line(dividerPoint, this.end)];
},
divideAtLength: function(length$1) {
var dividerPoint = this.pointAtLength(length$1);
return [new Line(this.start, dividerPoint), new Line(dividerPoint, this.end)];
},
equals: function(l) {
return !!l && this.start.x === l.start.x && this.start.y === l.start.y && this.end.x === l.end.x && this.end.y === l.end.y;
},
intersect: function(shape, opt) {
if (shape && shape.intersectionWithLine) {
var intersection$2 = shape.intersectionWithLine(this, opt);
if (intersection$2 && shape instanceof Line) intersection$2 = intersection$2[0];
return intersection$2;
}
return null;
},
intersectionWithLine: function(line$2) {
var pt1Dir = new Point(this.end.x - this.start.x, this.end.y - this.start.y);
var pt2Dir = new Point(line$2.end.x - line$2.start.x, line$2.end.y - line$2.start.y);
var det = pt1Dir.x * pt2Dir.y - pt1Dir.y * pt2Dir.x;
var deltaPt = new Point(line$2.start.x - this.start.x, line$2.start.y - this.start.y);
var alpha = deltaPt.x * pt2Dir.y - deltaPt.y * pt2Dir.x;
var beta = deltaPt.x * pt1Dir.y - deltaPt.y * pt1Dir.x;
if (det === 0 || alpha * det < 0 || beta * det < 0) return null;
if (det > 0) {
if (alpha > det || beta > det) return null;
} else if (alpha < det || beta < det) return null;
return [new Point(this.start.x + alpha * pt1Dir.x / det, this.start.y + alpha * pt1Dir.y / det)];
},
isDifferentiable: function() {
return !this.start.equals(this.end);
},
length: function() {
return length(this.start, this.end);
},
midpoint: function() {
return new Point((this.start.x + this.end.x) / 2, (this.start.y + this.end.y) / 2);
},
parallel: function(distance) {
const l = this.clone();
if (!this.isDifferentiable()) return l;
const { start, end } = l;
const eRef = start.clone().rotate(end, 270);
const sRef = end.clone().rotate(start, 90);
start.move(sRef, distance);
end.move(eRef, distance);
return l;
},
pointAt: function(t) {
var start = this.start;
var end = this.end;
if (t <= 0) return start.clone();
if (t >= 1) return end.clone();
return start.lerp(end, t);
},
pointAtLength: function(length$1) {
var start = this.start;
var end = this.end;
var fromStart = true;
if (length$1 < 0) {
fromStart = false;
length$1 = -length$1;
}
var lineLength = this.length();
if (length$1 >= lineLength) return fromStart ? end.clone() : start.clone();
return this.pointAt((fromStart ? length$1 : lineLength - length$1) / lineLength);
},
pointOffset: function(p) {
p = new Point(p);
var start = this.start;
var end = this.end;
var determinant$1 = (end.x - start.x) * (p.y - start.y) - (end.y - start.y) * (p.x - start.x);
return determinant$1 / this.length();
},
rotate: function(origin, angle) {
this.start.rotate(origin, angle);
this.end.rotate(origin, angle);
return this;
},
round: function(precision) {
this.start.round(precision);
this.end.round(precision);
return this;
},
scale: function(sx, sy, origin) {
this.start.scale(sx, sy, origin);
this.end.scale(sx, sy, origin);
return this;
},
setLength: function(length$1) {
var currentLength = this.length();
if (!currentLength) return this;
var scaleFactor = length$1 / currentLength;
return this.scale(scaleFactor, scaleFactor, this.start);
},
squaredLength: function() {
return squaredLength(this.start, this.end);
},
tangentAt: function(t) {
if (!this.isDifferentiable()) return null;
var start = this.start;
var end = this.end;
var tangentStart = this.pointAt(t);
var tangentLine = new Line(start, end);
tangentLine.translate(tangentStart.x - start.x, tangentStart.y - start.y);
return tangentLine;
},
tangentAtLength: function(length$1) {
if (!this.isDifferentiable()) return null;
var start = this.start;
var end = this.end;
var tangentStart = this.pointAtLength(length$1);
var tangentLine = new Line(start, end);
tangentLine.translate(tangentStart.x - start.x, tangentStart.y - start.y);
return tangentLine;
},
toString: function() {
return this.start.toString() + " " + this.end.toString();
},
serialize: function() {
return this.start.serialize() + " " + this.end.serialize();
},
translate: function(tx, ty) {
this.start.translate(tx, ty);
this.end.translate(tx, ty);
return this;
},
vector: function() {
return new Point(this.end.x - this.start.x, this.end.y - this.start.y);
}
};
Line.prototype.intersection = Line.prototype.intersect;
const line$1 = Line;
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/ellipse.mjs
const { sqrt: sqrt$1, round: round$2, pow: pow$2 } = Math;
const Ellipse$1 = function(c, a, b) {
if (!(this instanceof Ellipse$1)) return new Ellipse$1(c, a, b);
if (c instanceof Ellipse$1) return new Ellipse$1(new Point(c.x, c.y), c.a, c.b);
c = new Point(c);
this.x = c.x;
this.y = c.y;
this.a = a;
this.b = b;
};
Ellipse$1.fromRect = function(rect$1) {
rect$1 = new Rect(rect$1);
return new Ellipse$1(rect$1.center(), rect$1.width / 2, rect$1.height / 2);
};
Ellipse$1.prototype = {
type: types.Ellipse,
bbox: function() {
return new Rect(this.x - this.a, this.y - this.b, 2 * this.a, 2 * this.b);
},
center: function() {
return new Point(this.x, this.y);
},
clone: function() {
return new Ellipse$1(this);
},
containsPoint: function(p) {
return this.normalizedDistance(p) <= 1;
},
equals: function(ellipse$2) {
return !!ellipse$2 && ellipse$2.x === this.x && ellipse$2.y === this.y && ellipse$2.a === this.a && ellipse$2.b === this.b;
},
inflate: function(dx, dy) {
if (dx === void 0) dx = 0;
if (dy === void 0) dy = dx;
this.a += 2 * dx;
this.b += 2 * dy;
return this;
},
intersectionWithLine: function(line$2) {
var intersections = [];
var a1 = line$2.start;
var a2 = line$2.end;
var rx = this.a;
var ry = this.b;
var dir = line$2.vector();
var diff$1 = a1.difference(new Point(this));
var mDir = new Point(dir.x / (rx * rx), dir.y / (ry * ry));
var mDiff = new Point(diff$1.x / (rx * rx), diff$1.y / (ry * ry));
var a = dir.dot(mDir);
var b = dir.dot(mDiff);
var c = diff$1.dot(mDiff) - 1;
var d = b * b - a * c;
if (d < 0) return null;
else if (d > 0) {
var root = sqrt$1(d);
var ta = (-b - root) / a;
var tb = (-b + root) / a;
if ((ta < 0 || 1 < ta) && (tb < 0 || 1 < tb)) return null;
else {
if (0 <= ta && ta <= 1) intersections.push(a1.lerp(a2, ta));
if (0 <= tb && tb <= 1) intersections.push(a1.lerp(a2, tb));
}
} else {
var t = -b / a;
if (0 <= t && t <= 1) intersections.push(a1.lerp(a2, t));
else return null;
}
return intersections;
},
intersectionWithLineFromCenterToPoint: function(p, angle) {
p = new Point(p);
if (angle) p.rotate(new Point(this.x, this.y), angle);
var dx = p.x - this.x;
var dy = p.y - this.y;
var result$1;
if (dx === 0) {
result$1 = this.bbox().pointNearestToPoint(p);
if (angle) return result$1.rotate(new Point(this.x, this.y), -angle);
return result$1;
}
var m = dy / dx;
var mSquared = m * m;
var aSquared = this.a * this.a;
var bSquared = this.b * this.b;
var x = sqrt$1(1 / (1 / aSquared + mSquared / bSquared));
x = dx < 0 ? -x : x;
var y = m * x;
result$1 = new Point(this.x + x, this.y + y);
if (angle) return result$1.rotate(new Point(this.x, this.y), -angle);
return result$1;
},
normalizedDistance: function(point$1) {
var x0 = point$1.x;
var y0 = point$1.y;
var a = this.a;
var b = this.b;
var x = this.x;
var y = this.y;
return (x0 - x) * (x0 - x) / (a * a) + (y0 - y) * (y0 - y) / (b * b);
},
round: function(precision) {
let f = 1;
if (precision) switch (precision) {
case 1:
f = 10;
break;
case 2:
f = 100;
break;
case 3:
f = 1e3;
break;
default:
f = pow$2(10, precision);
break;
}
this.x = round$2(this.x * f) / f;
this.y = round$2(this.y * f) / f;
this.a = round$2(this.a * f) / f;
this.b = round$2(this.b * f) / f;
return this;
},
tangentTheta: function(p) {
var refPointDelta = 30;
var x0 = p.x;
var y0 = p.y;
var a = this.a;
var b = this.b;
var center$1 = this.bbox().center();
var m = center$1.x;
var n = center$1.y;
var q1 = x0 > center$1.x + a / 2;
var q3 = x0 < center$1.x - a / 2;
var y, x;
if (q1 || q3) {
y = x0 > center$1.x ? y0 - refPointDelta : y0 + refPointDelta;
x = a * a / (x0 - m) - a * a * (y0 - n) * (y - n) / (b * b * (x0 - m)) + m;
} else {
x = y0 > center$1.y ? x0 + refPointDelta : x0 - refPointDelta;
y = b * b / (y0 - n) - b * b * (x0 - m) * (x - m) / (a * a * (y0 - n)) + n;
}
return new Point(x, y).theta(p);
},
toString: function() {
return new Point(this.x, this.y).toString() + " " + this.a + " " + this.b;
}
};
const ellipse$1 = Ellipse$1;
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/rect.mjs
const { abs: abs$1, cos, sin, min: min$1, max: max$1, round: round$1, pow: pow$1 } = Math;
const Rect = function(x, y, w, h) {
if (!(this instanceof Rect)) return new Rect(x, y, w, h);
if (Object(x) === x) {
y = x.y;
w = x.width;
h = x.height;
x = x.x;
}
this.x = x === void 0 ? 0 : x;
this.y = y === void 0 ? 0 : y;
this.width = w === void 0 ? 0 : w;
this.height = h === void 0 ? 0 : h;
};
Rect.fromEllipse = function(e) {
e = new Ellipse$1(e);
return new Rect(e.x - e.a, e.y - e.b, 2 * e.a, 2 * e.b);
};
Rect.fromPointUnion = function(...points) {
if (points.length === 0) return null;
const p = new Point();
let minX, minY, maxX, maxY;
minX = minY = Infinity;
maxX = maxY = -Infinity;
for (let i = 0; i < points.length; i++) {
p.update(points[i]);
const x = p.x;
const y = p.y;
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
}
return new Rect(minX, minY, maxX - minX, maxY - minY);
};
Rect.fromRectUnion = function(...rects) {
if (rects.length === 0) return null;
const r = new Rect();
let minX, minY, maxX, maxY;
minX = minY = Infinity;
maxX = maxY = -Infinity;
for (let i = 0; i < rects.length; i++) {
r.update(rects[i]);
const x = r.x;
const y = r.y;
const mX = x + r.width;
const mY = y + r.height;
if (x < minX) minX = x;
if (mX > maxX) maxX = mX;
if (y < minY) minY = y;
if (mY > maxY) maxY = mY;
}
return new Rect(minX, minY, maxX - minX, maxY - minY);
};
Rect.prototype = {
type: types.Rect,
bbox: function(angle) {
return this.clone().rotateAroundCenter(angle);
},
rotateAroundCenter: function(angle) {
if (!angle) return this;
const { width: width$1, height: height$1 } = this;
const theta = toRad(angle);
const st = abs$1(sin(theta));
const ct = abs$1(cos(theta));
const w = width$1 * ct + height$1 * st;
const h = width$1 * st + height$1 * ct;
this.x += (width$1 - w) / 2;
this.y += (height$1 - h) / 2;
this.width = w;
this.height = h;
return this;
},
bottomLeft: function() {
return new Point(this.x, this.y + this.height);
},
bottomLine: function() {
return new Line(this.bottomLeft(), this.bottomRight());
},
bottomMiddle: function() {
return new Point(this.x + this.width / 2, this.y + this.height);
},
center: function() {
return new Point(this.x + this.width / 2, this.y + this.height / 2);
},
clone: function() {
return new Rect(this);
},
containsPoint: function(p, opt) {
let x, y;
if (!p || typeof p === "string") ({x, y} = new Point(p));
else ({x = 0, y = 0} = p);
return opt && opt.strict ? x > this.x && x < this.x + this.width && y > this.y && y < this.y + this.height : x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;
},
containsRect: function(r) {
var r0 = new Rect(this).normalize();
var r1 = new Rect(r).normalize();
var w0 = r0.width;
var h0 = r0.height;
var w1 = r1.width;
var h1 = r1.height;
if (!w0 || !h0 || !w1 || !h1) return false;
var x0 = r0.x;
var y0 = r0.y;
var x1 = r1.x;
var y1 = r1.y;
w1 += x1;
w0 += x0;
h1 += y1;
h0 += y0;
return x0 <= x1 && w1 <= w0 && y0 <= y1 && h1 <= h0;
},
corner: function() {
return new Point(this.x + this.width, this.y + this.height);
},
equals: function(r) {
var mr = new Rect(this).normalize();
var nr = new Rect(r).normalize();
return mr.x === nr.x && mr.y === nr.y && mr.width === nr.width && mr.height === nr.height;
},
inflate: function(dx, dy) {
if (dx === void 0) dx = 0;
if (dy === void 0) dy = dx;
this.x -= dx;
this.y -= dy;
this.width += 2 * dx;
this.height += 2 * dy;
return this;
},
intersect: function(r) {
var myOrigin = this.origin();
var myCorner = this.corner();
var rOrigin = r.origin();
var rCorner = r.corner();
if (rCorner.x <= myOrigin.x || rCorner.y <= myOrigin.y || rOrigin.x >= myCorner.x || rOrigin.y >= myCorner.y) return null;
var x = max$1(myOrigin.x, rOrigin.x);
var y = max$1(myOrigin.y, rOrigin.y);
return new Rect(x, y, min$1(myCorner.x, rCorner.x) - x, min$1(myCorner.y, rCorner.y) - y);
},
intersectionWithLine: function(line$2) {
var r = this;
var rectLines = [
r.topLine(),
r.rightLine(),
r.bottomLine(),
r.leftLine()
];
var points = [];
var dedupeArr = [];
var pt, i;
var n = rectLines.length;
for (i = 0; i < n; i++) {
pt = line$2.intersect(rectLines[i]);
if (pt !== null && dedupeArr.indexOf(pt.toString()) < 0) {
points.push(pt);
dedupeArr.push(pt.toString());
}
}
return points.length > 0 ? points : null;
},
intersectionWithLineFromCenterToPoint: function(p, angle) {
p = new Point(p);
var center$1 = new Point(this.x + this.width / 2, this.y + this.height / 2);
var result$1;
if (angle) p.rotate(center$1, angle);
var sides = [
this.topLine(),
this.rightLine(),
this.bottomLine(),
this.leftLine()
];
var connector = new Line(center$1, p);
for (var i = sides.length - 1; i >= 0; --i) {
var intersection$2 = sides[i].intersection(connector);
if (intersection$2 !== null) {
result$1 = intersection$2;
break;
}
}
if (result$1 && angle) result$1.rotate(center$1, -angle);
return result$1;
},
leftLine: function() {
return new Line(this.topLeft(), this.bottomLeft());
},
leftMiddle: function() {
return new Point(this.x, this.y + this.height / 2);
},
maxRectScaleToFit: function(rect$1, origin) {
rect$1 = new Rect(rect$1);
origin || (origin = rect$1.center());
var sx1, sx2, sx3, sx4, sy1, sy2, sy3, sy4;
var ox = origin.x;
var oy = origin.y;
sx1 = sx2 = sx3 = sx4 = sy1 = sy2 = sy3 = sy4 = Infinity;
var p1 = rect$1.topLeft();
if (p1.x < ox) sx1 = (this.x - ox) / (p1.x - ox);
if (p1.y < oy) sy1 = (this.y - oy) / (p1.y - oy);
var p2 = rect$1.bottomRight();
if (p2.x > ox) sx2 = (this.x + this.width - ox) / (p2.x - ox);
if (p2.y > oy) sy2 = (this.y + this.height - oy) / (p2.y - oy);
var p3 = rect$1.topRight();
if (p3.x > ox) sx3 = (this.x + this.width - ox) / (p3.x - ox);
if (p3.y < oy) sy3 = (this.y - oy) / (p3.y - oy);
var p4 = rect$1.bottomLeft();
if (p4.x < ox) sx4 = (this.x - ox) / (p4.x - ox);
if (p4.y > oy) sy4 = (this.y + this.height - oy) / (p4.y - oy);
return {
sx: min$1(sx1, sx2, sx3, sx4),
sy: min$1(sy1, sy2, sy3, sy4)
};
},
maxRectUniformScaleToFit: function(rect$1, origin) {
var scale$1 = this.maxRectScaleToFit(rect$1, origin);
return min$1(scale$1.sx, scale$1.sy);
},
moveAndExpand: function(r) {
this.x += r.x || 0;
this.y += r.y || 0;
this.width += r.width || 0;
this.height += r.height || 0;
return this;
},
normalize: function() {
var newx = this.x;
var newy = this.y;
var newwidth = this.width;
var newheight = this.height;
if (this.width < 0) {
newx = this.x + this.width;
newwidth = -this.width;
}
if (this.height < 0) {
newy = this.y + this.height;
newheight = -this.height;
}
this.x = newx;
this.y = newy;
this.width = newwidth;
this.height = newheight;
return this;
},
offset: function(dx, dy) {
return Point.prototype.offset.call(this, dx, dy);
},
origin: function() {
return new Point(this.x, this.y);
},
pointNearestToPoint: function(point$1) {
point$1 = new Point(point$1);
if (this.containsPoint(point$1)) {
var side = this.sideNearestToPoint(point$1);
switch (side) {
case "right": return new Point(this.x + this.width, point$1.y);
case "left": return new Point(this.x, point$1.y);
case "bottom": return new Point(point$1.x, this.y + this.height);
case "top": return new Point(point$1.x, this.y);
}
}
return point$1.adhereToRect(this);
},
rightLine: function() {
return new Line(this.topRight(), this.bottomRight());
},
rightMiddle: function() {
return new Point(this.x + this.width, this.y + this.height / 2);
},
round: function(precision) {
let f = 1;
if (precision) switch (precision) {
case 1:
f = 10;
break;
case 2:
f = 100;
break;
case 3:
f = 1e3;
break;
default:
f = pow$1(10, precision);
break;
}
this.x = round$1(this.x * f) / f;
this.y = round$1(this.y * f) / f;
this.width = round$1(this.width * f) / f;
this.height = round$1(this.height * f) / f;
return this;
},
scale: function(sx, sy, origin) {
origin = this.origin().scale(sx, sy, origin);
this.x = origin.x;
this.y = origin.y;
this.width *= sx;
this.height *= sy;
return this;
},
sideNearestToPoint: function(point$1) {
point$1 = new Point(point$1);
var distToLeft = point$1.x - this.x;
var distToRight = this.x + this.width - point$1.x;
var distToTop = point$1.y - this.y;
var distToBottom = this.y + this.height - point$1.y;
var closest$1 = distToLeft;
var side = "left";
if (distToRight < closest$1) {
closest$1 = distToRight;
side = "right";
}
if (distToTop < closest$1) {
closest$1 = distToTop;
side = "top";
}
if (distToBottom < closest$1) side = "bottom";
return side;
},
snapToGrid: function(gx, gy) {
var origin = this.origin().snapToGrid(gx, gy);
var corner = this.corner().snapToGrid(gx, gy);
this.x = origin.x;
this.y = origin.y;
this.width = corner.x - origin.x;
this.height = corner.y - origin.y;
return this;
},
toJSON: function() {
return {
x: this.x,
y: this.y,
width: this.width,
height: this.height
};
},
topLine: function() {
return new Line(this.topLeft(), this.topRight());
},
topMiddle: function() {
return new Point(this.x + this.width / 2, this.y);
},
topRight: function() {
return new Point(this.x + this.width, this.y);
},
toString: function() {
return this.origin().toString() + " " + this.corner().toString();
},
union: function(rect$1) {
return Rect.fromRectUnion(this, rect$1);
},
update: function(x, y, w, h) {
if (Object(x) === x) {
y = x.y;
w = x.width;
h = x.height;
x = x.x;
}
this.x = x || 0;
this.y = y || 0;
this.width = w || 0;
this.height = h || 0;
return this;
}
};
Rect.prototype.bottomRight = Rect.prototype.corner;
Rect.prototype.topLeft = Rect.prototype.origin;
Rect.prototype.translate = Rect.prototype.offset;
const rect = Rect;
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/points.mjs
function parsePoints(svgString) {
const trimmedString = svgString.trim();
if (trimmedString === "") return [];
const points = [];
const coords = trimmedString.split(/\b\s*,\s*|,\s*|\s+/);
const numCoords = coords.length;
for (let i = 0; i < numCoords; i += 2) points.push({
x: +coords[i],
y: +coords[i + 1]
});
return points;
}
function clonePoints(points) {
const numPoints = points.length;
if (numPoints === 0) return [];
const newPoints = [];
for (let i = 0; i < numPoints; i++) {
const point$1 = points[i].clone();
newPoints.push(point$1);
}
return newPoints;
}
function convexHull(points) {
const { abs: abs$3 } = Math;
var i;
var n;
var numPoints = points.length;
if (numPoints === 0) return [];
var startPoint;
for (i = 0; i < numPoints; i++) if (startPoint === void 0) startPoint = points[i];
else if (points[i].y < startPoint.y) startPoint = points[i];
else if (points[i].y === startPoint.y && points[i].x > startPoint.x) startPoint = points[i];
var sortedPointRecords = [];
for (i = 0; i < numPoints; i++) {
var angle = startPoint.theta(points[i]);
if (angle === 0) angle = 360;
var entry = [
points[i],
i,
angle
];
sortedPointRecords.push(entry);
}
sortedPointRecords.sort(function(record1, record2) {
var sortOutput = record1[2] - record2[2];
if (sortOutput === 0) sortOutput = record2[1] - record1[1];
return sortOutput;
});
if (sortedPointRecords.length > 2) {
var startPointRecord = sortedPointRecords[sortedPointRecords.length - 1];
sortedPointRecords.unshift(startPointRecord);
}
var insidePoints = {};
var hullPointRecords = [];
var currentPointRecord;
var currentPoint;
var lastHullPointRecord;
var lastHullPoint;
var secondLastHullPointRecord;
var secondLastHullPoint;
while (sortedPointRecords.length !== 0) {
currentPointRecord = sortedPointRecords.pop();
currentPoint = currentPointRecord[0];
if (insidePoints.hasOwnProperty(currentPointRecord[0] + "@@" + currentPointRecord[1])) continue;
var correctTurnFound = false;
while (!correctTurnFound) if (hullPointRecords.length < 2) {
hullPointRecords.push(currentPointRecord);
correctTurnFound = true;
} else {
lastHullPointRecord = hullPointRecords.pop();
lastHullPoint = lastHullPointRecord[0];
secondLastHullPointRecord = hullPointRecords.pop();
secondLastHullPoint = secondLastHullPointRecord[0];
var crossProduct = secondLastHullPoint.cross(lastHullPoint, currentPoint);
if (crossProduct < 0) {
hullPointRecords.push(secondLastHullPointRecord);
hullPointRecords.push(lastHullPointRecord);
hullPointRecords.push(currentPointRecord);
correctTurnFound = true;
} else if (crossProduct === 0) {
var THRESHOLD = 1e-10;
var angleBetween = lastHullPoint.angleBetween(secondLastHullPoint, currentPoint);
if (abs$3(angleBetween - 180) < THRESHOLD) {
insidePoints[lastHullPointRecord[0] + "@@" + lastHullPointRecord[1]] = lastHullPoint;
hullPointRecords.push(secondLastHullPointRecord);
} else if (lastHullPoint.equals(currentPoint) || secondLastHullPoint.equals(lastHullPoint)) {
insidePoints[lastHullPointRecord[0] + "@@" + lastHullPointRecord[1]] = lastHullPoint;
hullPointRecords.push(secondLastHullPointRecord);
} else if (abs$3((angleBetween + 1) % 360 - 1) < THRESHOLD) {
hullPointRecords.push(secondLastHullPointRecord);
sortedPointRecords.push(lastHullPointRecord);
}
} else {
insidePoints[lastHullPointRecord[0] + "@@" + lastHullPointRecord[1]] = lastHullPoint;
hullPointRecords.push(secondLastHullPointRecord);
}
}
}
if (hullPointRecords.length > 2) hullPointRecords.pop();
var lowestHullIndex;
var indexOfLowestHullIndexRecord = -1;
n = hullPointRecords.length;
for (i = 0; i < n; i++) {
var currentHullIndex = hullPointRecords[i][1];
if (lowestHullIndex === void 0 || currentHullIndex < lowestHullIndex) {
lowestHullIndex = currentHullIndex;
indexOfLowestHullIndexRecord = i;
}
}
var hullPointRecordsReordered = [];
if (indexOfLowestHullIndexRecord > 0) {
var newFirstChunk = hullPointRecords.slice(indexOfLowestHullIndexRecord);
var newSecondChunk = hullPointRecords.slice(0, indexOfLowestHullIndexRecord);
hullPointRecordsReordered = newFirstChunk.concat(newSecondChunk);
} else hullPointRecordsReordered = hullPointRecords;
var hullPoints = [];
n = hullPointRecordsReordered.length;
for (i = 0; i < n; i++) hullPoints.push(hullPointRecordsReordered[i][0]);
return hullPoints;
}
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/polyline.mjs
const Polyline = function(points) {
if (!(this instanceof Polyline)) return new Polyline(points);
if (typeof points === "string") return new Polyline.parse(points);
this.points = Array.isArray(points) ? points.map(Point) : [];
};
Polyline.parse = function(svgString) {
return new Polyline(parsePoints(svgString));
};
Polyline.fromRect = function(rect$1) {
return new Polyline([
rect$1.topLeft(),
rect$1.topRight(),
rect$1.bottomRight(),
rect$1.bottomLeft(),
rect$1.topLeft()
]);
};
Polyline.prototype = {
type: types.Polyline,
bbox: function() {
var x1 = Infinity;
var x2 = -Infinity;
var y1 = Infinity;
var y2 = -Infinity;
var points = this.points;
var numPoints = points.length;
if (numPoints === 0) return null;
for (var i = 0; i < numPoints; i++) {
var point$1 = points[i];
var x = point$1.x;
var y = point$1.y;
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
}
return new Rect(x1, y1, x2 - x1, y2 - y1);
},
clone: function() {
return new Polyline(clonePoints(this.points));
},
closestPoint: function(p) {
var cpLength = this.closestPointLength(p);
return this.pointAtLength(cpLength);
},
closestPointLength: function(p) {
var points = this.lengthPoints();
var numPoints = points.length;
if (numPoints === 0) return 0;
if (numPoints === 1) return 0;
var cpLength;
var minSqrDistance = Infinity;
var length$1 = 0;
var n = numPoints - 1;
for (var i = 0; i < n; i++) {
var line$2 = new Line(points[i], points[i + 1]);
var lineLength = line$2.length();
var cpNormalizedLength = line$2.closestPointNormalizedLength(p);
var cp = line$2.pointAt(cpNormalizedLength);
var sqrDistance = cp.squaredDistance(p);
if (sqrDistance < minSqrDistance) {
minSqrDistance = sqrDistance;
cpLength = length$1 + cpNormalizedLength * lineLength;
}
length$1 += lineLength;
}
return cpLength;
},
closestPointNormalizedLength: function(p) {
var cpLength = this.closestPointLength(p);
if (cpLength === 0) return 0;
var length$1 = this.length();
if (length$1 === 0) return 0;
return cpLength / length$1;
},
closestPointTangent: function(p) {
var cpLength = this.closestPointLength(p);
return this.tangentAtLength(cpLength);
},
containsPoint: function(p) {
var points = this.points;
var numPoints = points.length;
if (numPoints === 0) return false;
var x = p.x;
var y = p.y;
var startIndex = numPoints - 1;
var endIndex = 0;
var numIntersections = 0;
var segment = new Line();
var ray = new Line();
var rayEnd = new Point();
for (; endIndex < numPoints; endIndex++) {
var start = points[startIndex];
var end = points[endIndex];
if (p.equals(start)) return true;
segment.start = start;
segment.end = end;
if (segment.containsPoint(p)) return true;
if (y <= start.y && y > end.y || y > start.y && y <= end.y) {
var xDifference = start.x - x > end.x - x ? start.x - x : end.x - x;
if (xDifference >= 0) {
rayEnd.x = x + xDifference;
rayEnd.y = y;
ray.start = p;
ray.end = rayEnd;
if (segment.intersect(ray)) numIntersections++;
}
}
startIndex = endIndex;
}
return numIntersections % 2 === 1;
},
close: function() {
const { start, end, points } = this;
if (start && end && !start.equals(end)) points.push(start.clone());
return this;
},
lengthPoints: function() {
return this.points;
},
convexHull: function() {
return new Polyline(convexHull(this.points));
},
equals: function(p) {
if (!p) return false;
var points = this.points;
var otherPoints = p.points;
var numPoints = points.length;
if (otherPoints.length !== numPoints) return false;
for (var i = 0; i < numPoints; i++) {
var point$1 = points[i];
var otherPoint = p.points[i];
if (!point$1.equals(otherPoint)) return false;
}
return true;
},
intersectionWithLine: function(l) {
var line$2 = new Line(l);
var intersections = [];
var points = this.lengthPoints();
var l2 = new Line();
for (var i = 0, n = points.length - 1; i < n; i++) {
l2.start = points[i];
l2.end = points[i + 1];
var int = line$2.intersectionWithLine(l2);
if (int) intersections.push(int[0]);
}
return intersections.length > 0 ? intersections : null;
},
isDifferentiable: function() {
var points = this.points;
var numPoints = points.length;
if (numPoints === 0) return false;
var line$2 = new Line();
var n = numPoints - 1;
for (var i = 0; i < n; i++) {
line$2.start = points[i];
line$2.end = points[i + 1];
if (line$2.isDifferentiable()) return true;
}
return false;
},
length: function() {
var points = this.lengthPoints();
var numPoints = points.length;
if (numPoints === 0) return 0;
var length$1 = 0;
var n = numPoints - 1;
for (var i = 0; i < n; i++) length$1 += points[i].distance(points[i + 1]);
return length$1;
},
pointAt: function(ratio) {
var points = this.lengthPoints();
var numPoints = points.length;
if (numPoints === 0) return null;
if (numPoints === 1) return points[0].clone();
if (ratio <= 0) return points[0].clone();
if (ratio >= 1) return points[numPoints - 1].clone();
var polylineLength = this.length();
var length$1 = polylineLength * ratio;
return this.pointAtLength(length$1);
},
pointAtLength: function(length$1) {
var points = this.lengthPoints();
var numPoints = points.length;
if (numPoints === 0) return null;
if (numPoints === 1) return points[0].clone();
var fromStart = true;
if (length$1 < 0) {
fromStart = false;
length$1 = -length$1;
}
var l = 0;
var n = numPoints - 1;
for (var i = 0; i < n; i++) {
var index = fromStart ? i : n - 1 - i;
var a = points[index];
var b = points[index + 1];
var line$2 = new Line(a, b);
var d = a.distance(b);
if (length$1 <= l + d) return line$2.pointAtLength((fromStart ? 1 : -1) * (length$1 - l));
l += d;
}
var lastPoint = fromStart ? points[numPoints - 1] : points[0];
return lastPoint.clone();
},
round: function(precision) {
var points = this.points;
var numPoints = points.length;
for (var i = 0; i < numPoints; i++) points[i].round(precision);
return this;
},
scale: function(sx, sy, origin) {
var points = this.points;
var numPoints = points.length;
for (var i = 0; i < numPoints; i++) points[i].scale(sx, sy, origin);
return this;
},
simplify: function(opt = {}) {
const points = this.points;
if (points.length < 3) return this;
const threshold = opt.threshold || 1e-10;
let currentIndex = 0;
while (points[currentIndex + 2]) {
const firstIndex = currentIndex;
const middleIndex = currentIndex + 1;
const lastIndex = currentIndex + 2;
const firstPoint = points[firstIndex];
const middlePoint = points[middleIndex];
const lastPoint = points[lastIndex];
const chord = new Line(firstPoint, lastPoint);
const closestPoint = chord.closestPoint(middlePoint);
const closestPointDistance = closestPoint.distance(middlePoint);
if (closestPointDistance <= threshold) points.splice(middleIndex, 1);
else currentIndex += 1;
}
return this;
},
tangentAt: function(ratio) {
var points = this.lengthPoints();
var numPoints = points.length;
if (numPoints === 0) return null;
if (numPoints === 1) return null;
if (ratio < 0) ratio = 0;
if (ratio > 1) ratio = 1;
var polylineLength = this.length();
var length$1 = polylineLength * ratio;
return this.tangentAtLength(length$1);
},
tangentAtLength: function(length$1) {
var points = this.lengthPoints();
var numPoints = points.length;
if (numPoints === 0) return null;
if (numPoints === 1) return null;
var fromStart = true;
if (length$1 < 0) {
fromStart = false;
length$1 = -length$1;
}
var lastValidLine;
var l = 0;
var n = numPoints - 1;
for (var i = 0; i < n; i++) {
var index = fromStart ? i : n - 1 - i;
var a = points[index];
var b = points[index + 1];
var line$2 = new Line(a, b);
var d = a.distance(b);
if (line$2.isDifferentiable()) {
if (length$1 <= l + d) return line$2.tangentAtLength((fromStart ? 1 : -1) * (length$1 - l));
lastValidLine = line$2;
}
l += d;
}
if (lastValidLine) {
var ratio = fromStart ? 1 : 0;
return lastValidLine.tangentAt(ratio);
}
return null;
},
toString: function() {
return this.points + "";
},
translate: function(tx, ty) {
var points = this.points;
var numPoints = points.length;
for (var i = 0; i < numPoints; i++) points[i].translate(tx, ty);
return this;
},
serialize: function() {
var points = this.points;
var numPoints = points.length;
if (numPoints === 0) return "";
var output = "";
for (var i = 0; i < numPoints; i++) {
var point$1 = points[i];
output += point$1.x + "," + point$1.y + " ";
}
return output.trim();
}
};
Object.defineProperty(Polyline.prototype, "start", {
configurable: true,
enumerable: true,
get: function() {
var points = this.points;
var numPoints = points.length;
if (numPoints === 0) return null;
return this.points[0];
}
});
Object.defineProperty(Polyline.prototype, "end", {
configurable: true,
enumerable: true,
get: function() {
var points = this.points;
var numPoints = points.length;
if (numPoints === 0) return null;
return this.points[numPoints - 1];
}
});
//#endregion
//#region ../../node_modules/.pnpm/@joint+core@4.1.3/node_modules/@joint/core/src/g/curve.mjs
const { abs, sqrt, min, max, pow } = Math;
const Curve = function(p1, p2, p3, p4) {
if (!(this instanceof Curve)) return new Curve(p1, p2, p3, p4);
if (p1 instanceof Curve) return new Curve(p1.start, p1.controlPoint1, p1.controlPoint2, p1.end);
this.start = new Point(p1);
this.controlPoint1 = new Point(p2);
this.controlPoint2 = new Point(p3);
this.end = new Point(p4);
};
Curve.throughPoints = (function() {
function getCurveControlPoints(knots) {
var firstControlPoints = [];
var secondControlPoints = [];
var n = knots.length - 1;
var i;
if (n == 1) {
firstControlPoints[0] = new Point((2 * knots[0].x + knots[1].x) / 3, (2 * knots[0].y + knots[1].y) / 3);
secondControlPoints[0] = new Point(2 * firstControlPoints[0].x - knots[0].x, 2 * firstControlPoints[0].y - knots[0].y);
return [firstControlPoints, secondControlPoints];
}
var rhs = [];
for (i = 1; i < n - 1; i++) rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;
rhs[0] = knots[0].x + 2 * knots[1].x;
rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x) / 2;
var x = getFirstControlPoints(rhs);
for (i = 1; i < n - 1; ++i) rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;
rhs[0] = knots[0].y + 2 * knots[1].y;
rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y) / 2;
var y = getFirstControlPoints(rhs);
for (i = 0; i < n; i++) {
firstControlPoints.push(new Point(x[i], y[i]));
if (i < n - 1) secondControlPoints.push(new Point(2 * knots[i + 1].x - x[i + 1], 2 * knots[i + 1].y - y[i + 1]));
else secondControlPoints.push(new Point((knots[n].x + x[n - 1]) / 2, (knots[n].y + y[n - 1]) / 2));
}
return [firstControlPoints, secondControlPoints];
}
function getFirstControlPoints(rhs) {
var n = rhs.length;
var x = [];
var tmp = [];
var b = 2;
x[0] = rhs[0] / b;
for (var i = 1; i < n; i++) {
tmp[i] = 1 / b;
b = (i < n - 1 ? 4 : 3.5) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
for (i = 1; i < n; i++) x[n - i - 1] -= tmp[n - i] * x[n - i];
return x;
}
return function(points) {
if (!points || Array.isArray(points) && points.length < 2) throw new Error("At least 2 points are required");
var controlPoints = getCurveControlPoints(points);
var curves = [];
var n = controlPoints[0].length;
for (var i = 0; i < n; i++) {
var controlPoint1 = new Point(controlPoints[0][i].x, controlPoints[0][i].y);
var controlPoint2 = new Point(controlPoints[1][i].x, controlPoints[1][i].y);
curves.push(new Curve(points[i], controlPoint1, controlPoint2, points[i + 1]));
}
return curves;
};
})();
Curve.prototype = {
type: types.Curve,
bbox: function() {
var start = this.start;
var controlPoint1 = this.controlPoint1;
var controlPoint2 = this.controlPoint2;
var end = this.end;
var x0 = start.x;
var y0 = start.y;
var x1 = controlPoint1.x;
var y1 = controlPoint1.y;
var x2 = controlPoint2.x;
var y2 = controlPoint2.y;
var x3 = end.x;
var y3 = end.y;
var points = new Array();
var tvalues = new Array();
var bounds = [new Array(), new Array()];
var a, b, c, t;
var t1, t2;
var b2ac, sqrtb2ac;
for (var i = 0; i < 2; ++i) {
if (i === 0) {
b = 6 * x0 - 12 * x1 + 6 * x2;
a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
c = 3 * x1 - 3 * x0;
} else {
b = 6 * y0 - 12 * y1 + 6 * y2;
a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
c = 3 * y1 - 3 * y0;
}
if (abs(a) < 1e-12) {
if (abs(b) < 1e-12) continue;
t = -c / b;
if (0 < t && t < 1) tvalues.push(t);
continue;
}
b2ac = b * b - 4 * c * a;
sqrtb2ac = sqrt(b2ac);
if (b2ac < 0) continue;
t1 = (-b + sqrtb2ac) / (2 * a);
if (0 < t1 && t1 < 1) tvalues.push(t1);
t2 = (-b - sqrtb2ac) / (2 * a);
if (0 < t2 && t2 < 1) tvalues.push(t2);
}
var j = tvalues.length;
var jlen = j;
var mt;
var x, y;
while (j--) {
t = tvalues[j];
mt = 1 - t;
x = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3;
bounds[0][j] = x;
y = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3;
bounds[1][j] = y;
points[j] = {
X: x,
Y: y
};
}
tvalues[jlen] = 0;
tvalues[jlen + 1] = 1;
points[jlen] = {
X: x0,
Y: y0
};
points[jlen + 1] = {
X: x3,
Y: y3
};
bounds[0][jlen] = x0;
bounds[1][jlen] = y0;
bounds[0][jlen + 1] = x3;
bounds[1][jlen + 1] = y3;
tvalues.length = jlen + 2;
bounds[0].length = jlen + 2;
bounds[1].length = jlen + 2;
points.length = jlen + 2;
var left$3 = min.apply(null, bounds[0]);
var top$3 = min.apply(null, bounds[1]);
var right$3 = max.apply(null, bounds[0]);
var bottom$3 = max.apply(null, bounds[1]);
return new Rect(left$3, top$3, right$3 - left$3, bottom$3 - top$3);
},
clone: function() {
return new Curve(this.start, this.controlPoint1, this.controlPoint2, this.end);
},
closestPoint: function(p, opt) {
return this.pointAtT(this.closestPointT(p, opt));
},
closestPointLength: function(p, opt) {
opt = opt || {};
var precision = opt.precision === void 0 ? this.PRECISION : opt.precision;
var subdivisions = opt.subdivisions === void 0 ? this.getSubdivisions({ precision }) : opt.subdivisions;
var localOpt = {
precision,
subdivisions
};
return this.lengthAtT(this.closestPointT(p, localOpt), localOpt);
},
closestPointNormalizedLength: function(p, opt) {
opt = opt || {};
var precision = opt.precision === void 0 ? this.PRECISION : opt.precision;
var subdivisions = opt.subdivisions === void 0 ? this.getSubdivisions({ precision }) : opt.subdivisions;
var localOpt = {
precision,
subdivisions
};
var cpLength = this.closestPointLength(p, localOpt);
if (!cpLength) return 0;
var length$1 = this.length(localOpt);
if (length$1 === 0) return 0;
return cpLength / length$1;
},
closestPointT: function(p, opt) {
opt = opt || {};
var precision = opt.precision === void 0 ? this.PRECISION : opt.precision;
var subdivisions = opt.subdivisions === void 0 ? this.getSubdivisions({ precision }) : opt.subdivisions;
var investigatedSubdivision;
var investigatedSubdivisionStartT;
var investigatedSubdivisionEndT;
var distFromStart;
var distFromEnd;
var chordLength;
var minSumDist;
var n = subdivisions.length;
var subdivisionSize = n ? 1 / n : 0;
for (var i = 0; i < n; i++) {
var currentSubdivision = subdivisions[i];
var startDist = currentSubdivision.start.distance(p);
var endDist = currentSubdivision.end.distance(p);
var sumDist = startDist + endDist;
if (!minSumDist || sumDist < minSumDist) {
investigatedSubdivision = currentSubdivision;
investigatedSubdivisionStartT = i * subdivisionSize;
investigatedSubdivisionEndT = (i + 1) * subdivisionSize;
distFromStart = startDist;
distFromEnd = endDist;
chordLength = currentSubdivision.start.distance(currentSubdivision.end);
mi