tower / files / test / cap-pattern.test.ts
cap-pattern.test.ts
| 1 | import { describe, expect, it } from 'vitest' |
| 2 | import { TRIANGLE_KM, triangleMullions } from '../src/views/cap-pattern.js' |
| 3 | |
| 4 | describe('the cap windows are identical triangles (D-078)', () => { |
| 5 | const lines = triangleMullions() |
| 6 | const height = (TRIANGLE_KM * Math.sqrt(3)) / 2 |
| 7 | |
| 8 | it('runs its mullions in three directions, 60° apart', () => { |
| 9 | const dirs = new Set(lines.map(([x0, y0, x1, y1]) => { |
| 10 | const a = (Math.atan2(y1 - y0, x1 - x0) * 180) / Math.PI |
| 11 | return Math.round(((a % 180) + 180) % 180) |
| 12 | })) |
| 13 | expect([...dirs].sort((a, b) => a - b)).toEqual([0, 60, 120]) |
| 14 | }) |
| 15 | |
| 16 | it('spaces every line a whole triangle height from the axis, so every triangle is the same', () => { |
| 17 | for (const [x0, y0, x1, y1] of lines) { |
| 18 | const len = Math.hypot(x1 - x0, y1 - y0) |
| 19 | // Distance from the axis to the line: |cross(p0, d)|. |
| 20 | const off = Math.abs(x0 * (y1 - y0) - y0 * (x1 - x0)) / len |
| 21 | const k = off / height |
| 22 | expect(Math.abs(k - Math.round(k))).toBeLessThan(1e-9) |
| 23 | } |
| 24 | }) |
| 25 | |
| 26 | it('stays inside the cap, and puts a vertex on the axis', () => { |
| 27 | for (const [x0, y0, x1, y1] of lines) { |
| 28 | expect(Math.hypot(x0, y0)).toBeLessThanOrEqual(50 + 1e-9) |
| 29 | expect(Math.hypot(x1, y1)).toBeLessThanOrEqual(50 + 1e-9) |
| 30 | } |
| 31 | // One line of each family passes through the centre. |
| 32 | const through = lines.filter(([x0, y0, x1, y1]) => Math.abs(x0 * y1 - y0 * x1) < 1e-9) |
| 33 | expect(through).toHaveLength(3) |
| 34 | }) |
| 35 | }) |