// Static figures for Chapters 9 and 10.
import { Arrowheads, Figure, Label, Node, arrow } from './svg.tsx'
import { ink, method, seqColor } from '../plot/palette.ts'
/** The L-shaped domain, its re-entrant corner, and the profile of r^(2/3). */
export function ReentrantCorner() {
const S = 62 // half-width of the square, in px
const CX = 150
const CY = 112
return (
{/* the domain */}
{/* the corner angle */}
{/* the profile */}
{(
[
{ p: 2 / 3, c: method.mps, l: 'r²ᐟ³ at the re-entrant corner' },
{ p: 2, c: ink.muted, l: 'r² at a convex corner' },
] as const
).map((s, k) => {
const pts: string[] = []
for (let i = 0; i <= 100; i++) {
const t = i / 100
pts.push(`${(20 + t * 280).toFixed(1)} ${(186 - 140 * Math.pow(t, s.p)).toFixed(1)}`)
}
return (
)
})}
)
}
/** Discretising the area against discretising the boundary. */
export function AreaAgainstBoundary() {
const blobPts = (cx: number, cy: number, rr: number, m: number) =>
Array.from({ length: m }, (_, i) => {
const t = (2 * Math.PI * i) / m
const r = rr * (1 + 0.18 * Math.cos(3 * t))
return { x: cx + r * Math.cos(t), y: cy + r * Math.sin(t) * 0.92, t }
})
const path = (cx: number, cy: number, rr: number) =>
'M ' + blobPts(cx, cy, rr, 160).map((p) => `${p.x.toFixed(1)} ${p.y.toFixed(1)}`).join(' L ') + ' Z'
const cx1 = 168
const cx2 = 548
const cy = 118
const rr = 78
return (
{/* area discretisation */}
{Array.from({ length: 19 }, (_, i) => (
))}
{Array.from({ length: 18 }, (_, j) => (
))}
{Array.from({ length: 19 }, (_, i) =>
Array.from({ length: 17 }, (_, j) => (
)),
)}
{/* boundary discretisation */}
{blobPts(cx2, cy, rr, 36).map((p, i) => (
))}
)
}
/** Why evaluation near the curve is the hard part. */
export function CloseEvaluation() {
const cx = 200
const cy = 116
const rr = 86
const pts = (m: number) =>
Array.from({ length: m }, (_, i) => {
const t = (2 * Math.PI * i) / m
const r = rr * (1 + 0.16 * Math.cos(3 * t))
return { x: cx + r * Math.cos(t), y: cy + r * Math.sin(t) * 0.94 }
})
const d = 'M ' + pts(180).map((p) => `${p.x.toFixed(1)} ${p.y.toFixed(1)}`).join(' L ') + ' Z'
const far = { x: cx - 12, y: cy + 6 }
const near = { x: cx + 74, y: cy - 26 }
// the integrand along the curve, seen from each target
const K = (spread: number, amp: number) => {
const out: string[] = []
for (let i = 0; i <= 200; i++) {
const t = -1 + (2 * i) / 200
const v = amp / (1 + (t / spread) ** 2)
out.push(`${(420 + (t + 1) * 140).toFixed(1)} ${(186 - v).toFixed(1)}`)
}
return 'M ' + out.join(' L ')
}
return (
{pts(40).map((p, i) => (
))}
{Array.from({ length: 21 }, (_, i) => (
))}
)
}
/** The Pac-Man domain, and its image as a rectangle in polar coordinates. */
export function PacmanDomain() {
const CX = 158
const CY = 128
const R = 88
// the rectangle: theta across, r up
const RX = 430
const RY = 48
const RW = 240
const RH = 150
return (
{/* the domain */}
{/* the interior angle at the corner */}
{/* right-angle marks where the edges meet the arc */}
{/* the polar rectangle */}
)
}