@react-arch/geometry 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -57,6 +57,7 @@ interface WallLike {
57
57
  start: Vec2$1;
58
58
  end: Vec2$1;
59
59
  thickness: number;
60
+ height?: number;
60
61
  }
61
62
  declare function wallLength(wall: WallLike): number;
62
63
  declare function wallDirection(wall: WallLike): Vec2$1;
@@ -70,6 +71,8 @@ declare function pointAlongWall(wall: WallLike, offset: number): Vec2$1;
70
71
  interface OpeningLike {
71
72
  offset: number;
72
73
  width: number;
74
+ height?: number;
75
+ sillHeight?: number;
73
76
  }
74
77
  /**
75
78
  * The two centerline endpoints of an opening cut, clamped to the wall length.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/vec2.ts","../src/line.ts","../src/polygon.ts","../src/wall.ts","../src/snap.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/vec2.ts","../src/line.ts","../src/polygon.ts","../src/wall.ts","../src/snap.ts"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -195,7 +195,10 @@ function openingSpan(wall, opening) {
195
195
  /** Whether an opening fits entirely within the wall it is attached to. */
196
196
  function openingFits(wall, opening) {
197
197
  const len = wallLength(wall);
198
- return opening.offset - opening.width / 2 >= -1e-6 && opening.offset + opening.width / 2 <= len + 1e-6;
198
+ if (!(opening.width > 0 && opening.offset - opening.width / 2 >= -1e-6 && opening.offset + opening.width / 2 <= len + 1e-6)) return false;
199
+ if (wall.height === void 0 || opening.height === void 0) return true;
200
+ const sill = opening.sillHeight ?? 0;
201
+ return opening.height > 0 && sill >= -1e-6 && sill + opening.height <= wall.height + 1e-6;
199
202
  }
200
203
  function wallBoxes(wall, openings, wallHeight, extendEnds = 0) {
201
204
  const len = wallLength(wall);
@@ -207,12 +210,23 @@ function wallBoxes(wall, openings, wallHeight, extendEnds = 0) {
207
210
  z0: 0,
208
211
  z1: wallHeight
209
212
  }];
210
- const sorted = [...openings].map((o) => ({
211
- a0: Math.max(0, o.offset - o.width / 2),
212
- a1: Math.min(len, o.offset + o.width / 2),
213
- sill: Math.max(0, o.sillHeight),
214
- top: Math.min(wallHeight, o.sillHeight + o.height)
215
- })).sort((a, b) => a.a0 - b.a0);
213
+ const sorted = [...openings].map((o) => {
214
+ const rawA0 = o.offset - o.width / 2;
215
+ const rawA1 = o.offset + o.width / 2;
216
+ return {
217
+ a0: Math.max(0, rawA0),
218
+ a1: Math.min(len, rawA1),
219
+ sill: Math.max(0, Math.min(wallHeight, o.sillHeight)),
220
+ top: Math.max(0, Math.min(wallHeight, o.sillHeight + o.height)),
221
+ overlapsWall: rawA1 > 0 && rawA0 < len
222
+ };
223
+ }).filter((o) => o.overlapsWall && o.a1 > o.a0 && o.top > o.sill).sort((a, b) => a.a0 - b.a0);
224
+ if (sorted.length === 0) return [{
225
+ along0: lo,
226
+ along1: hi,
227
+ z0: 0,
228
+ z1: wallHeight
229
+ }];
216
230
  const boxes = [];
217
231
  let cursor = lo;
