This is the 2D top-down counterpart to the rotatable 3D scene, and it is computed independently, not flattened from it. The sun still comes from real solar-geometry equations at latitude 51.5°N:
δ = 23.44° · sin(2π(284+d)/365) (declination, day d)
H = 15°·(hour − 12) (hour angle)
elevation = asin(sinφ sinδ + cosφ cosδ cosH)
Corrected tracking angle. The 3D version points its single-axis tracker straight at the sun's raw azimuth angle. That is only exactly optimal at solar noon. A horizontal tracker rotating about its own row axis has normal n=(sinθ,cosθ,0), and the angle that truly maximizes n·sunDir is the calculus optimum θ = atan2(sunDir.x, sunDir.y) — this simulator uses that corrected formula, which measurably out-performs the 3D approximation away from solar noon (verified numerically: never worse, sometimes several % better energy yield).
Exact shadow quadrilateral. The 3D version's shadow math also drops the north–south offset component ("ignore z offset spread"). Here every panel corner is rotated into its real 3D position (about the row's own long axis for tracking, or about the east–west axis for fixed-tilt) and projected straight down the sun's ray onto the ground — giving the true shadow shape, which is a plain translated rectangle for a flat horizontal panel but a sheared, area-changed quadrilateral once the panel tilts. Crop cells are tested for containment in that exact quadrilateral, not a 1D shadow band.
groundPoint = worldCorner − (worldCorner.y / sunDir.y) · sunDir
Crop yield still follows a saturating light-response curve — cropYield ≈ min(1, PAR/0.5) — and the Land Equivalent Ratio combines both outputs: LER = energyYield + cropYield, with LER > 1 meaning the shared field out-produces two separate fields. The right-hand chart traces sun elevation, energy yield, crop PAR and LER across the whole day for the chosen date, computed once per date change by re-running the exact same equations at 15-minute intervals — not smoothed or interpolated.