ixfx
Version:
A framework for programming interactivity
1,782 lines (1,707 loc) • 118 kB
JavaScript
import {
fromNumbers as fromNumbers2,
fromPoints
} from "./chunk-425CNZZO.js";
import {
linearSpace
} from "./chunk-ARAXT7VF.js";
import {
mutable
} from "./chunk-BMX5N5CN.js";
import {
Empty,
angleRadian,
bbox,
bezier_exports,
center,
circleCircle,
circleRect,
clampMagnitude,
clampMagnitude2,
degreeArc,
degreeToRadian,
degreesSum,
distance,
distanceCenter,
distanceFromCenter,
distanceFromExterior,
distanceFromExterior2,
divide,
dotProduct,
dotProduct2,
fromCartesian,
fromNumbers,
fromTopLeft,
getPointParameter,
getPointParameter2,
getRectPositioned,
guard,
guard2,
guard3,
guard4,
guardDim,
guardPositioned,
guardPositioned2,
interpolate,
intersectionLine,
intersections,
intersectsPoint,
isCircle,
isCirclePositioned,
isEmpty,
isEmpty2,
isEqual,
isEqual2,
isIntersecting,
isLine,
isNaN,
isPlaceholder,
isPlaceholder2,
isPoint,
isPoint3d,
isPolarCoord,
isPolyLine,
isPositioned,
isPositioned2,
isQuadraticBezier,
isRect,
isRectPositioned,
length,
maxFromCorners,
multiply,
multiplyScalar,
normalise,
normalise2,
normaliseByRect,
pointAtDistance,
point_exports,
polar_exports,
project,
radianArc,
radianInvert,
radianToDegree,
radiansFromAxisX,
radiansSum,
reduce2 as reduce,
reverse,
rotate,
subtract,
sum2 as sum,
toCartesian,
toPoint,
toString,
toString2
} from "./chunk-R4JIRHLR.js";
import {
minFast,
minIndex
} from "./chunk-YG33FJI6.js";
import {
sortByNumericProperty
} from "./chunk-45M4HUXQ.js";
import {
zipKeyValue
} from "./chunk-KVLT2D4E.js";
import {
randomElement
} from "./chunk-LVLPUJZY.js";
import {
scale,
toRgb8bit
} from "./chunk-DLFRRV7R.js";
import {
clampIndex
} from "./chunk-QAEJS6HO.js";
import {
defaultRandom
} from "./chunk-5VWJ6TUI.js";
import {
throwIntegerTest,
throwNumberTest
} from "./chunk-UC4AQMTL.js";
import {
__export
} from "./chunk-L5EJU35C.js";
// src/geometry/index.ts
var geometry_exports = {};
__export(geometry_exports, {
Arcs: () => arc_exports,
Beziers: () => bezier_exports,
Circles: () => circle_exports,
Compound: () => CompoundPath_exports,
Convolve2d: () => Convolve2d_exports,
CurveSimplification: () => CurveSimplification_exports,
Ellipses: () => Ellipse_exports,
Grids: () => grid_exports,
Layouts: () => Layout_exports,
Lines: () => line_exports,
Paths: () => path_exports,
Points: () => point_exports,
Polar: () => polar_exports,
QuadTree: () => QuadTree_exports,
Rects: () => rect_exports,
Scaler: () => Scaler_exports,
Shapes: () => shape_exports,
SurfacePoints: () => SurfacePoints_exports,
Triangles: () => triangle_exports,
Vectors: () => Vector_exports,
Waypoints: () => Waypoint_exports,
degreeArc: () => degreeArc,
degreeToRadian: () => degreeToRadian,
degreesSum: () => degreesSum,
radianArc: () => radianArc,
radianInvert: () => radianInvert,
radianToDegree: () => radianToDegree,
radiansFromAxisX: () => radiansFromAxisX,
radiansSum: () => radiansSum
});
// src/geometry/Waypoint.ts
var Waypoint_exports = {};
__export(Waypoint_exports, {
fromPoints: () => fromPoints2,
init: () => init
});
// src/geometry/line/JoinPointsToLines.ts
var joinPointsToLines = (...points) => {
const lines = [];
let start = points[0];
for (let index = 1; index < points.length; index++) {
lines.push(fromPoints(start, points[index]));
start = points[index];
}
return lines;
};
// src/geometry/line/Angles.ts
var directionVector = (line) => ({
x: line.b.x - line.a.x,
y: line.b.y - line.a.y
});
var directionVectorNormalised = (line) => {
const l = length(line);
const v = directionVector(line);
return {
x: v.x / l,
y: v.y / l
};
};
var parallel = (line, distance3) => {
const dv = directionVector(line);
const dvn = directionVectorNormalised(line);
const a = {
x: line.a.x - dvn.y * distance3,
y: line.a.y + dvn.x * distance3
};
return {
a,
b: {
x: a.x + dv.x,
y: a.y + dv.y
}
};
};
var perpendicularPoint = (line, distance3, amount = 0) => {
const origin = interpolate(amount, line);
const dvn = directionVectorNormalised(line);
return {
x: origin.x - dvn.y * distance3,
y: origin.y + dvn.x * distance3
};
};
// src/geometry/line/Midpoint.ts
var midpoint = (aOrLine, pointB) => {
const [a, b] = getPointParameter2(aOrLine, pointB);
return interpolate(0.5, a, b);
};
// src/geometry/line/index.ts
var line_exports = {};
__export(line_exports, {
Empty: () => Empty2,
Placeholder: () => Placeholder,
angleRadian: () => angleRadian2,
apply: () => apply,
asPoints: () => asPoints,
bbox: () => bbox2,
distance: () => distance2,
distanceSingleLine: () => distanceSingleLine,
divide: () => divide2,
extendFromA: () => extendFromA,
fromFlatArray: () => fromFlatArray,
fromNumbers: () => fromNumbers2,
fromPivot: () => fromPivot,
fromPoints: () => fromPoints,
fromPointsToPath: () => fromPointsToPath,
getPointParameter: () => getPointParameter2,
guard: () => guard4,
interpolate: () => interpolate,
isEmpty: () => isEmpty3,
isEqual: () => isEqual3,
isLine: () => isLine,
isPlaceholder: () => isPlaceholder3,
isPolyLine: () => isPolyLine,
joinPointsToLines: () => joinPointsToLines,
length: () => length,
midpoint: () => midpoint,
multiply: () => multiply2,
nearest: () => nearest,
normaliseByRect: () => normaliseByRect2,
parallel: () => parallel,
perpendicularPoint: () => perpendicularPoint,
pointAtDistance: () => pointAtDistance,
pointAtX: () => pointAtX,
pointsOf: () => pointsOf,
relativePosition: () => relativePosition,
reverse: () => reverse,
rotate: () => rotate2,
scaleFromMidpoint: () => scaleFromMidpoint,
slope: () => slope,
subtract: () => subtract2,
sum: () => sum2,
toFlatArray: () => toFlatArray,
toPath: () => toPath,
toString: () => toString3,
toSvgString: () => toSvgString,
withinRange: () => withinRange
});
// src/geometry/line/Nearest.ts
var nearest = (line, point2) => {
const n = (line2) => {
const { a, b } = line2;
const atob = { x: b.x - a.x, y: b.y - a.y };
const atop = { x: point2.x - a.x, y: point2.y - a.y };
const length4 = atob.x * atob.x + atob.y * atob.y;
let dot = atop.x * atob.x + atop.y * atob.y;
const t = Math.min(1, Math.max(0, dot / length4));
dot = (b.x - a.x) * (point2.y - a.y) - (b.y - a.y) * (point2.x - a.x);
return { x: a.x + atob.x * t, y: a.y + atob.y * t };
};
if (Array.isArray(line)) {
const pts = line.map((l) => n(l));
const dists = pts.map((p) => distance(p, point2));
return Object.freeze(pts[minIndex(...dists)]);
} else {
return Object.freeze(n(line));
}
};
// src/geometry/line/DistanceSingleLine.ts
var distanceSingleLine = (line, point2) => {
guard4(line, `line`);
guard(point2, `point`);
if (length(line) === 0) {
return length(line.a, point2);
}
const near = nearest(line, point2);
return length(near, point2);
};
// src/geometry/line/Bbox.ts
var bbox2 = (line) => bbox(line.a, line.b);
// src/geometry/line/Divide.ts
var divide2 = (line, point2) => Object.freeze({
...line,
a: divide(line.a, point2),
b: divide(line.b, point2)
});
// src/geometry/line/FromFlatArray.ts
var fromFlatArray = (array) => {
if (!Array.isArray(array)) throw new Error(`arr parameter is not an array`);
if (array.length !== 4) throw new Error(`array is expected to have length four`);
return fromNumbers2(array[0], array[1], array[2], array[3]);
};
// src/geometry/line/FromPivot.ts
var fromPivot = (origin = { x: 0.5, y: 0.5 }, length4 = 1, angleRadian3 = 0, balance = 0.5) => {
const left = length4 * balance;
const right = length4 * (1 - balance);
const a = toCartesian(left, radianInvert(angleRadian3), origin);
const b = toCartesian(right, angleRadian3, origin);
return Object.freeze({
a,
b
});
};
// src/geometry/line/FromPointsToPath.ts
var fromPointsToPath = (a, b) => toPath(fromPoints(a, b));
// src/geometry/line/IsEqual.ts
var isEqual3 = (a, b) => isEqual(a.a, b.a) && isEqual(a.b, b.b);
// src/geometry/line/Multiply.ts
var multiply2 = (line, point2) => Object.freeze({
...line,
a: multiply(line.a, point2),
b: multiply(line.b, point2)
});
// src/geometry/line/RelativePosition.ts
var relativePosition = (line, pt) => {
const fromStart = distance(line.a, pt);
const total = length(line);
return fromStart / total;
};
// src/geometry/line/Rotate.ts
var rotate2 = (line, amountRadian, origin) => {
if (amountRadian === void 0 || amountRadian === 0) return line;
if (origin === void 0) origin = 0.5;
if (typeof origin === `number`) {
origin = interpolate(origin, line.a, line.b);
}
return Object.freeze({
...line,
a: rotate(line.a, amountRadian, origin),
b: rotate(line.b, amountRadian, origin)
});
};
// src/geometry/line/Subtract.ts
var subtract2 = (line, point2) => Object.freeze({
...line,
a: subtract(line.a, point2),
b: subtract(line.b, point2)
});
// src/geometry/line/Sum.ts
var sum2 = (line, point2) => Object.freeze({
...line,
a: sum(line.a, point2),
b: sum(line.b, point2)
});
// src/geometry/line/ToString.ts
function toString3(a, b) {
if (isLine(a)) {
guard4(a, `a`);
b = a.b;
a = a.a;
} else if (b === void 0) throw new Error(`Expect second point if first is a point`);
return toString2(a) + `-` + toString2(b);
}
// src/geometry/line/index.ts
var Empty2 = Object.freeze({
a: Object.freeze({ x: 0, y: 0 }),
b: Object.freeze({ x: 0, y: 0 })
});
var Placeholder = Object.freeze({
a: Object.freeze({ x: Number.NaN, y: Number.NaN }),
b: Object.freeze({ x: Number.NaN, y: Number.NaN })
});
var isEmpty3 = (l) => isEmpty(l.a) && isEmpty(l.b);
var isPlaceholder3 = (l) => isPlaceholder(l.a) && isPlaceholder(l.b);
var apply = (line, fn) => Object.freeze(
{
...line,
a: fn(line.a),
b: fn(line.b)
}
);
var angleRadian2 = (lineOrPoint, b) => {
let a;
if (isLine(lineOrPoint)) {
a = lineOrPoint.a;
b = lineOrPoint.b;
} else {
a = lineOrPoint;
if (b === void 0) throw new Error(`b point must be provided`);
}
return Math.atan2(b.y - a.y, b.x - a.x);
};
var normaliseByRect2 = (line, width, height4) => Object.freeze({
...line,
a: normaliseByRect(line.a, width, height4),
b: normaliseByRect(line.b, width, height4)
});
var withinRange = (line, point2, maxRange) => {
const calculatedDistance = distance2(line, point2);
return calculatedDistance <= maxRange;
};
var slope = (lineOrPoint, b) => {
let a;
if (isLine(lineOrPoint)) {
a = lineOrPoint.a;
b = lineOrPoint.b;
} else {
a = lineOrPoint;
if (b === void 0) throw new Error(`b parameter required`);
}
if (b === void 0) {
throw new TypeError(`Second point missing`);
} else {
return (b.y - a.y) / (b.x - a.x);
}
};
var scaleFromMidpoint = (line, factor) => {
const a = interpolate(factor / 2, line);
const b = interpolate(0.5 + factor / 2, line);
return { a, b };
};
var pointAtX = (line, x) => {
const y = line.a.y + (x - line.a.x) * slope(line);
return Object.freeze({ x, y });
};
var extendFromA = (line, distance3) => {
const calculatedLength = length(line);
return Object.freeze({
...line,
a: line.a,
b: Object.freeze({
x: line.b.x + (line.b.x - line.a.x) / calculatedLength * distance3,
y: line.b.y + (line.b.y - line.a.y) / calculatedLength * distance3
})
});
};
function* pointsOf(line) {
const { a, b } = line;
let x0 = Math.floor(a.x);
let y0 = Math.floor(a.y);
const x1 = Math.floor(b.x);
const y1 = Math.floor(b.y);
const dx = Math.abs(x1 - x0);
const dy = -Math.abs(y1 - y0);
const sx = x0 < x1 ? 1 : -1;
const sy = y0 < y1 ? 1 : -1;
let err = dx + dy;
while (true) {
yield { x: x0, y: y0 };
if (x0 === x1 && y0 === y1) break;
const e2 = 2 * err;
if (e2 >= dy) {
err += dy;
x0 += sx;
}
if (e2 <= dx) {
err += dx;
y0 += sy;
}
}
}
var distance2 = (line, point2) => {
if (Array.isArray(line)) {
const distances = line.map((l) => distanceSingleLine(l, point2));
return minFast(distances);
} else {
return distanceSingleLine(line, point2);
}
};
var toFlatArray = (a, b) => {
if (isLine(a)) {
return [a.a.x, a.a.y, a.b.x, a.b.y];
} else if (isPoint(a) && isPoint(b)) {
return [a.x, a.y, b.x, b.y];
} else {
throw new Error(`Expected single line parameter, or a and b points`);
}
};
function* asPoints(lines) {
for (const l of lines) {
yield l.a;
yield l.b;
}
}
var toSvgString = (a, b) => [`M${a.x} ${a.y} L ${b.x} ${b.y}`];
// src/geometry/line/ToPath.ts
var toPath = (line) => {
const { a, b } = line;
return Object.freeze({
...line,
length: () => length(a, b),
interpolate: (amount) => interpolate(amount, a, b),
relativePosition: (point2) => relativePosition(line, point2),
bbox: () => bbox2(line),
toString: () => toString3(a, b),
toFlatArray: () => toFlatArray(a, b),
toSvgString: () => toSvgString(a, b),
toPoints: () => [a, b],
rotate: (amountRadian, origin) => toPath(rotate2(line, amountRadian, origin)),
nearest: (point2) => nearest(line, point2),
sum: (point2) => toPath(sum2(line, point2)),
divide: (point2) => toPath(divide2(line, point2)),
multiply: (point2) => toPath(multiply2(line, point2)),
subtract: (point2) => toPath(subtract2(line, point2)),
midpoint: () => midpoint(a, b),
distanceToPoint: (point2) => distanceSingleLine(line, point2),
parallel: (distance3) => parallel(line, distance3),
perpendicularPoint: (distance3, amount) => perpendicularPoint(line, distance3, amount),
slope: () => slope(line),
withinRange: (point2, maxRange) => withinRange(line, point2, maxRange),
isEqual: (otherLine) => isEqual3(line, otherLine),
apply: (fn) => toPath(apply(line, fn)),
kind: `line`
});
};
// src/geometry/Waypoint.ts
var fromPoints2 = (waypoints, opts = {}) => {
const lines = joinPointsToLines(...waypoints);
return init(
lines.map((l) => toPath(l)),
opts
);
};
var init = (paths, opts = {}) => {
const maxDistanceFromLine = opts.maxDistanceFromLine ?? 0.1;
const checkUnordered = (pt) => {
const results = paths.map((p, index) => {
const nearest3 = p.nearest(pt);
const distance3 = distance(pt, nearest3);
const positionRelative = p.relativePosition(nearest3, maxDistanceFromLine);
;
return { positionRelative, path: p, index, nearest: nearest3, distance: distance3, rank: Number.MAX_SAFE_INTEGER };
});
const filtered = results.filter((v) => v.distance <= maxDistanceFromLine);
const sorted = sortByNumericProperty(filtered, `distance`);
for (let rank = 0; rank < sorted.length; rank++) {
sorted[rank].rank = rank;
}
return sorted;
};
return checkUnordered;
};
// src/geometry/Layout.ts
var Layout_exports = {};
__export(Layout_exports, {
CirclePacking: () => CirclePacking_exports
});
// src/geometry/CirclePacking.ts
var CirclePacking_exports = {};
__export(CirclePacking_exports, {
random: () => random2
});
// src/geometry/shape/index.ts
var shape_exports = {};
__export(shape_exports, {
arrow: () => arrow,
center: () => center3,
isIntersecting: () => isIntersecting3,
randomPoint: () => randomPoint3,
starburst: () => starburst
});
// src/geometry/rect/Corners.ts
var corners = (rect, origin) => {
const r = getRectPositioned(rect, origin);
return [
{ x: r.x, y: r.y },
{ x: r.x + r.width, y: r.y },
{ x: r.x + r.width, y: r.y + r.height },
{ x: r.x, y: r.y + r.height }
];
};
// src/geometry/circle/IsContainedBy.ts
var isContainedBy = (a, b, c) => {
const d = distanceCenter(a, b);
if (isCircle(b)) {
return d < Math.abs(a.radius - b.radius);
} else if (isPoint(b)) {
if (c === void 0) {
return d <= a.radius;
} else {
return d < Math.abs(a.radius - c);
}
} else throw new Error(`b parameter is expected to be CirclePositioned or Point`);
};
// src/geometry/circle/Intersecting.ts
var isIntersecting2 = (a, b, c) => {
if (isEqual(a, b)) return true;
if (isContainedBy(a, b, c)) return true;
if (isCircle(b)) {
return circleCircle(a, b);
} else if (isRectPositioned(b)) {
return circleRect(a, b);
} else if (isPoint(b) && c !== void 0) {
return circleCircle(a, { ...b, radius: c });
}
return false;
};
// src/geometry/circle/Random.ts
var piPi = Math.PI * 2;
var randomPoint = (within, opts = {}) => {
const offset2 = isCirclePositioned(within) ? within : { x: 0, y: 0 };
const strategy = opts.strategy ?? `uniform`;
const margin = opts.margin ?? 0;
const radius = within.radius - margin;
const rand = opts.randomSource ?? Math.random;
switch (strategy) {
case `naive`: {
return sum(offset2, toCartesian(rand() * radius, rand() * piPi));
}
case `uniform`: {
return sum(offset2, toCartesian(Math.sqrt(rand()) * radius, rand() * piPi));
}
default: {
throw new Error(`Unknown strategy '${strategy}'. Expects 'uniform' or 'naive'`);
}
}
};
// src/geometry/circle/Center.ts
var center2 = (circle) => {
return isCirclePositioned(circle) ? Object.freeze({ x: circle.x, y: circle.y }) : Object.freeze({ x: circle.radius, y: circle.radius });
};
// src/geometry/rect/Random.ts
var random = (rando) => {
if (rando === void 0) rando = defaultRandom;
return Object.freeze({
x: rando(),
y: rando(),
width: rando(),
height: rando()
});
};
var randomPoint2 = (within, options = {}) => {
const rand = options.randomSource ?? defaultRandom;
const margin = options.margin ?? { x: 0, y: 0 };
const x = rand() * (within.width - margin.x - margin.x);
const y = rand() * (within.height - margin.y - margin.y);
const pos = { x: x + margin.x, y: y + margin.y };
return isPositioned2(within) ? sum(pos, within) : Object.freeze(pos);
};
// src/geometry/shape/index.ts
var isIntersecting3 = (a, b) => {
if (isCirclePositioned(a)) {
return isIntersecting2(a, b);
} else if (isRectPositioned(a)) {
return isIntersecting(a, b);
}
throw new Error(
`a or b are unknown shapes. a: ${JSON.stringify(a)} b: ${JSON.stringify(b)}`
);
};
var randomPoint3 = (shape, opts = {}) => {
if (isCirclePositioned(shape)) {
return randomPoint(shape, opts);
} else if (isRectPositioned(shape)) {
return randomPoint2(shape, opts);
}
throw new Error(`Unknown shape. Only CirclePositioned and RectPositioned are supported.`);
};
var center3 = (shape) => {
if (shape === void 0) {
return Object.freeze({ x: 0.5, y: 0.5 });
} else if (isRect(shape)) {
return center(shape);
} else if (triangle_exports.isTriangle(shape)) {
return triangle_exports.centroid(shape);
} else if (isCircle(shape)) {
return center2(shape);
} else {
throw new Error(`Unknown shape: ${JSON.stringify(shape)}`);
}
};
var starburst = (outerRadius, points = 5, innerRadius, origin = point_exports.Empty, opts) => {
throwIntegerTest(points, `positive`, `points`);
const angle = Math.PI * 2 / points;
const angleHalf = angle / 2;
const initialAngle = opts?.initialAngleRadian ?? -Math.PI / 2;
if (innerRadius === void 0) innerRadius = outerRadius / 2;
let a = initialAngle;
const pts = [];
for (let index = 0; index < points; index++) {
const peak = toCartesian(outerRadius, a, origin);
const left = toCartesian(innerRadius, a - angleHalf, origin);
const right = toCartesian(innerRadius, a + angleHalf, origin);
pts.push(left, peak);
if (index + 1 < points) pts.push(right);
a += angle;
}
return pts;
};
var arrow = (origin, from, opts = {}) => {
const tailLength = opts.tailLength ?? 10;
const tailThickness = opts.tailThickness ?? Math.max(tailLength / 5, 5);
const angleRadian3 = opts.angleRadian ?? 0;
const arrowSize = opts.arrowSize ?? Math.max(tailLength / 5, 15);
const triAngle = Math.PI / 2;
let tri;
let tailPoints;
if (from === `tip`) {
tri = triangle_exports.equilateralFromVertex(origin, arrowSize, triAngle);
tailPoints = corners(
fromTopLeft(
{ x: tri.a.x - tailLength, y: origin.y - tailThickness / 2 },
tailLength,
tailThickness
)
);
} else if (from === `middle`) {
const midX = tailLength + arrowSize / 2;
const midY = tailThickness / 2;
tri = triangle_exports.equilateralFromVertex(
{
x: origin.x + arrowSize * 1.2,
y: origin.y
},
arrowSize,
triAngle
);
tailPoints = corners(
fromTopLeft(
{ x: origin.x - midX, y: origin.y - midY },
tailLength + arrowSize,
tailThickness
)
);
} else {
tailPoints = corners(
fromTopLeft(
{ x: origin.x, y: origin.y - tailThickness / 2 },
tailLength,
tailThickness
)
);
tri = triangle_exports.equilateralFromVertex(
{ x: origin.x + tailLength + arrowSize * 0.7, y: origin.y },
arrowSize,
triAngle
);
}
const arrow2 = point_exports.rotate(
[
tailPoints[0],
tailPoints[1],
tri.a,
tri.b,
tri.c,
tailPoints[2],
tailPoints[3]
],
angleRadian3,
origin
);
return arrow2;
};
// src/geometry/CirclePacking.ts
var random2 = (circles, container, opts = {}) => {
if (!Array.isArray(circles)) throw new Error(`Parameter 'circles' is not an array`);
const attempts = opts.attempts ?? 2e3;
const sorted = sortByNumericProperty(circles, `radius`);
const positionedCircles = [];
const willHit = (b, radius) => positionedCircles.some((v) => isIntersecting2(v, b, radius));
while (sorted.length > 0) {
const circle = sorted.pop();
if (!circle) break;
const randomPointOpts = { ...opts, margin: { x: circle.radius, y: circle.radius } };
for (let index = 0; index < attempts; index++) {
const position = randomPoint3(container, randomPointOpts);
if (!willHit(position, circle.radius)) {
positionedCircles.push(Object.freeze({ ...circle, ...position }));
break;
}
}
}
return positionedCircles;
};
// src/geometry/circle/index.ts
var circle_exports = {};
__export(circle_exports, {
area: () => area,
bbox: () => bbox3,
center: () => center2,
circumference: () => circumference,
distanceCenter: () => distanceCenter,
distanceFromExterior: () => distanceFromExterior,
exteriorIntegerPoints: () => exteriorIntegerPoints,
guard: () => guard2,
guardPositioned: () => guardPositioned,
interiorIntegerPoints: () => interiorIntegerPoints,
interpolate: () => interpolate2,
intersectionLine: () => intersectionLine,
intersections: () => intersections,
isCircle: () => isCircle,
isCirclePositioned: () => isCirclePositioned,
isContainedBy: () => isContainedBy,
isEqual: () => isEqual2,
isIntersecting: () => isIntersecting2,
isNaN: () => isNaN,
isPositioned: () => isPositioned,
length: () => length2,
multiplyScalar: () => multiplyScalar2,
nearest: () => nearest2,
pointOnPerimeter: () => pointOnPerimeter,
randomPoint: () => randomPoint,
toPath: () => toPath2,
toPositioned: () => toPositioned,
toSvg: () => toSvg
});
// src/geometry/circle/Area.ts
var area = (circle) => {
guard2(circle);
return Math.PI * circle.radius * circle.radius;
};
// src/geometry/rect/FromCenter.ts
var fromCenter = (origin, width, height4) => {
guard(origin, `origin`);
guardDim(width, `width`);
guardDim(height4, `height`);
const halfW = width / 2;
const halfH = height4 / 2;
return {
x: origin.x - halfW,
y: origin.y - halfH,
width,
height: height4
};
};
// src/geometry/circle/Bbox.ts
var bbox3 = (circle) => {
return isCirclePositioned(circle) ? fromCenter(circle, circle.radius * 2, circle.radius * 2) : { width: circle.radius * 2, height: circle.radius * 2, x: 0, y: 0 };
};
// src/geometry/circle/ExteriorPoints.ts
function* exteriorIntegerPoints(circle) {
const { x, y, radius } = circle;
let xx = radius;
let yy = 0;
let radiusError = 1 - x;
while (xx >= yy) {
yield { x: xx + x, y: yy + y };
yield { x: yy + x, y: xx + y };
yield { x: -xx + x, y: yy + y };
yield { x: -yy + x, y: xx + y };
yield { x: -xx + x, y: -yy + y };
yield { x: -yy + x, y: -xx + y };
yield { x: xx + x, y: -yy + y };
yield { x: yy + x, y: -xx + y };
yy++;
if (radiusError < 0) {
radiusError += 2 * yy + 1;
} else {
xx--;
radiusError += 2 * (yy - xx + 1);
}
}
}
// src/geometry/circle/InteriorPoints.ts
function* interiorIntegerPoints(circle) {
const xMin = circle.x - circle.radius;
const xMax = circle.x + circle.radius;
const yMin = circle.y - circle.radius;
const yMax = circle.y + circle.radius;
for (let x = xMin; x < xMax; x++) {
for (let y = yMin; y < yMax; y++) {
const r = Math.abs(distance(circle, x, y));
if (r <= circle.radius) yield { x, y };
}
}
}
// src/geometry/circle/Perimeter.ts
var piPi2 = Math.PI * 2;
var nearest2 = (circle, point2) => {
const n = (a) => {
const l = Math.sqrt(Math.pow(point2.x - a.x, 2) + Math.pow(point2.y - a.y, 2));
const x = a.x + a.radius * ((point2.x - a.x) / l);
const y = a.y + a.radius * ((point2.y - a.y) / l);
return { x, y };
};
if (Array.isArray(circle)) {
const pts = circle.map((l) => n(l));
const dists = pts.map((p) => distance(p, point2));
return Object.freeze(pts[minIndex(...dists)]);
} else {
return Object.freeze(n(circle));
}
};
var pointOnPerimeter = (circle, angleRadian3, origin) => {
if (origin === void 0) {
origin = isCirclePositioned(circle) ? circle : { x: 0, y: 0 };
}
return {
x: Math.cos(-angleRadian3) * circle.radius + origin.x,
y: Math.sin(-angleRadian3) * circle.radius + origin.y
};
};
var circumference = (circle) => {
guard2(circle);
return piPi2 * circle.radius;
};
var length2 = (circle) => circumference(circle);
// src/geometry/circle/Interpolate.ts
var piPi3 = Math.PI * 2;
var interpolate2 = (circle, t) => pointOnPerimeter(circle, t * piPi3);
// src/geometry/circle/Multiply.ts
function multiplyScalar2(a, value) {
if (isCirclePositioned(a)) {
const pt = multiplyScalar(a, value);
return Object.freeze({
...a,
...pt,
radius: a.radius * value
});
} else {
return Object.freeze({
...a,
radius: a.radius * value
});
}
}
// src/geometry/circle/Svg.ts
var toSvg = (a, sweep, origin) => {
if (isCircle(a)) {
if (origin !== void 0) {
return toSvgFull(a.radius, origin, sweep);
}
if (isCirclePositioned(a)) {
return toSvgFull(a.radius, a, sweep);
} else throw new Error(`origin parameter needed for non-positioned circle`);
} else {
if (origin === void 0) {
throw new Error(`origin parameter needed`);
} else {
return toSvgFull(a, origin, sweep);
}
}
};
var toSvgFull = (radius, origin, sweep) => {
const { x, y } = origin;
const s = sweep ? `1` : `0`;
return `
M ${x}, ${y}
m -${radius}, 0
a ${radius},${radius} 0 1,${s} ${radius * 2},0
a ${radius},${radius} 0 1,${s} -${radius * 2},0
`.split(`
`);
};
// src/geometry/circle/ToPath.ts
var toPath2 = (circle) => {
guard2(circle);
return {
...circle,
nearest: (point2) => nearest2(circle, point2),
/**
* Returns a relative (0.0-1.0) point on a circle. 0=3 o'clock, 0.25=6 o'clock, 0.5=9 o'clock, 0.75=12 o'clock etc.
* @param {t} Relative (0.0-1.0) point
* @returns {Point} X,y
*/
interpolate: (t) => interpolate2(circle, t),
bbox: () => bbox3(circle),
length: () => circumference(circle),
toSvgString: (sweep = true) => toSvg(circle, sweep),
relativePosition: (_point, _intersectionThreshold) => {
throw new Error(`Not implemented`);
},
distanceToPoint: (_point) => {
throw new Error(`Not implemented`);
},
kind: `circular`
};
};
// src/geometry/circle/ToPositioned.ts
var toPositioned = (circle, defaultPositionOrX, y) => {
if (isCirclePositioned(circle)) return circle;
const pt = getPointParameter(defaultPositionOrX, y);
return Object.freeze({
...circle,
...pt
});
};
// src/geometry/rect/index.ts
var rect_exports = {};
__export(rect_exports, {
Empty: () => Empty3,
EmptyPositioned: () => EmptyPositioned,
Placeholder: () => Placeholder2,
PlaceholderPositioned: () => PlaceholderPositioned,
applyDim: () => applyDim,
applyFields: () => applyFields,
applyMerge: () => applyMerge,
applyScalar: () => applyScalar,
area: () => area2,
cardinal: () => cardinal,
center: () => center,
corners: () => corners,
distanceFromCenter: () => distanceFromCenter,
distanceFromExterior: () => distanceFromExterior2,
divide: () => divide3,
divideDim: () => divideDim,
divideScalar: () => divideScalar,
dividerByLargestDimension: () => dividerByLargestDimension,
edges: () => edges,
encompass: () => encompass,
fromCenter: () => fromCenter,
fromElement: () => fromElement,
fromNumbers: () => fromNumbers3,
fromTopLeft: () => fromTopLeft,
getEdgeX: () => getEdgeX,
getEdgeY: () => getEdgeY,
getRectPositioned: () => getRectPositioned,
getRectPositionedParameter: () => getRectPositionedParameter,
guard: () => guard3,
guardDim: () => guardDim,
guardPositioned: () => guardPositioned2,
intersectsPoint: () => intersectsPoint,
isEmpty: () => isEmpty2,
isEqual: () => isEqual4,
isEqualSize: () => isEqualSize,
isIntersecting: () => isIntersecting,
isPlaceholder: () => isPlaceholder2,
isPositioned: () => isPositioned2,
isRect: () => isRect,
isRectPositioned: () => isRectPositioned,
lengths: () => lengths,
maxFromCorners: () => maxFromCorners,
multiply: () => multiply3,
multiplyDim: () => multiplyDim,
multiplyScalar: () => multiplyScalar3,
nearestInternal: () => nearestInternal,
perimeter: () => perimeter,
random: () => random,
randomPoint: () => randomPoint2,
subtract: () => subtract3,
subtractOffset: () => subtractOffset,
subtractSize: () => subtractSize,
sum: () => sum3,
sumOffset: () => sumOffset,
toArray: () => toArray
});
// src/geometry/rect/Area.ts
var area2 = (rect) => {
guard3(rect);
return rect.height * rect.width;
};
// src/geometry/rect/Apply.ts
function applyFields(op, rectOrWidth, heightValue) {
let width = typeof rectOrWidth === `number` ? rectOrWidth : rectOrWidth.width;
let height4 = typeof rectOrWidth === `number` ? heightValue : rectOrWidth.height;
if (width === void 0) throw new Error(`Param 'width' undefined`);
if (height4 === void 0) throw new Error(`Param 'height' undefined`);
width = op(width, `width`);
height4 = op(height4, `height`);
if (typeof rectOrWidth === `object`) {
if (isPositioned2(rectOrWidth)) {
const x = op(rectOrWidth.x, `x`);
const y = op(rectOrWidth.y, `y`);
return { ...rectOrWidth, width, height: height4, x, y };
} else {
return {
...rectOrWidth,
width,
height: height4
};
}
}
return { width, height: height4 };
}
function applyMerge(op, a, b, c) {
guard3(a, `a`);
if (isRect(b)) {
return isRectPositioned(a) ? Object.freeze({
...a,
x: op(a.x, b.width),
y: op(a.y, b.height),
width: op(a.width, b.width),
height: op(a.height, b.height)
}) : Object.freeze({
...a,
width: op(a.width, b.width),
height: op(a.height, b.height)
});
} else {
if (typeof b !== `number`) {
throw new TypeError(
`Expected second parameter of type Rect or number. Got ${JSON.stringify(
b
)}`
);
}
if (typeof c !== `number`) throw new Error(`Expected third param as height. Got ${JSON.stringify(c)}`);
return isRectPositioned(a) ? Object.freeze({
...a,
x: op(a.x, b),
y: op(a.y, c),
width: op(a.width, b),
height: op(a.height, c)
}) : Object.freeze({
...a,
width: op(a.width, b),
height: op(a.height, c)
});
}
}
function applyScalar(op, rect, parameter) {
return isPositioned2(rect) ? Object.freeze({
...rect,
x: op(rect.x, parameter),
y: op(rect.y, parameter),
width: op(rect.width, parameter),
height: op(rect.height, parameter)
}) : Object.freeze({
...rect,
width: op(rect.width, parameter),
height: op(rect.height, parameter)
});
}
function applyDim(op, rect, parameter) {
return Object.freeze({
...rect,
width: op(rect.width, parameter),
height: op(rect.height, parameter)
});
}
// src/geometry/rect/Cardinal.ts
var cardinal = (rect, card) => {
const { x, y, width, height: height4 } = rect;
switch (card) {
case `nw`: {
return Object.freeze({ x, y });
}
case `n`: {
return Object.freeze({
x: x + width / 2,
y
});
}
case `ne`: {
return Object.freeze({
x: x + width,
y
});
}
case `sw`: {
return Object.freeze({ x, y: y + height4 });
}
case `s`: {
return Object.freeze({
x: x + width / 2,
y: y + height4
});
}
case `se`: {
return Object.freeze({
x: x + width,
y: y + height4
});
}
case `w`: {
return Object.freeze({ x, y: y + height4 / 2 });
}
case `e`: {
return Object.freeze({ x: x + width, y: y + height4 / 2 });
}
case `center`: {
return Object.freeze({
x: x + width / 2,
y: y + height4 / 2
});
}
default: {
throw new Error(`Unknown direction: ${card}`);
}
}
};
// src/geometry/rect/Divide.ts
var divideOp = (a, b) => a / b;
function divide3(a, b, c) {
return applyMerge(divideOp, a, b, c);
}
function divideScalar(rect, amount) {
return applyScalar(divideOp, rect, amount);
}
function divideDim(rect, amount) {
return applyDim(divideOp, rect, amount);
}
// src/geometry/rect/Edges.ts
var edges = (rect, origin) => {
const c = corners(rect, origin);
return joinPointsToLines(...c, c[0]);
};
var getEdgeX = (rect, edge) => {
guard3(rect);
switch (edge) {
case `top`: {
return isPoint(rect) ? rect.x : 0;
}
case `bottom`: {
return isPoint(rect) ? rect.x : 0;
}
case `left`: {
return isPoint(rect) ? rect.y : 0;
}
case `right`: {
return isPoint(rect) ? rect.x + rect.width : rect.width;
}
}
};
var getEdgeY = (rect, edge) => {
guard3(rect);
switch (edge) {
case `top`: {
return isPoint(rect) ? rect.y : 0;
}
case `bottom`: {
return isPoint(rect) ? rect.y + rect.height : rect.height;
}
case `left`: {
return isPoint(rect) ? rect.y : 0;
}
case `right`: {
return isPoint(rect) ? rect.y : 0;
}
}
};
// src/geometry/rect/Empty.ts
var Empty3 = Object.freeze({ width: 0, height: 0 });
var EmptyPositioned = Object.freeze({
x: 0,
y: 0,
width: 0,
height: 0
});
// src/geometry/rect/Encompass.ts
var encompass = (rect, ...points) => {
const x = points.map((p) => p.x);
const y = points.map((p) => p.y);
let minX = Math.min(...x, rect.x);
let minY = Math.min(...y, rect.y);
let maxX = Math.max(...x, rect.x + rect.width);
let maxY = Math.max(...y, rect.y + rect.height);
let rectW = Math.max(rect.width, maxX - minX);
let rectH = Math.max(rect.height, maxY - minY);
return Object.freeze({
...rect,
x: minX,
y: minY,
width: rectW,
height: rectH
});
};
// src/geometry/rect/FromElement.ts
var fromElement = (el) => ({
width: el.clientWidth,
height: el.clientHeight
});
// src/geometry/rect/FromNumbers.ts
function fromNumbers3(xOrWidth, yOrHeight, width, height4) {
if (width === void 0 || height4 === void 0) {
if (typeof xOrWidth !== `number`) throw new Error(`width is not an number`);
if (typeof yOrHeight !== `number`) {
throw new TypeError(`height is not an number`);
}
return Object.freeze({ width: xOrWidth, height: yOrHeight });
}
if (typeof xOrWidth !== `number`) throw new Error(`x is not an number`);
if (typeof yOrHeight !== `number`) throw new Error(`y is not an number`);
if (typeof width !== `number`) throw new Error(`width is not an number`);
if (typeof height4 !== `number`) throw new Error(`height is not an number`);
return Object.freeze({ x: xOrWidth, y: yOrHeight, width, height: height4 });
}
// src/geometry/rect/GetRectPositionedParameter.ts
function getRectPositionedParameter(a, b, c, d) {
if (typeof a === `number`) {
if (typeof b === `number`) {
if (typeof c === `number` && typeof d === `number`) {
return { x: a, y: b, width: c, height: d };
} else if (isRect(c)) {
return { x: a, y: b, width: c.width, height: c.height };
} else {
throw new TypeError(`If params 'a' & 'b' are numbers, expect following parameters to be x,y or Rect`);
}
} else {
throw new TypeError(`If parameter 'a' is a number, expect following parameters to be: y,w,h`);
}
} else if (isRectPositioned(a)) {
return a;
} else if (isRect(a)) {
if (typeof b === `number` && typeof c === `number`) {
return { width: a.width, height: a.height, x: b, y: c };
} else if (isPoint(b)) {
return { width: a.width, height: a.height, x: b.x, y: b.y };
} else {
throw new TypeError(`If param 'a' is a Rect, expects following parameters to be x,y`);
}
} else if (isPoint(a)) {
if (typeof b === `number` && typeof c === `number`) {
return { x: a.x, y: a.y, width: b, height: c };
} else if (isRect(b)) {
return { x: a.x, y: a.y, width: b.width, height: b.height };
} else {
throw new TypeError(`If parameter 'a' is a Point, expect following params to be: Rect or width,height`);
}
}
throw new TypeError(`Expect a first parameter to be x,RectPositioned,Rect or Point`);
}
// src/geometry/rect/IsEqual.ts
var isEqualSize = (a, b) => {
if (a === void 0) throw new Error(`a undefined`);
if (b === void 0) throw new Error(`b undefined`);
return a.width === b.width && a.height === b.height;
};
var isEqual4 = (a, b) => {
if (isPositioned2(a) && isPositioned2(b)) {
if (!isEqual(a, b)) return false;
return a.width === b.width && a.height === b.height;
} else if (!isPositioned2(a) && !isPositioned2(b)) {
return a.width === b.width && a.height === b.height;
} else {
return false;
}
};
// src/geometry/rect/Lengths.ts
var lengths = (rect) => {
guardPositioned2(rect, `rect`);
return edges(rect).map((l) => length(l));
};
// src/geometry/rect/Multiply.ts
var multiplyOp = (a, b) => a * b;
function multiply3(a, b, c) {
return applyMerge(multiplyOp, a, b, c);
}
function multiplyScalar3(rect, amount) {
return applyScalar(multiplyOp, rect, amount);
}
function multiplyDim(rect, amount) {
return applyDim(multiplyOp, rect, amount);
}
// src/geometry/rect/Nearest.ts
var nearestInternal = (rect, p) => {
let { x, y } = p;
if (x < rect.x) x = rect.x;
else if (x > rect.x + rect.width) x = rect.x + rect.width;
if (y < rect.y) y = rect.y;
else if (y > rect.y + rect.height) y = rect.y + rect.height;
return Object.freeze({ ...p, x, y });
};
// src/geometry/rect/Placeholder.ts
var Placeholder2 = Object.freeze({
width: Number.NaN,
height: Number.NaN
});
var PlaceholderPositioned = Object.freeze({
x: Number.NaN,
y: Number.NaN,
width: Number.NaN,
height: Number.NaN
});
// src/geometry/rect/Perimeter.ts
var perimeter = (rect) => {
guard3(rect);
return rect.height + rect.height + rect.width + rect.width;
};
// src/geometry/rect/NormaliseByRect.ts
var dividerByLargestDimension = (rect) => {
const largest = Math.max(rect.width, rect.height);
return (value) => {
if (typeof value === `number`) {
return value / largest;
} else if (isPoint3d(value)) {
return Object.freeze({
...value,
x: value.x / largest,
y: value.y / largest,
z: value.x / largest
});
} else if (isPoint(value)) {
return Object.freeze({
...value,
x: value.x / largest,
y: value.y / largest
});
} else throw new Error(`Param 'value' is neither number nor Point`);
};
};
// src/geometry/rect/Subtract.ts
var subtractOp = (a, b) => a - b;
function subtract3(a, b, c) {
return applyMerge(subtractOp, a, b, c);
}
function subtractSize(a, b, c) {
const w = typeof b === `number` ? b : b.width;
const h = typeof b === `number` ? c : b.height;
if (h === void 0) throw new Error(`Expected height as third parameter`);
const r = {
...a,
width: a.width - w,
height: a.height - h
};
return r;
}
function subtractOffset(a, b) {
let x = 0;
let y = 0;
if (isPositioned2(a)) {
x = a.x;
y = a.y;
}
let xB = 0;
let yB = 0;
if (isPositioned2(b)) {
xB = b.x;
yB = b.y;
}
return Object.freeze({
...a,
x: x - xB,
y: y - yB,
width: a.width - b.width,
height: a.height - b.height
});
}
// src/geometry/rect/Sum.ts
var sumOp = (a, b) => a + b;
function sum3(a, b, c) {
return applyMerge(sumOp, a, b, c);
}
function sumOffset(a, b) {
let x = 0;
let y = 0;
if (isPositioned2(a)) {
x = a.x;
y = a.y;
}
let xB = 0;
let yB = 0;
if (isPositioned2(b)) {
xB = b.x;
yB = b.y;
}
return Object.freeze({
...a,
x: x + xB,
y: y + yB,
width: a.width + b.width,
height: a.height + b.height
});
}
// src/geometry/rect/ToArray.ts
function toArray(rect) {
if (isPositioned2(rect)) {
return [rect.x, rect.y, rect.width, rect.height];
} else if (isRect(rect)) {
return [rect.width, rect.height];
} else {
throw new Error(
`Param 'rect' is not a rectangle. Got: ${JSON.stringify(rect)}`
);
}
}
// src/geometry/path/index.ts
var path_exports = {};
__export(path_exports, {
getEnd: () => getEnd,
getStart: () => getStart
});
var getStart = function(path) {
if (isQuadraticBezier(path)) return path.a;
else if (isLine(path)) return path.a;
else throw new Error(`Unknown path type ${JSON.stringify(path)}`);
};
var getEnd = function(path) {
if (isQuadraticBezier(path)) return path.b;
else if (isLine(path)) return path.b;
else throw new Error(`Unknown path type ${JSON.stringify(path)}`);
};
// src/geometry/grid/index.ts
var grid_exports = {};
__export(grid_exports, {
Array1d: () => Array1d_exports,
Array2d: () => Array2d_exports,
As: () => As_exports,
By: () => enumerators_exports,
Visit: () => visitors_exports,
allDirections: () => allDirections,
applyBounds: () => applyBounds,
asRectangles: () => asRectangles,
cellAtPoint: () => cellAtPoint,
cellEquals: () => cellEquals,
cellFromIndex: () => cellFromIndex,
cellKeyString: () => cellKeyString,
cellMiddle: () => cellMiddle,
crossDirections: () => crossDirections,
getLine: () => getLine,
getVectorFromCardinal: () => getVectorFromCardinal,
guardCell: () => guardCell,
guardGrid: () => guardGrid,
indexFromCell: () => indexFromCell,
inside: () => inside,
isCell: () => isCell,
isEqual: () => isEqual5,
neighbourList: () => neighbourList,
neighbours: () => neighbours,
offset: () => offset,
offsetCardinals: () => offsetCardinals,
randomNeighbour: () => randomNeighbour,
rectangleForCell: () => rectangleForCell,
simpleLine: () => simpleLine,
toArray2d: () => toArray2d,
values: () => values
});
// src/geometry/grid/Inside.ts
var inside = (grid2, cell) => {
if (cell.x < 0 || cell.y < 0) return false;
if (cell.x >= grid2.cols || cell.y >= grid2.rows) return false;
return true;
};
// src/geometry/grid/Guards.ts
var isCell = (cell) => {
if (cell === void 0) return false;
return `x` in cell && `y` in cell;
};
var guardCell = (cell, parameterName = `Param`, grid2) => {
if (cell === void 0) {
throw new Error(parameterName + ` is undefined. Expecting {x,y}`);
}
if (cell.x === void 0) throw new Error(parameterName + `.x is undefined`);
if (cell.y === void 0) throw new Error(parameterName + `.y is undefined`);
if (Number.isNaN(cell.x)) throw new Error(parameterName + `.x is NaN`);
if (Number.isNaN(cell.y)) throw new Error(parameterName + `.y is NaN`);
if (!Number.isInteger(cell.x)) {
throw new TypeError(parameterName + `.x is non-integer`);
}
if (!Number.isInteger(cell.y)) {
throw new TypeError(parameterName + `.y is non-integer`);
}
if (grid2 !== void 0 && !inside(grid2, cell)) {
throw new Error(
`${parameterName} is outside of grid. Cell: ${cell.x},${cell.y} Grid: ${grid2.cols}, ${grid2.rows}`
);
}
};
var guardGrid = (grid2, parameterName = `Param`) => {
if (grid2 === void 0) {
throw new Error(`${parameterName} is undefined. Expecting grid.`);
}
if (!(`rows` in grid2)) throw new Error(`${parameterName}.rows is undefined`);
if (!(`cols` in grid2)) throw new Error(`${parameterName}.cols is undefined`);
if (!Number.isInteger(grid2.rows)) {
throw new TypeError(`${parameterName}.rows is not an integer`);
}
if (!Number.isInteger(grid2.cols)) {
throw new TypeError(`${parameterName}.cols is not an integer`);
}
};
// src/geometry/grid/ApplyBounds.ts
var applyBounds = function(grid2, cell, wrap4 = `undefined`) {
guardGrid(grid2, `grid`);
guardCell(cell, `cell`);
let x = cell.x;
let y = cell.y;
switch (wrap4) {
case `wrap`: {
x = x % grid2.cols;
y = y % grid2.rows;
if (x < 0) x = grid2.cols + x;
else if (x >= grid2.cols) {
x -= grid2.cols;
}
if (y < 0) y = grid2.rows + y;
else if (y >= grid2.rows) {
y -= grid2.rows;
}
x = Math.abs(x);
y = Math.abs(y);
break;
}
case `stop`: {
x = clampIndex(x, grid2.cols);
y = clampIndex(y, grid2.rows);
break;
}
case `undefined`: {
if (x < 0 || y < 0) return;
if (x >= grid2.cols || y >= grid2.rows) return;
break;
}
case `unbounded`: {
break;
}
default: {
throw new Error(`Unknown BoundsLogic '${wrap4}'. Expected: wrap, stop, undefined or unbounded`);
}
}
return Object.freeze({ x, y });
};
// src/geometry/grid/Array1d.ts
var Array1d_exports = {};
__export(Array1d_exports, {
access: () => access,
createArray: () => createArray,
createMutable: () => createMutable,
set: () => set,
setMutate: () => setMutate,
wrap: () => wrap,
wrapMutable: () => wrapMutable
});
var access = (array, cols) => {
const grid2 = gridFromArrayDimensions(array, cols);
const fn = (cell, wrap4 = `undefined`) => accessWithGrid(grid2, array, cell, wrap4);
return fn;
};
var accessWithGrid = (grid2, array, cell, wrap4) => {
const index = indexFromCell(grid2, cell, wrap4);
if (index === void 0) return void 0;
return array[index];
};
var setMutate = (array, cols) => {
const grid2 = gridFromArrayDimensions(array, cols);
return (value, cell, wrap4 = `undefined`) => setMutateWithGrid(grid2, array, value, cell, wrap4);
};
var setMutateWithGrid = (grid2, array, value, cell, wrap4) => {
const index = indexFromCell(grid2, cell, wrap4);
if (index === void 0) throw new RangeError(`Cell (${cell.x},${cell.y}) is out of range of grid cols: ${grid2.cols} rows: ${grid2.rows}`);
array[index] = value;
return array;
};
var set = (array, cols) => {
const grid2 = gridFromArrayDimensions(array, cols);
return (value, cell, wrap4) => setWithGrid(grid2, array, value, cell, wrap4);
};
var setWithGrid = (grid2, array, value, cell, wrap4) => {
const index = indexFromCell(grid2, cell, wrap4);
if (index === void 0) throw new RangeError(`Cell (${cell.x},${cell.y}) is out of range of grid cols: ${grid2.cols} rows: ${grid2.rows}`);
let copy = [...array];
copy[index] = value;
array = copy;
return copy;
};
var gridFromArrayDimensions = (array, cols) => {
const grid2 = { cols, rows: Math.ceil(array.length / cols) };
return grid2;
};
var wrapMutable = (array, cols) => {
const grid2 = gridFromArrayDimensions(array, cols);
return {
...grid2,
get: access(array, cols),
set: setMutate(array, cols),
get array() {
return array;
}
};
};
var wrap = (array, cols) => {
const grid2 = gridFromArrayDimensions(array, cols);
return {
...grid2,
get: (cell, boundsLogic = `undefined`) => accessWithGrid(grid2, array, cell, boundsLogic),
set: (value, cell, boundsLogic = `undefined`) => {
array = setWithGrid(grid2, array, value, cell, boundsLogic);
return wrap(array, cols);
},
get array() {
return array;
}
};
};
var createArray = (initialValue, rowsOrGrid, columns2) => {
const rows2 = typeof rowsOrGrid === `number` ? rowsOrGrid : rowsOrGrid.rows;
const cols = typeof rowsOrGrid === `object` ? rowsOrGrid.cols : columns2;
if (!cols) throw new Error(`Parameter 'columns' missing`);
throwIntegerTest(rows2, `aboveZero`, `rows`);
throwIntegerTest(cols, `aboveZero`, `cols`);
let t = [];
let total = rows2 * cols;
for (let i = 0; i < total; i++) {
t[i] = initialValue;
}
return t;
};
var createMutable = (initialValue, rowsOrGrid, columns2) => {
const rows2 = typeof rowsOrGrid === `number` ? rowsOrGrid : rowsOrGrid.rows;
const cols = typeof rowsOrGrid === `object` ? rowsOrGrid.cols : columns2;
if (!cols) throw new Error(`Parameter 'columns' missing`);
const arr = createArray(initialValue, rows2, cols);
return wrapMutable(arr, cols);
};
// src/geometry/grid/Array2d.ts
var Array2d_exports = {};
__export(Array2d_exports, {
access: () => access2,
create: () => create,
set: () => set2,
setMutate: () => setMutate2,
wrap: () => wrap2,
wrapMutable: () => wrapMutable2
});
var create = (array) => {
let colLen = NaN;
for (const row of array) {
if (Number.isNaN(colLen)) {
colLen = row.length;
} else {
if (colLen !== row.length) throw new Error(`Array does not have uniform column length`);