( pts: Pt[], width: number, height: number, )
| 113 | |
| 114 | /** Scale+centre transform that fits `pts` into a W×H frame (with padding). */ |
| 115 | export function fitTransform( |
| 116 | pts: Pt[], |
| 117 | width: number, |
| 118 | height: number, |
| 119 | ): { k: number; cx: number; cy: number } { |
| 120 | if (pts.length === 0) return { k: 1, cx: width / 2, cy: height / 2 }; |
| 121 | const xs = pts.map((p) => p.x); |
| 122 | const ys = pts.map((p) => p.y); |
| 123 | const minX = Math.min(...xs); |
| 124 | const maxX = Math.max(...xs); |
| 125 | const minY = Math.min(...ys); |
| 126 | const maxY = Math.max(...ys); |
| 127 | const cx = (minX + maxX) / 2; |
| 128 | const cy = (minY + maxY) / 2; |
| 129 | const span = Math.max(maxX - minX, maxY - minY, 1); |
| 130 | const k = Math.max(0.3, Math.min(7, (Math.min(width, height) * 0.8) / span)); |
| 131 | return { k, cx, cy }; |
| 132 | } |
| 133 | |
| 134 | /** Grid geometry for the filmstrip layout. */ |
| 135 | export function stripCells(n: number, width: number, height: number) { |
no outgoing calls
no test coverage detected