@rickosborne/hexgrid
Version:
Rick Osborne's collection of hexagonal grid-related code.
81 lines (80 loc) • 3.35 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
import { BetterMap } from "@rickosborne/foundation";
const hexContainsChecker = /* @__PURE__ */ __name((corners) => {
const { maxX, maxY, minX, minY, xs } = corners.slice(1).reduce((p, { x: rx, y: ry }) => {
if (rx < p.minX) p.minX = rx;
if (rx > p.maxX) p.maxX = rx;
if (ry < p.minY) p.minY = ry;
if (ry > p.maxY) p.maxY = ry;
p.xs.upsert(rx, (e) => rx + (e ?? 0));
return p;
}, { minX: corners[0].x, maxX: corners[0].x, minY: corners[0].y, maxY: corners[0].y, xs: BetterMap.empty() });
const isFlat = xs.get(minX) === 1;
let rectMinX = isFlat ? Infinity : minX;
let rectMaxX = isFlat ? -Infinity : maxX;
let rectMinY = isFlat ? minY : Infinity;
let rectMaxY = isFlat ? maxY : -Infinity;
const triangleCheckers = [];
for (const corner of corners) {
const { x: cx, y: cy } = corner;
if (isFlat && (cy === minY || cy === maxY)) {
if (cx < rectMinX) rectMinX = cx;
if (cx > rectMaxX) rectMaxX = cx;
} else if (!isFlat && (cx === minX || cx === maxX)) {
if (cy < rectMinY) rectMinY = cy;
if (cy > rectMaxY) rectMaxY = cy;
} else if (cx < rectMinX) {
triangleCheckers.push(triangleContainsChecker([corner, { x: rectMinX, y: maxY }, { x: rectMinX, y: minY }]));
} else if (cx > rectMaxX) {
triangleCheckers.push(triangleContainsChecker([corner, { x: rectMaxX, y: maxY }, { x: rectMaxX, y: minY }]));
} else if (cy < rectMinY) {
triangleCheckers.push(triangleContainsChecker([corner, { x: rectMinX, y: rectMinY }, { x: rectMaxX, y: rectMinY }]));
} else if (cy > rectMaxY) {
triangleCheckers.push(triangleContainsChecker([corner, { x: rectMinX, y: rectMaxY }, { x: rectMaxX, y: rectMaxY }]));
} else {
throw new Error("Odd hex corners?");
}
}
return (xy) => {
const { x, y } = xy;
if (x < minX || x > maxX || y < minY || y > maxY) {
return false;
}
if (x >= rectMinX && x <= rectMaxX && y >= rectMinY && y <= rectMaxY) {
return true;
}
return triangleCheckers.some((checkTriangle) => checkTriangle(xy));
};
}, "hexContainsChecker");
const hexCornersContainPoint = /* @__PURE__ */ __name((corners, xy) => {
return hexContainsChecker(corners)(xy);
}, "hexCornersContainPoint");
const triangleContainsChecker = /* @__PURE__ */ __name((triangle) => {
const [{ x: x1, y: y1 }, { x: x2, y: y2 }, { x: x3, y: y3 }] = triangle;
const x1x3 = x1 - x3;
const x3x2 = x3 - x2;
const y2y3 = y2 - y3;
const y3y1 = y3 - y1;
const d = y2y3 * x1x3 + x3x2 * (y1 - y3);
const y2y3d = y2y3 / d;
const x3x2d = x3x2 / d;
const y3y1d = y3y1 / d;
const x1x3d = x1x3 / d;
return ({ x: px, y: py }) => {
const a = y2y3d * (px - x3) + x3x2d * (py - y3);
const b = y3y1d * (px - x3) + x1x3d * (py - y3);
const c = 1 - a - b;
return a >= 0 && a <= 1 && b >= 0 && b <= 1 && c >= 0 && c <= 1;
};
}, "triangleContainsChecker");
const triangleContainsPoint = /* @__PURE__ */ __name((triangle, point) => {
return triangleContainsChecker(triangle)(point);
}, "triangleContainsPoint");
export {
hexContainsChecker,
hexCornersContainPoint,
triangleContainsChecker,
triangleContainsPoint
};
//# sourceMappingURL=hex-contains-point.mjs.map