Beams have no width in that sense, you were right originally
I was really beat today from some other stuff going on so I cracked this problem open to relax a bit, and upon further investigation I found that we don't actually do line vs circle, we do line vs the circle's inscribed square, whose sidelength is precomputed to avoid any trig. Way less complex than anything involving a curve or approximation thereof.
But it's still running really slowly. Part of it is FInt: I created FInt equivalents of your Intersection and Rotate methods and they were roughly 10x slower than your double-based variants. Then I tested our "cheat and use the square" method and it still came up really slow (faster than IntersectionFInt, but interestingly slower than RotateFInt... how could it possibly be slower than trig, right?). After a bit of profiing it seems like most of the cost is in casting ints to FInts, but I'm still not entirely sure.
Anyway, thanks for kickstarting the investigation, significant gains seem likely in the end