218
232
  for (const o of sorted) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["EPSILON","EPSILON"],"sources":["../src/vec2.ts","../src/line.ts","../src/polygon.ts","../src/wall.ts","../src/snap.ts"],"sourcesContent":["import { EPSILON, type Vec2 } from \"@react-arch/shared\";\n\nexport const add = (a: Vec2, b: Vec2): Vec2 => [a[0] + b[0], a[1] + b[1]];\nexport const sub = (a: Vec2, b: Vec2): Vec2 => [a[0] - b[0], a[1] - b[1]];\nexport const scale = (a: Vec2, s: number): Vec2 => [a[0] * s, a[1] * s];\nexport const dot = (a: Vec2, b: Vec2): number => a[0] * b[0] + a[1] * b[1];\nexport const cross = (a: Vec2, b: Vec2): number => a[0] * b[1] - a[1] * b[0];\nexport const length = (a: Vec2): number => Math.hypot(a[0], a[1]);\nexport const distance = (a: Vec2, b: Vec2): number => length(sub(a, b));\n\nexport function normalize(a: Vec2): Vec2 {\n const len = length(a);\n if (len < EPSILON) return [0, 0];\n return [a[0] / len, a[1] / len];\n}\n\n/** Left-hand normal of a vector (rotate +90°). */\nexport function normal(a: Vec2): Vec2 {\n return [-a[1], a[0]];\n}\n\nexport function lerp(a: Vec2, b: Vec2, t: number): Vec2 {\n return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];\n}\n\nexport function angle(a: Vec2, b: Vec2): number {\n return Math.atan2(b[1] - a[1], b[0] - a[0]);\n}\n\nexport function equals(a: Vec2, b: Vec2, eps = EPSILON): boolean {\n return Math.abs(a[0] - b[0]) <= eps && Math.abs(a[1] - b[1]) <= eps;\n}\n\n/** Project point p onto the segment [a,b], returning the closest point + t. */\nexport function projectPointOnSegment(\n p: Vec2,\n a: Vec2,\n b: Vec2,\n): { point: Vec2; t: number; distance: number } {\n const ab = sub(b, a);\n const len2 = dot(ab, ab);\n if (len2 < EPSILON) return { point: a, t: 0, distance: distance(p, a) };\n let t = dot(sub(p, a), ab) / len2;\n t = Math.max(0, Math.min(1, t));\n const point = add(a, scale(ab, t));\n return { point, t, distance: distance(p, point) };\n}\n","import { EPSILON, type Vec2 } from \"@react-arch/shared\";\nimport { cross, sub } from \"./vec2.js\";\n\nexport interface Segment {\n a: Vec2;\n b: Vec2;\n}\n\n/**\n * Intersection of two infinite lines defined by segments. Returns null when\n * the lines are parallel (within EPSILON).\n */\nexport function lineIntersection(s1: Segment, s2: Segment): Vec2 | null {\n const r = sub(s1.b, s1.a);\n const s = sub(s2.b, s2.a);\n const denom = cross(r, s);\n if (Math.abs(denom) < EPSILON) return null; // parallel\n const qp = sub(s2.a, s1.a);\n const t = cross(qp, s) / denom;\n return [s1.a[0] + t * r[0], s1.a[1] + t * r[1]];\n}\n\n/**\n * Intersection point of two finite segments, or null if they don't cross.\n */\nexport function segmentIntersection(s1: Segment, s2: Segment): Vec2 | null {\n const r = sub(s1.b, s1.a);\n const s = sub(s2.b, s2.a);\n const denom = cross(r, s);\n if (Math.abs(denom) < EPSILON) return null;\n const qp = sub(s2.a, s1.a);\n const t = cross(qp, s) / denom;\n const u = cross(qp, r) / denom;\n if (t < -EPSILON || t > 1 + EPSILON || u < -EPSILON || u > 1 + EPSILON) {\n return null;\n }\n return [s1.a[0] + t * r[0], s1.a[1] + t * r[1]];\n}\n","import { type Vec2 } from \"@react-arch/shared\";\n\n/** Signed area (positive = counter-clockwise winding). */\nexport function signedArea(polygon: Vec2[]): number {\n let sum = 0;\n for (let i = 0; i < polygon.length; i++) {\n const a = polygon[i]!;\n const b = polygon[(i + 1) % polygon.length]!;\n sum += a[0] * b[1] - b[0] * a[1];\n }\n return sum / 2;\n}\n\nexport function polygonArea(polygon: Vec2[]): number {\n return Math.abs(signedArea(polygon));\n}\n\nexport function polygonCentroid(polygon: Vec2[]): Vec2 {\n let cx = 0;\n let cy = 0;\n let a = 0;\n for (let i = 0; i < polygon.length; i++) {\n const p0 = polygon[i]!;\n const p1 = polygon[(i + 1) % polygon.length]!;\n const f = p0[0] * p1[1] - p1[0] * p0[1];\n cx += (p0[0] + p1[0]) * f;\n cy += (p0[1] + p1[1]) * f;\n a += f;\n }\n if (Math.abs(a) < 1e-9) {\n // Degenerate polygon: fall back to vertex average.\n const n = polygon.length || 1;\n return [\n polygon.reduce((s, p) => s + p[0], 0) / n,\n polygon.reduce((s, p) => s + p[1], 0) / n,\n ];\n }\n a *= 3;\n return [cx / a, cy / a];\n}\n\nexport function isClockwise(polygon: Vec2[]): boolean {\n return signedArea(polygon) < 0;\n}\n\nexport function ensureCounterClockwise(polygon: Vec2[]): Vec2[] {\n return isClockwise(polygon) ? [...polygon].reverse() : polygon;\n}\n\n/** Axis-aligned bounding box of a set of points. */\nexport function bounds(points: Vec2[]): {\n min: Vec2;\n max: Vec2;\n width: number;\n height: number;\n} {\n if (points.length === 0) {\n return { min: [0, 0], max: [0, 0], width: 0, height: 0 };\n }\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of points) {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n return {\n min: [minX, minY],\n max: [maxX, maxY],\n width: maxX - minX,\n height: maxY - minY,\n };\n}\n\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n let inside = false;\n const [px, py] = point;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const a = polygon[i]!;\n const b = polygon[j]!;\n const intersect =\n a[1] > py !== b[1] > py &&\n px < ((b[0] - a[0]) * (py - a[1])) / (b[1] - a[1]) + a[0];\n if (intersect) inside = !inside;\n }\n return inside;\n}\n","import { type Vec2 } from \"@react-arch/shared\";\nimport { add, distance, normal, normalize, scale, sub } from \"./vec2.js\";\n\nexport interface WallLike {\n start: Vec2;\n end: Vec2;\n thickness: number;\n}\n\nexport function wallLength(wall: WallLike): number {\n return distance(wall.start, wall.end);\n}\n\nexport function wallDirection(wall: WallLike): Vec2 {\n return normalize(sub(wall.end, wall.start));\n}\n\n/**\n * Generate the visible quad polygon of a wall from its centerline and\n * thickness. Vertices are ordered counter-clockwise.\n */\nexport function wallPolygon(wall: WallLike, extendEnds = 0): Vec2[] {\n const dir = wallDirection(wall);\n const n = normal(dir);\n const half = wall.thickness / 2;\n const offset = scale(n, half);\n const negOffset = scale(n, -half);\n // Push the ends out along the wall direction so corners overlap (no notch).\n const start = add(wall.start, scale(dir, -extendEnds));\n const end = add(wall.end, scale(dir, extendEnds));\n return [\n add(start, negOffset),\n add(end, negOffset),\n add(end, offset),\n add(start, offset),\n ];\n}\n\n/** World position of a point at distance `offset` along the wall centerline. */\nexport function pointAlongWall(wall: WallLike, offset: number): Vec2 {\n const dir = wallDirection(wall);\n return add(wall.start, scale(dir, offset));\n}\n\nexport interface OpeningLike {\n offset: number;\n width: number;\n}\n\n/**\n * The two centerline endpoints of an opening cut, clamped to the wall length.\n */\nexport function openingSpan(\n wall: WallLike,\n opening: OpeningLike,\n): { start: Vec2; end: Vec2; center: Vec2 } {\n const len = wallLength(wall);\n const half = opening.width / 2;\n const start = Math.max(0, opening.offset - half);\n const end = Math.min(len, opening.offset + half);\n return {\n start: pointAlongWall(wall, start),\n end: pointAlongWall(wall, end),\n center: pointAlongWall(wall, opening.offset),\n };\n}\n\n/** Whether an opening fits entirely within the wall it is attached to. */\nexport function openingFits(wall: WallLike, opening: OpeningLike): boolean {\n const len = wallLength(wall);\n return (\n opening.offset - opening.width / 2 >= -1e-6 &&\n opening.offset + opening.width / 2 <= len + 1e-6\n );\n}\n\nexport interface WallOpeningInput extends OpeningLike {\n /** Bottom of the opening above the floor. */\n sillHeight: number;\n /** Opening height. */\n height: number;\n}\n\n/**\n * A solid box of the wall expressed in wall-local coordinates: `along` runs\n * from the wall start, `z` is vertical. The 3D renderer extrudes each box by\n * the wall thickness. This is how openings are \"cut\" without CSG — the wall is\n * decomposed into the solid pieces that remain around its openings.\n */\nexport interface WallBox {\n along0: number;\n along1: number;\n z0: number;\n z1: number;\n}\n\nexport function wallBoxes(\n wall: WallLike,\n openings: WallOpeningInput[],\n wallHeight: number,\n /**\n * Extend the solid wall by this much past each end. Pass `thickness / 2` so\n * walls meeting at a corner overlap and fill the corner square — otherwise\n * each centerline box stops short and leaves a notch.\n */\n extendEnds = 0,\n): WallBox[] {\n const len = wallLength(wall);\n const lo = -extendEnds;\n const hi = len + extendEnds;\n if (openings.length === 0) {\n return [{ along0: lo, along1: hi, z0: 0, z1: wallHeight }];\n }\n const sorted = [...openings]\n .map((o) => ({\n a0: Math.max(0, o.offset - o.width / 2),\n a1: Math.min(len, o.offset + o.width / 2),\n sill: Math.max(0, o.sillHeight),\n top: Math.min(wallHeight, o.sillHeight + o.height),\n }))\n .sort((a, b) => a.a0 - b.a0);\n\n const boxes: WallBox[] = [];\n let cursor = lo;\n for (const o of sorted) {\n if (o.a0 > cursor) {\n boxes.push({ along0: cursor, along1: o.a0, z0: 0, z1: wallHeight });\n }\n // Lintel above the opening.\n if (o.top < wallHeight) {\n boxes.push({ along0: o.a0, along1: o.a1, z0: o.top, z1: wallHeight });\n }\n // Sill below the opening (windows).\n if (o.sill > 0) {\n boxes.push({ along0: o.a0, along1: o.a1, z0: 0, z1: o.sill });\n }\n cursor = Math.max(cursor, o.a1);\n }\n if (cursor < hi) {\n boxes.push({ along0: cursor, along1: hi, z0: 0, z1: wallHeight });\n }\n return boxes;\n}\n","import { type Vec2 } from \"@react-arch/shared\";\nimport { distance, lerp } from \"./vec2.js\";\nimport { projectPointOnSegment } from \"./vec2.js\";\n\nexport type SnapKind = \"endpoint\" | \"midpoint\" | \"grid\" | \"perpendicular\";\n\nexport interface SnapResult {\n point: Vec2;\n kind: SnapKind;\n distance: number;\n}\n\nexport interface SnapSegment {\n a: Vec2;\n b: Vec2;\n}\n\nexport function snapToGrid(point: Vec2, gridSize: number): Vec2 {\n if (gridSize <= 0) return point;\n return [\n Math.round(point[0] / gridSize) * gridSize,\n Math.round(point[1] / gridSize) * gridSize,\n ];\n}\n\n/**\n * Find the best snap candidate near `point`. Endpoint and midpoint snaps take\n * priority over grid snaps within the given pixel/world tolerance.\n */\nexport function findSnap(\n point: Vec2,\n segments: SnapSegment[],\n options: { tolerance: number; gridSize?: number } = { tolerance: 0.2 },\n): SnapResult | null {\n const candidates: SnapResult[] = [];\n for (const seg of segments) {\n for (const ep of [seg.a, seg.b]) {\n const d = distance(point, ep);\n if (d <= options.tolerance) {\n candidates.push({ point: ep, kind: \"endpoint\", distance: d });\n }\n }\n const mid = lerp(seg.a, seg.b, 0.5);\n const dm = distance(point, mid);\n if (dm <= options.tolerance) {\n candidates.push({ point: mid, kind: \"midpoint\", distance: dm });\n }\n const proj = projectPointOnSegment(point, seg.a, seg.b);\n if (proj.distance <= options.tolerance) {\n candidates.push({\n point: proj.point,\n kind: \"perpendicular\",\n distance: proj.distance,\n });\n }\n }\n\n if (candidates.length > 0) {\n candidates.sort((a, b) => {\n const rank: Record<SnapKind, number> = {\n endpoint: 0,\n midpoint: 1,\n perpendicular: 2,\n grid: 3,\n };\n if (rank[a.kind] !== rank[b.kind]) return rank[a.kind] - rank[b.kind];\n return a.distance - b.distance;\n });\n return candidates[0]!;\n }\n\n if (options.gridSize) {\n const gp = snapToGrid(point, options.gridSize);\n return { point: gp, kind: \"grid\", distance: distance(point, gp) };\n }\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["EPSILON","EPSILON"],"sources":["../src/vec2.ts","../src/line.ts","../src/polygon.ts","../src/wall.ts","../src/snap.ts"],"sourcesContent":["import { EPSILON, type Vec2 } from \"@react-arch/shared\";\n\nexport const add = (a: Vec2, b: Vec2): Vec2 => [a[0] + b[0], a[1] + b[1]];\nexport const sub = (a: Vec2, b: Vec2): Vec2 => [a[0] - b[0], a[1] - b[1]];\nexport const scale = (a: Vec2, s: number): Vec2 => [a[0] * s, a[1] * s];\nexport const dot = (a: Vec2, b: Vec2): number => a[0] * b[0] + a[1] * b[1];\nexport const cross = (a: Vec2, b: Vec2): number => a[0] * b[1] - a[1] * b[0];\nexport const length = (a: Vec2): number => Math.hypot(a[0], a[1]);\nexport const distance = (a: Vec2, b: Vec2): number => length(sub(a, b));\n\nexport function normalize(a: Vec2): Vec2 {\n const len = length(a);\n if (len < EPSILON) return [0, 0];\n return [a[0] / len, a[1] / len];\n}\n\n/** Left-hand normal of a vector (rotate +90°). */\nexport function normal(a: Vec2): Vec2 {\n return [-a[1], a[0]];\n}\n\nexport function lerp(a: Vec2, b: Vec2, t: number): Vec2 {\n return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];\n}\n\nexport function angle(a: Vec2, b: Vec2): number {\n return Math.atan2(b[1] - a[1], b[0] - a[0]);\n}\n\nexport function equals(a: Vec2, b: Vec2, eps = EPSILON): boolean {\n return Math.abs(a[0] - b[0]) <= eps && Math.abs(a[1] - b[1]) <= eps;\n}\n\n/** Project point p onto the segment [a,b], returning the closest point + t. */\nexport function projectPointOnSegment(\n p: Vec2,\n a: Vec2,\n b: Vec2,\n): { point: Vec2; t: number; distance: number } {\n const ab = sub(b, a);\n const len2 = dot(ab, ab);\n if (len2 < EPSILON) return { point: a, t: 0, distance: distance(p, a) };\n let t = dot(sub(p, a), ab) / len2;\n t = Math.max(0, Math.min(1, t));\n const point = add(a, scale(ab, t));\n return { point, t, distance: distance(p, point) };\n}\n","import { EPSILON, type Vec2 } from \"@react-arch/shared\";\nimport { cross, sub } from \"./vec2.js\";\n\nexport interface Segment {\n a: Vec2;\n b: Vec2;\n}\n\n/**\n * Intersection of two infinite lines defined by segments. Returns null when\n * the lines are parallel (within EPSILON).\n */\nexport function lineIntersection(s1: Segment, s2: Segment): Vec2 | null {\n const r = sub(s1.b, s1.a);\n const s = sub(s2.b, s2.a);\n const denom = cross(r, s);\n if (Math.abs(denom) < EPSILON) return null; // parallel\n const qp = sub(s2.a, s1.a);\n const t = cross(qp, s) / denom;\n return [s1.a[0] + t * r[0], s1.a[1] + t * r[1]];\n}\n\n/**\n * Intersection point of two finite segments, or null if they don't cross.\n */\nexport function segmentIntersection(s1: Segment, s2: Segment): Vec2 | null {\n const r = sub(s1.b, s1.a);\n const s = sub(s2.b, s2.a);\n const denom = cross(r, s);\n if (Math.abs(denom) < EPSILON) return null;\n const qp = sub(s2.a, s1.a);\n const t = cross(qp, s) / denom;\n const u = cross(qp, r) / denom;\n if (t < -EPSILON || t > 1 + EPSILON || u < -EPSILON || u > 1 + EPSILON) {\n return null;\n }\n return [s1.a[0] + t * r[0], s1.a[1] + t * r[1]];\n}\n","import { type Vec2 } from \"@react-arch/shared\";\n\n/** Signed area (positive = counter-clockwise winding). */\nexport function signedArea(polygon: Vec2[]): number {\n let sum = 0;\n for (let i = 0; i < polygon.length; i++) {\n const a = polygon[i]!;\n const b = polygon[(i + 1) % polygon.length]!;\n sum += a[0] * b[1] - b[0] * a[1];\n }\n return sum / 2;\n}\n\nexport function polygonArea(polygon: Vec2[]): number {\n return Math.abs(signedArea(polygon));\n}\n\nexport function polygonCentroid(polygon: Vec2[]): Vec2 {\n let cx = 0;\n let cy = 0;\n let a = 0;\n for (let i = 0; i < polygon.length; i++) {\n const p0 = polygon[i]!;\n const p1 = polygon[(i + 1) % polygon.length]!;\n const f = p0[0] * p1[1] - p1[0] * p0[1];\n cx += (p0[0] + p1[0]) * f;\n cy += (p0[1] + p1[1]) * f;\n a += f;\n }\n if (Math.abs(a) < 1e-9) {\n // Degenerate polygon: fall back to vertex average.\n const n = polygon.length || 1;\n return [\n polygon.reduce((s, p) => s + p[0], 0) / n,\n polygon.reduce((s, p) => s + p[1], 0) / n,\n ];\n }\n a *= 3;\n return [cx / a, cy / a];\n}\n\nexport function isClockwise(polygon: Vec2[]): boolean {\n return signedArea(polygon) < 0;\n}\n\nexport function ensureCounterClockwise(polygon: Vec2[]): Vec2[] {\n return isClockwise(polygon) ? [...polygon].reverse() : polygon;\n}\n\n/** Axis-aligned bounding box of a set of points. */\nexport function bounds(points: Vec2[]): {\n min: Vec2;\n max: Vec2;\n width: number;\n height: number;\n} {\n if (points.length === 0) {\n return { min: [0, 0], max: [0, 0], width: 0, height: 0 };\n }\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of points) {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n return {\n min: [minX, minY],\n max: [maxX, maxY],\n width: maxX - minX,\n height: maxY - minY,\n };\n}\n\nexport function pointInPolygon(point: Vec2, polygon: Vec2[]): boolean {\n let inside = false;\n const [px, py] = point;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const a = polygon[i]!;\n const b = polygon[j]!;\n const intersect =\n a[1] > py !== b[1] > py &&\n px < ((b[0] - a[0]) * (py - a[1])) / (b[1] - a[1]) + a[0];\n if (intersect) inside = !inside;\n }\n return inside;\n}\n","import { type Vec2 } from \"@react-arch/shared\";\nimport { add, distance, normal, normalize, scale, sub } from \"./vec2.js\";\n\nexport interface WallLike {\n start: Vec2;\n end: Vec2;\n thickness: number;\n height?: number;\n}\n\nexport function wallLength(wall: WallLike): number {\n return distance(wall.start, wall.end);\n}\n\nexport function wallDirection(wall: WallLike): Vec2 {\n return normalize(sub(wall.end, wall.start));\n}\n\n/**\n * Generate the visible quad polygon of a wall from its centerline and\n * thickness. Vertices are ordered counter-clockwise.\n */\nexport function wallPolygon(wall: WallLike, extendEnds = 0): Vec2[] {\n const dir = wallDirection(wall);\n const n = normal(dir);\n const half = wall.thickness / 2;\n const offset = scale(n, half);\n const negOffset = scale(n, -half);\n // Push the ends out along the wall direction so corners overlap (no notch).\n const start = add(wall.start, scale(dir, -extendEnds));\n const end = add(wall.end, scale(dir, extendEnds));\n return [\n add(start, negOffset),\n add(end, negOffset),\n add(end, offset),\n add(start, offset),\n ];\n}\n\n/** World position of a point at distance `offset` along the wall centerline. */\nexport function pointAlongWall(wall: WallLike, offset: number): Vec2 {\n const dir = wallDirection(wall);\n return add(wall.start, scale(dir, offset));\n}\n\nexport interface OpeningLike {\n offset: number;\n width: number;\n height?: number;\n sillHeight?: number;\n}\n\n/**\n * The two centerline endpoints of an opening cut, clamped to the wall length.\n */\nexport function openingSpan(\n wall: WallLike,\n opening: OpeningLike,\n): { start: Vec2; end: Vec2; center: Vec2 } {\n const len = wallLength(wall);\n const half = opening.width / 2;\n const start = Math.max(0, opening.offset - half);\n const end = Math.min(len, opening.offset + half);\n return {\n start: pointAlongWall(wall, start),\n end: pointAlongWall(wall, end),\n center: pointAlongWall(wall, opening.offset),\n };\n}\n\n/** Whether an opening fits entirely within the wall it is attached to. */\nexport function openingFits(wall: WallLike, opening: OpeningLike): boolean {\n const len = wallLength(wall);\n const fitsAlongWall =\n opening.width > 0 &&\n opening.offset - opening.width / 2 >= -1e-6 &&\n opening.offset + opening.width / 2 <= len + 1e-6;\n if (!fitsAlongWall) return false;\n\n if (wall.height === undefined || opening.height === undefined) return true;\n const sill = opening.sillHeight ?? 0;\n return opening.height > 0 && sill >= -1e-6 && sill + opening.height <= wall.height + 1e-6;\n}\n\nexport interface WallOpeningInput extends OpeningLike {\n /** Bottom of the opening above the floor. */\n sillHeight: number;\n /** Opening height. */\n height: number;\n}\n\n/**\n * A solid box of the wall expressed in wall-local coordinates: `along` runs\n * from the wall start, `z` is vertical. The 3D renderer extrudes each box by\n * the wall thickness. This is how openings are \"cut\" without CSG — the wall is\n * decomposed into the solid pieces that remain around its openings.\n */\nexport interface WallBox {\n along0: number;\n along1: number;\n z0: number;\n z1: number;\n}\n\nexport function wallBoxes(\n wall: WallLike,\n openings: WallOpeningInput[],\n wallHeight: number,\n /**\n * Extend the solid wall by this much past each end. Pass `thickness / 2` so\n * walls meeting at a corner overlap and fill the corner square — otherwise\n * each centerline box stops short and leaves a notch.\n */\n extendEnds = 0,\n): WallBox[] {\n const len = wallLength(wall);\n const lo = -extendEnds;\n const hi = len + extendEnds;\n if (openings.length === 0) {\n return [{ along0: lo, along1: hi, z0: 0, z1: wallHeight }];\n }\n const sorted = [...openings]\n .map((o) => {\n const rawA0 = o.offset - o.width / 2;\n const rawA1 = o.offset + o.width / 2;\n return {\n a0: Math.max(0, rawA0),\n a1: Math.min(len, rawA1),\n sill: Math.max(0, Math.min(wallHeight, o.sillHeight)),\n top: Math.max(0, Math.min(wallHeight, o.sillHeight + o.height)),\n overlapsWall: rawA1 > 0 && rawA0 < len,\n };\n })\n .filter((o) => o.overlapsWall && o.a1 > o.a0 && o.top > o.sill)\n .sort((a, b) => a.a0 - b.a0);\n\n if (sorted.length === 0) {\n return [{ along0: lo, along1: hi, z0: 0, z1: wallHeight }];\n }\n\n const boxes: WallBox[] = [];\n let cursor = lo;\n for (const o of sorted) {\n if (o.a0 > cursor) {\n boxes.push({ along0: cursor, along1: o.a0, z0: 0, z1: wallHeight });\n }\n // Lintel above the opening.\n if (o.top < wallHeight) {\n boxes.push({ along0: o.a0, along1: o.a1, z0: o.top, z1: wallHeight });\n }\n // Sill below the opening (windows).\n if (o.sill > 0) {\n boxes.push({ along0: o.a0, along1: o.a1, z0: 0, z1: o.sill });\n }\n cursor = Math.max(cursor, o.a1);\n }\n if (cursor < hi) {\n boxes.push({ along0: cursor, along1: hi, z0: 0, z1: wallHeight });\n }\n return boxes;\n}\n","import { type Vec2 } from \"@react-arch/shared\";\nimport { distance, lerp } from \"./vec2.js\";\nimport { projectPointOnSegment } from \"./vec2.js\";\n\nexport type SnapKind = \"endpoint\" | \"midpoint\" | \"grid\" | \"perpendicular\";\n\nexport interface SnapResult {\n point: Vec2;\n kind: SnapKind;\n distance: number;\n}\n\nexport interface SnapSegment {\n a: Vec2;\n b: Vec2;\n}\n\nexport function snapToGrid(point: Vec2, gridSize: number): Vec2 {\n if (gridSize <= 0) return point;\n return [\n Math.round(point[0] / gridSize) * gridSize,\n Math.round(point[1] / gridSize) * gridSize,\n ];\n}\n\n/**\n * Find the best snap candidate near `point`. Endpoint and midpoint snaps take\n * priority over grid snaps within the given pixel/world tolerance.\n */\nexport function findSnap(\n point: Vec2,\n segments: SnapSegment[],\n options: { tolerance: number; gridSize?: number } = { tolerance: 0.2 },\n): SnapResult | null {\n const candidates: SnapResult[] = [];\n for (const seg of segments) {\n for (const ep of [seg.a, seg.b]) {\n const d = distance(point, ep);\n if (d <= options.tolerance) {\n candidates.push({ point: ep, kind: \"endpoint\", distance: d });\n }\n }\n const mid = lerp(seg.a, seg.b, 0.5);\n const dm = distance(point, mid);\n if (dm <= options.tolerance) {\n candidates.push({ point: mid, kind: \"midpoint\", distance: dm });\n }\n const proj = projectPointOnSegment(point, seg.a, seg.b);\n if (proj.distance <= options.tolerance) {\n candidates.push({\n point: proj.point,\n kind: \"perpendicular\",\n distance: proj.distance,\n });\n }\n }\n\n if (candidates.length > 0) {\n candidates.sort((a, b) => {\n const rank: Record<SnapKind, number> = {\n endpoint: 0,\n midpoint: 1,\n perpendicular: 2,\n grid: 3,\n };\n if (rank[a.kind] !== rank[b.kind]) return rank[a.kind] - rank[b.kind];\n return a.distance - b.distance;\n });\n return candidates[0]!;\n }\n\n if (options.gridSize) {\n const gp = snapToGrid(point, options.gridSize);\n return { point: gp, kind: \"grid\", distance: distance(point, gp) };\n }\n return null;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-arch/geometry",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -12,7 +12,7 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "@react-arch/shared": "0.1.1"
15
+ "@react-arch/shared": "0.1.3"
16
16
  },
17
17
  "devDependencies": {
18
18
  "typescript": "^5.7.2",