Lemma
math, backwards
the hook · the count that won't sit still

Where do the missing intersections go?

Drag two conics on a screen. Sometimes you see four crossings. Sometimes two. Sometimes one. Sometimes none. A physics engine doing collision, a vector tool doing clipping, a font rasterizer doing outline cleanup, a ray tracer doing picking — all of them need a stable answer to “how many?” What you see on screen flickers; the math underneath does not.

Bezout’s theorem says the count is always 4 for two conics — counted in the right number system, on the right plane, with the right multiplicity. The widget below is the same one the Bezout module ships with; here it answers a different question: which subset of those 4 is what the screen actually shows?

Widget — Two Conics, Four Intersections
real4
complex0
with multiplicity > 10
total (Bezout)4 = 2 · 2
Re xIm xcomplex x-plane
Try the four presets in order. General gives 4 real intersections (Bezout satisfied without help). Tangent drops to 3 visible — turn on show multiplicity: the tangent point counts twice. Disjoint gives 0 visible — turn on show complex: the four intersections live off the real plane. Partial mixes both fixes. Every preset totals 4.
the arc
1

What the screen sees vs. what is there

Two real curves on a 2D plane. The “visible count” is just the number of points your eye finds at the same pixel — real coordinates, both finite. That is the count a naive collision detector returns by raster sampling, or a CAD engine returns by approximate root-finding. It depends on where the curves happen to be drifting today and is not stable under tiny perturbations.

Try the widget. The generalgeneral preset shows 4 real crossings — visible count agrees with Bezout. The tangenttangent preset drops to 3 visible — turn on show multiplicity and one of those gets a ×2×2 tag. The disjointdisjoint preset shows 0 visible — turn on show complex and four open dots appear in the side panel. None of the missing intersections were lost. They just left the real-affine plane.

2

Three places they hide

Bezout’s repair (covered fully in the Bezout module) tells you exactly where the missing crossings went. Three corrections; three places to look.

  • Tangency. Two crossings collapsed onto one geometric point — the algebra still says two, but the renderer sees one dot. The bookkeeping is : a tangent intersection counts as 2.
  • Off the visible plane. The intersection points have complex coordinates — they exist as solutions of the algebra but cannot be plotted in the real (x,y)(x, y) grid. Two disjoint circles still intersect at (3/2,±i5/2)(3/2, ± i \sqrt{5} / 2); the screen has nowhere to put those.
  • At infinity. Some intersections live on the line at infinity. Every two distinct circles, no matter where they sit, share the two circular points I=[1:i:0]I = [1 : i : 0] and J=[1:i:0]J = [1 : −i : 0] — that’s two of their four Bezout intersections, off-screen and complex, accounted for whether you like it or not. The fix is the .
3

Why a graphics engine cares about the stable count

An engine that only watches “visible count” is fragile. Two near-tangent circles can have visible-count 0, 1, or 2 depending on a sub-pixel jitter. A renderer that reports “no intersection” one frame and “two intersections” the next is reporting numerical noise as physics. The fix is to compute the algebraic count — the one Bezout guarantees — and then classify each root.

Practically: solve the y-resultant (a quartic in x), find its 4 complex roots with multiplicity, then label each one as real-affine (visible), complex (off-plane), or at infinity (asymptotic). The visible count is the size of the first bucket. Tangencies are marked by repeated roots, not by “two roots that happen to be very close.” A multiplicity-2 real root and two distinct real roots within ε of each other are different geometric situations that look identical on screen — the algebraic classification keeps them apart.

4

What the engine actually computes

The pipeline is short. (1) from the two conic equations to get a single polynomial in the other — a quartic when both inputs are degree 2. (2) Find its roots numerically (Durand–Kerner or similar). (3) Recover the corresponding y-coordinates by linear back-substitution. (4) Tag each intersection as real-affine, complex, or at infinity. The widget above performs steps 1–4 every time you move a slider.

# Engine pipeline: solve, classify, render. Bezout count = 4 always
# for two conics; the picture only shows the real-affine subset.
import numpy as np

def conic_resultant(c1, c2):
    """y-resultant of two conics → quartic in x. (Same as bezout module.)"""
    a1, b1, cc1, d1, e1, k1 = c1
    a2, b2, cc2, d2, e2, k2 = c2
    P = np.polynomial.Polynomial
    A1, A2 = cc1, cc2
    B1, B2 = P([e1, b1]), P([e2, b2])
    C1, C2 = P([k1, d1, a1]), P([k2, d2, a2])
    return (A1*C2 - A2*C1)**2 - (A1*B2 - A2*B1)*(B1*C2 - B2*C1)

