How dimension lines work — chain dims, witness lines, perpendicular measurements, hiding segments, repositioning chains. Use when dims look wrong or when modifying dimension behavior.
Complete reference for the dimension system — how measurements are drawn, hidden, and repositioned.
$ARGUMENTS — what's happening (e.g., "dims at wrong angle", "witness line crosses boundary", "chain missing segment", "how to add new dim type")ALL dimension drawing is SetbackEngine (engine-setback.js).
updateBldgDimLabels()updateBldgDimLabels()drawChain() inside updateBldgDimLabels()MapEngine does NOT draw dimension lines. It only provides the map object for Leaflet layer placement.
Instead of individual per-building dimensions, the system draws continuous chains across the full lot:
Each chain is an ordered list of boundary points. The distance between consecutive points = one labeled segment. Shared boundaries between buildings create one witness line serving both adjacent segments.
Two arrays built before drawing:
dPts (depth): starts with rear lot edge (-lotHalfDepth) and front lot edge (+lotHalfDepth), then adds front/rear of every building copywPts (width): starts with left/right lot edges, then adds left/right of every buildingBuilding edges come from _buildingExtents(): cx +/- halfDepth, cy +/- halfWidth
Both arrays: deduplicated, sorted. The sorted array IS the chain.
drawChain(chain, refCoord, isX, perpX, perpY, rotDeg, prefix):
refCoord — perpendicular position where the dim line runs (offset from building edge)perpX, perpY — unit vector pointing away from lot (which side to draw on)At every boundary position: a short line perpendicular to the chain, extending from the building/lot edge out to the dim line + 2ft overshoot.
EXT = 5 ft — offset from building edge to dim lineEX2 = 2 ft — overshoot beyond dim lineALL geometry is in the rotated local frame (Frame B). +X = rear, +Y = right side. Because everything is in the same frame, every distance between chain points is an exact perpendicular measurement — regardless of lot rotation on the map.
18.0 ft in the depth chain means exactly 18.0 feet between those two surfaces, measured at a right angle.
Frame B (Local Rotated Feet) — SetbackEngine only.
SetbackEngine computes positions in feet → MapEngine converts to lat/lng for Leaflet drawing.
The conversion (in MapEngine):
rx = px * cos(rot) - py * sin(rot)
ry = px * sin(rot) + py * cos(rot)
lat = state.lat + ry / F_LAT
lng = state.lng + rx / F_LNG
hiddenDimKeys Setchain_w_3 (width chain, segment 3) or chain_d_1 (depth chain, segment 1)_payload().saved.hiddenDimKeys as arraynew Set() in MapEngine on loadchainWOffset or chainDOffset in real time_payload() → persists across reloads| Name | Value | Purpose |
|---|---|---|
| EXT | 5 ft | Perpendicular offset from building edge to dim line |
| EX2 | 2 ft | Witness line overshoot beyond dim line |
| TK | 1.2 ft | Half-length of 45-degree tick marks |
| F_LAT | 364,566 | ft per degree latitude |
| F_LNG | 365,228 * cos(lat) | ft per degree longitude |
polyLocalVerts computed relative to polygon centroid (ccLat/ccLng)chainRefX/Y is relative to the pin (state.lat/lng)polyExtentAt() returns wrong extentpolyExtentAt() (needs KB-1 fixed first)| Symptom | Check |
|---|---|
| Dim line at wrong angle | Is state.rotation correct? Check rotDeg in drawChain() |
| Dims don't appear | Is showBldgDims true? Check the toggle state |
| Segment missing | Is it in hiddenDimKeys? Check Set contents |
| Wrong distance shown | Check _buildingExtents() — is the bounding box correct for the building orientation? |
| Chain on wrong side of lot | Check perpX/perpY direction and refCoord offset |
| Dims overlap each other | Check chainWOffset/chainDOffset — may need repositioning |
| Witness line crosses boundary | KB-2 — no fix yet, cosmetic issue |
| Polygon lot dims wrong | KB-1 — centroid vs pin origin mismatch |