I’m trying to bounce points off mirror-lines in the plane, and my algebra keeps dropping the banana peel at exactly the wrong moment. I feel like the reflections should be clean and snappy, but my points sometimes ricochet into nonsense.
Two examples I’m playing with:
1) Reflect P = (3, -1) across L1: y = 2x + 1.
2) Reflect Q = (5, 4) across L2: the line through A = (1, 3) and B = (4, 1).
My attempt (vector style): I used the idea that if a line has a normal n and passes through a point p0 on the line, then the reflection of v should be v’ = v − 2 ((v − p0) · n) n. For L1, I picked p0 = (0, 1). I first tried n = (-2, 1) without normalizing it, and unsurprisingly everything blew up in size and the midpoint test didn’t land back on the line. Then I remembered to normalize n = (-2, 1)/sqrt(5), and I get a result like P’ ≈ (-3.4, 2.2). That one seems to behave better, but I’m still shaky because when I do a second example I start second-guessing my signs again and sometimes the midpoint isn’t exactly on the line (I get tiny offsets like 0.615 instead of 0.6 and I can’t tell if it’s round-off or me doing a step out of order).
Alternative attempt (matrix style): For a line through the origin with slope m, I wrote down the reflection matrix R_m = 1/(1 + m^2) times [[1 − m^2, 2m], [2m, m^2 − 1]]. Then for a line y = mx + b, I tried translating by a point on the line, applying R_m, and translating back. For L1 with m = 2 and p0 = (0, 1), I get R = 1/5 [[-3, 4], [4, 3]]. I subtracted p0, multiplied, then added p0 back. Sometimes I get the nice-looking P’ I mentioned above; other times (especially on L2 when I try translating by A and using m = -2/3) I get a reflected point whose midpoint with Q is off the line by a hair, or the segment isn’t exactly perpendicular based on the slope check. I suspect I’m mixing up a sign or misapplying the translation order.
My questions:
– What is a clean, reliable way to compute reflections across a general line y = mx + b so I stop tripping over signs?
– In the vector formula, is normalizing the normal absolutely required, or can I sneak the length into a denominator somewhere without breaking the magic?
– For the line through two points version, what’s the quickest robust method? Should I convert to y = mx + b first, or go straight with a direction vector and a perpendicular normal?
– If I’m doing the translate–reflect–translate-back method, what’s the exact order, and is there a common pitfall with choosing p0 or setting up the matrix that would explain my tiny mismatches?
Any help appreciated!
















3 Responses
A clean way that avoids sign slips is to use the implicit form ax + by + c = 0 with normal n = (a, b): the reflection of (x, y) is (x’, y’) where x’ = x − 2a(ax + by + c)/(a^2 + b^2) and y’ = y − 2b(ax + by + c)/(a^2 + b^2). This formula already “hides” the normalization: any nonzero multiple of the normal works because you divide by a^2 + b^2. For y = mx + b, take (a, b, c) = (m, −1, b); then with s = mx − y + b and D = 1 + m^2, you get x’ = x − 2ms/D and y’ = y + 2s/D. Example 1: P = (3, −1), m = 2, b = 1 gives s = 8, D = 5, so P’ = (−17/5, 11/5) = (−3.4, 2.2). For a line through two points, don’t convert to slope; take d = B − A = (dx, dy), a perpendicular normal n = (dy, −dx), then choose c so that a x_A + b y_A + c = 0 and apply the same formula; for A = (1, 3), B = (4, 1) we get 2x + 3y − 11 = 0, so reflecting Q = (5, 4) gives Q’ = (21/13, −14/13). If you prefer the translate–reflect–translate-back view, the exact order is x’ = p0 + R(x − p0) with R = I − 2 nn^T/(n·n); common pitfalls are using the direction vector instead of a normal, forgetting the division by n·n, or rounding early-those tiny midpoint offsets disappear if you keep exact fractions. Would you like a quick derivation of the implicit-form formula, or are the ready-to-use versions enough for your workflow?
Use the vector formula x’ = x − 2 ((x − p0)·n)/(n·n) n; no normalization is required (the n·n in the denominator handles scale), sign of n doesn’t matter, and this is exactly “translate by −p0, reflect, translate back”; for y = mx + b take n = (m, −1), p0 any point on the line (e.g., (0, b)), and for the line through A,B take p0 = A and n = (A_y − B_y, B_x − A_x).
Example: reflecting P = (3, −1) across y = 2x + 1 with n = (−2, 1), p0 = (0, 1) gives P’ = (−17/5, 11/5); reflecting Q = (5, 4) across AB with n = (2, 3), p0 = A gives Q’ = (21/13, −14/13), whose midpoint with Q is (43/13, 19/13) on AB and the segment is perpendicular to AB.
Here’s the no-banana-peel version: reflect x across the line through a with normal n by x’ = x − 2((x − a)·n) n / ||n||^2 (no unit-normal needed-its length lives in the denominator); for y = mx + b take a = (0, b), n = (m, −1); for a line through A,B take a = A and n perpendicular to d = B − A; translate–reflect–translate-back = subtract a, apply the origin formula (or the matrix from n/||n||), then add a, and any hairline mismatch is just round-off.
Example: L1 with m = 2, a = (0,1), n = (2,−1) gives P’ = (3,−1) − 2((3,−2)·(2,−1))(2,−1)/5 = (−17/5, 11/5); L2 with A = (1,3), B = (4,1), d = (3,−2), n = (2,3) gives Q’ = (5,4) − 2((4,1)·(2,3))(2,3)/13 = (21/13, −14/13).