Roof Space Constraints: From Panel Dimensions to a Real Layout
Your consumption analysis says 6 kWp. Your roof says something else, and the roof wins. This post is about the conversion step: taking a measured roof plane and turning it into a specific number of specific modules in a specific arrangement, with the setbacks, the soil vent pipe and the roof window all costing you real panels. It is the least glamorous part of a solar panel layout roof planner workflow and the part that most often makes a quote 30% smaller than the spreadsheet promised.
Three measurements, and one of them is a trap
You need the width of the roof plane along the eaves, the length from eaves to ridge measured along the slope, and the pitch.
Google Earth Pro (free desktop app, Tools → Ruler) will give you the eaves width to within about 0.3 m if you zoom hard and pick the gutter line carefully. It will also give you an eaves-to-ridge distance, and that number is wrong for your purposes: it is the horizontal run seen from above, not the slope length. Divide by the cosine of the pitch.
For a 35° roof with a 4.42 m horizontal run:
slope length = 4.42 / cos(35°) = 4.42 / 0.8192 = 5.40 m
That’s 0.98 m of roof you’d have lost by trusting the aerial measurement. At panel scale, roughly one extra row.
Pitch itself comes free from the Environment Agency’s National LiDAR Programme DSM (1 m resolution, downloadable from the Defra Survey Data Download service, covers most of England). Take ridge height minus eaves height, divide by the horizontal run, take the arctangent. Rise 3.1 m over run 4.42 m gives 35.0°. If you’d rather not touch LiDAR, a pitch gauge app against a rafter in the loft gets you within a degree.
While you’re in the loft with a Bosch GLM laser measure, count rafters and check centres. 400 mm or 600 mm changes what mounting configurations are open to you later.
Working example for the rest of this post: 8.40 m wide, 5.40 m slope, 35° pitch, south-west facing.
Modules are not 1.7 by 1.0 metres
Round numbers will cost you a row. Here are the footprints that actually turn up on UK residential quotes in 2026:
| Module | Power | Dimensions (mm) | Weight |
|---|---|---|---|
| Trina Vertex S+ TSM-NEG9R.28 | 445 W | 1762 × 1134 × 30 | 21.0 kg |
| JA Solar JAM54D41 | 440 W | 1762 × 1134 × 30 | 21.5 kg |
| Jinko Tiger Neo 54HL4R | 440 W | 1762 × 1134 × 30 | 21.0 kg |
| Aiko Neostar 2S | 465 W | 1722 × 1134 × 30 | 21.5 kg |
| LONGi Hi-MO X6 | 430 W | 1722 × 1134 × 30 | 21.5 kg |
| REC Alpha Pure-RX | 430 W | 1730 × 1118 × 30 | 19.5 kg |
| Legacy 60-cell (pre-2020) | 300 W | 1650 × 991 × 35 | 18.5 kg |
Datasheet revisions change these. Trina has shipped the Vertex S+ at both 1762 mm and 1 762 mm with different frame heights depending on the production year, so pull the PDF for the exact SKU your installer is quoting rather than the range page.
Add the clamp gap. Mid-clamps on K2, Renusol and Schletter rails are typically 18–22 mm wide, so 20 mm between adjacent panels is the right planning figure. Over six columns that’s 100 mm, which is exactly the kind of number that decides whether you get six or seven.
Setbacks: what you actually have to leave
There is a lot of folklore here, so be precise about which constraints are real.
Permitted development in England caps roof-mounted panels at 200 mm protrusion from the roof plane and forbids anything above the ridge (chimneys excluded). Neither imposes an edge margin.
Wind uplift is the real driver. BS EN 1991-1-4 defines a perimeter edge zone of width e/10, where e = min(building width, 2 × height). For an 8.4 m wide house at 7 m to the ridge, e = 8.4 m and the edge zone is 840 mm. That does not mean “no panels within 840 mm”. It means the uplift pressure in that band is higher, so your mounting kit needs more hooks per square metre there. Both K2 Base and the Renusol PV-Configurator are free after registration, take your postcode, terrain category and roof geometry, and output hook spacing per zone. Run one before you finalise anything.
What forces a physical margin is practical: gutter and eaves flashing, mortar-bedded ridge tiles you’ll want to reach again, verge clips, and the need to walk a course of tiles during install. 300 mm from the eaves and both verges, 400 mm from the ridge is a defensible planning default for on-roof mounting.
In-roof systems are different animals. GSE In-Roof trays add roughly 100 mm per module in each direction plus a flashing and soaker perimeter of 150 mm or more, and the trays are sized for specific module dimension bands. Same panel count, noticeably more roof.
Applying 300/300/300/400 to our example:
usable width = 8400 - 300 - 300 = 7800 mm
usable slope = 5400 - 300 - 400 = 4700 mm
Portrait or landscape is a four-panel decision
Same roof, same module, both orientations:
portrait cols = (7800 + 20) // (1134 + 20) = 6
rows = (4700 + 20) // (1762 + 20) = 2 → 12 panels, 5.34 kWp
slack: 896 mm horizontally, 1156 mm vertically
landscape cols = (7800 + 20) // (1762 + 20) = 4
rows = (4700 + 20) // (1134 + 20) = 4 → 16 panels, 7.12 kWp
slack: 692 mm horizontally, 104 mm vertically
Four extra panels, 1.78 kWp, purely from rotating the grid. Note the 104 mm of vertical slack in the landscape case: that is not a margin, it’s a rounding error. If your slope length is actually 5.29 m rather than 5.40 m, you lose a whole row and land back at 12. Measure it twice, from inside the loft, before you commit.
The catch is structural. Portrait with horizontal rails is the default because rails run perpendicular to rafters and hooks land wherever you like. Landscape gives you two options: run rails vertically down the slope (about 37 m of rail here versus 27 m for portrait, and each rail has to land near a rafter), or keep rails horizontal and clamp the module’s short edges. Short-side clamping is permitted by most manufacturers but at a reduced load rating, and only in the configurations listed in the installation manual’s mounting methods table. K2 Base will downrate or reject a configuration the module doesn’t allow, which is a useful sanity check you get for free.
Now put the obstructions in
Our roof has a 110 mm soil vent pipe at (1545, 845) mm from the bottom-left corner of the plane, and a Velux GGL MK04 whose external frame plus flashing clearance occupies a 1080 × 1280 mm rectangle at (5100, 2600).
Naively dropping these onto the landscape grid kills five panels, because the Velux straddles two column boundaries and two row boundaries. But nothing says the array has to start at the minimum setback. You have 692 mm of horizontal slack to slide it into.
Brute-force the offsets:
from itertools import product
MODULE, WATTS, GAP = (1762, 1134), 445, 20
ROOF = (8400, 5400)
SETBACK = dict(left=300, right=300, eaves=300, ridge=400)
OBSTRUCTIONS = [
(1545, 845, 110, 110), # soil vent pipe
(5100, 2600, 1080, 1280), # Velux MK04 + flashing clearance
]
def hits(a, b):
ax, ay, aw, ah = a; bx, by, bw, bh = b
return ax < bx+bw and bx < ax+aw and ay < by+bh and by < ay+ah
def pack(landscape):
w, h = MODULE if landscape else MODULE[::-1]
uw = ROOF[0] - SETBACK["left"] - SETBACK["right"]
uh = ROOF[1] - SETBACK["eaves"] - SETBACK["ridge"]
cols, rows = (uw+GAP)//(w+GAP), (uh+GAP)//(h+GAP)
sw = uw - (cols*w + (cols-1)*GAP)
sh = uh - (rows*h + (rows-1)*GAP)
best = (0, 0, 0)
for dx, dy in product(range(0, sw+1, 10), range(0, sh+1, 10)):
x0, y0 = SETBACK["left"]+dx, SETBACK["eaves"]+dy
n = sum(not any(hits((x0+c*(w+GAP), y0+r*(h+GAP), w, h), o)
for o in OBSTRUCTIONS)
for c, r in product(range(cols), range(rows)))
if n > best[0]: best = (n, x0, y0)
return cols, rows, best
for name, ls in (("portrait", False), ("landscape", True)):
c, r, (n, x0, y0) = pack(ls)
print(f"{name:10} {c}x{r} raw {c*r:2} fits {n:2} "
f"{n*WATTS/1000:5.2f} kWp origin x={x0} y={y0}")
portrait 6x2 raw 12 fits 10 4.45 kWp origin x=450 y=400
landscape 4x4 raw 16 fits 13 5.79 kWp origin x=900 y=300
Sliding the landscape array 600 mm right tucks the Velux entirely inside one column, recovering two panels. Landscape still wins, 13 to 10.
The vent pipe costs one panel in every arrangement, because a 110 mm obstruction can never hide in a 20 mm clamp gap. Replacing it with an internal air admittance valve and slating over the hole is a genuinely cheap fix, maybe £40 of parts plus a roofer’s morning, and buys back a panel. Check your drainage layout first: Approved Document H still wants at least one open ventilating stack serving the building, so this only works if another stack qualifies.
What 13 panels does to the rest of the design
Thirteen modules at 445 W is 5.785 kWp. On a SW-facing 35° roof in southern England, PVGIS (use PVGIS-SARAH3, set the azimuth to -45 and tick “optimise slope” off) puts you around 920 kWh/kWp, so roughly 5,320 kWh a year. The portrait layout would have delivered about 4,090 kWh. At 40% self-consumption against a 26p import rate and 15p SEG on the rest, that gap is worth around £240 a year, for the cost of three more modules and some extra rail.
Thirteen is an odd number, which matters. A dual-MPPT hybrid (GivEnergy Gen3, Solis S6, Fox ESS H3) takes 7 + 6. Cold-weather Voc check on the longer string: 39.2 V open circuit, -0.25%/°C, at -10°C gives 39.2 × 1.0875 = 42.6 V, times seven is 298 V. Comfortably inside a 600 V input. A 5 kW inverter on 5.785 kWp is a 1.16 DC:AC ratio, which is fine for UK irradiance, and it puts you over the 3.68 kW G98 threshold so you’ll need a G99 application to your DNO.
Array mass is 13 × 21 kg = 273 kg spread over about 26 m², roughly 10.5 kg/m². That’s within what BS 5534 assumes for most post-war rafters, but if yours are 100 × 47 at 600 mm centres over a long unsupported span, get someone to look.
Feeding the number back into the model
You started with a kWp target from your half-hourly data. You now have 5.785 kWp, and it arrived with constraints attached: a fixed azimuth, a fixed tilt, and a Velux-shaped hole that means one column of modules sits in partial shade for part of the afternoon. Go back and re-run the self-consumption model with the real figure rather than the target, because the shape of the generation curve on a SW roof is not the shape you probably assumed. If you haven’t built that model yet, sizing from your own consumption data is the step this one depends on.
Worth doing before you call anyone: rebuild the same layout in OpenSolar. It’s free, works in the UK, pulls decent aerial imagery, lets you trace the roof plane and drop real modules on it, and will render a shading analysis from a chimney you drew in. Compare its panel count to your script’s. Where they disagree, one of you has the wrong setback assumption, and finding out which takes ten minutes.
Then take the layout to quotes. An installer who proposes 10 portrait panels on this roof is not necessarily wrong, but you’re now in a position to ask why, and to hear whether the answer is “your module manual doesn’t permit short-side clamping” or “that’s just how we always do it.”