def classify(roots, eps=1e-6):
    """Group complex roots into 'real-affine' (visible) and 'complex' (off-plane)."""
    visible, off_plane = [], []
    for r in roots:
        if abs(r.imag) < eps:
            visible.append(r.real)
        else:
            off_plane.append(r)
    return visible, off_plane

# Two ellipses, perpendicular major axes — the "general" preset.
c1 = (1/4, 0, 1,    0, 0, -1)
c2 = (1,   0, 1/4,  0, 0, -1)
roots = conic_resultant(c1, c2).roots()
visible, hidden = classify(roots)
len(visible), len(hidden)        # → (4, 0)   four visible crossings

# Two disjoint ellipses — the "disjoint" preset.
c2_far = (9, 0, 1, 0, -10, 24)
roots2 = conic_resultant(c1, c2_far).roots()
v2, h2 = classify(roots2)
len(v2), len(h2)                 # → (0, 4)   nothing on screen, all complex
# Bezout 4 = 0 visible + 4 hidden. The "disjoint" pair never lost the count;
# the renderer just had no place to draw the imaginary parts.
5

Where this shows up in a graphics stack

The same Bezout-and-classify logic, in different costumes, runs in:

  • Collision detection. Two convex shapes (circles, ellipses, capsules) meet how many times? Bezout gives the upper bound; tangency-with-multiplicity detects glancing contact; “0 real, 4 complex” reports clearly disjoint.
  • Vector clipping. When you intersect two paths in Illustrator/Figma, the tool computes algebraic intersections of cubic Bezier segments — degree 3 × degree 3 = up to 9 algebraic, classified into visible / out-of-segment / tangent.
  • Ray–curve picking. A line (degree 1) meets a conic (degree 2) in 2 algebraic points. The mouse picks the first real-affine one along the ray. If both are complex, the click misses.
  • Font outline rasterization. A horizontal scanline (degree 1) crosses a glyph outline (Beziers up to degree 3) in d·1 = d points. Counting those with multiplicity gives the even-odd fill rule for free.

In every case the surface story is “count and classify”; the deep story is Bezout’s theorem and a root-classifier. The shape changes; the count protocol doesn’t.

Real intersections come and go. Bezout’s count never does. What the screen shows is the real-affine subset of a number that doesn’t change. A graphics engine keeps the count and classifies each member; the picture is just one bucket.

exercises · 손으로 풀기
1line meets circleno calculator

The line y=mx+cy = mx + c meets the unit circle x2+y2=1x² + y² = 1 in how many points, by Bezout? For what range of (m,c)(m, c) are all of those visible (real-affine), and for what range do the missing ones become complex? Sketch one example of each.

2two circles share infinity

Take any two distinct circles. Bezout says they meet 4 times. Yet the picture on screen never shows more than 2 real-affine intersections. Where are the other 2 always? (Hint: the equation of any circle, evaluated at the line at infinity Z=0Z = 0, depends only on the leading term.)

3tangent vs near-missno calculator

An engine has two parameters: an angle θθ and a tolerance εε. As θθ sweeps through a tangent configuration, the visible-count goes 2 → 1 → 0 → 1 → 2. The “tangent” instant is one configuration; the surrounding “near-tangent” instants are different. State the difference algebraically (one root with multiplicity 2 vs two roots within ε), and explain why a robust engine should not dedupe based on raw εε-distance.

4the cubic that won't fit

You’re computing intersections of a horizontal line y=0y = 0 with the cubic y=x3+1y = x³ + 1. Bezout predicts 1·3 = 3. How many real-affine? Where are the others? (No ii required for the visible ones; one for each of the others.)

glossary · used on this page · 4
intersection multiplicity·교차 중복도
The number of times an intersection point should be counted. A transverse crossing counts once. A simple tangency counts twice — algebraically, eliminating one variable produces a polynomial with a double root at that point. A higher-order tangency counts three, four, … times. Bezout's theorem is the count with multiplicity: a curve of degree d and a curve of degree e meet, multiplicity-counted, in exactly de points.
projective plane·사영평면
The affine plane plus one extra "point at infinity" for every direction — so parallel lines, which share a direction, meet at the same one of those points. With this addition, any two distinct lines meet at exactly one point. Real version: ℝℙ². Complex version: ℂℙ². Bezout's theorem works in ℂℙ², not ℝ².
resultant·종결식
A polynomial built from two polynomials P, Q that vanishes exactly when they share a root. For two conics (degree 2 each in y, with coefficients depending on x), eliminating y via the resultant produces a polynomial in x of degree 2·2 = 4. Its 4 (complex, with multiplicity) roots are the x-coordinates of the 4 intersection points Bezout promises.
homogenize·동차화
Rewrite an affine equation in projective coordinates: substitute x → X/Z, y → Y/Z, then clear Z so every term shares one total degree. Setting Z = 1 brings the affine version back. Example: y = x² becomes YZ = X².