How lot boundaries, setbacks, and building constraints work — rectangle vs polygon mode, setback zones, clamping, snapping. Use when lot shape is wrong, setbacks don't apply correctly, or buildings escape the boundary.
Complete reference for lot boundary rendering, setback enforcement, and building constraint logic.
$ARGUMENTS — what's happening (e.g., "building escapes lot", "setback zone wrong shape", "polygon lot not rendering", "snap not working at edges")parcelPolygon is empty ([])lotWidth x lotDepth + state.rotationparcelPolygon has vertex array: [[lat1,lng1], [lat2,lng2], ...]| Operation | Owner | Function |
|---|---|---|
| Draw lot boundary polygon | MapEngine | render() |
| Draw setback zone polygon | SetbackEngine | drawSetbacks() |
| Validate setback values | SetbackEngine | applySetbacks() |
| Clamp building inside lot | SetbackEngine | _clampToLot() |
| Snap building to edges | MapEngine | _applySnap() |
| Calculate building bounding box | SetbackEngine | _buildingExtents() |
Rectangle mode:
hw = lotWidth/2, hd = lotDepth/2(-hd, -hw), (-hd, +hw), (+hd, +hw), (+hd, -hw)state.rotation degreesPolygon mode:
parcelPolygon array from ConfigEngineThe setback zone is a smaller rectangle (or polygon) inside the lot boundary:
Validation in applySetbacks():
front + rear < lotDepth (must leave room)sideL + sideR < lotWidth (must leave room)ConfigEngine.state.setbacksCommercial front: When commFront is true, a commercial zone (blue polygon) is drawn at the front of the lot, depth = commercialDepth from site JSON.
When a building is placed or dragged, _clampToLot() ensures it stays inside the lot:
_buildingExtents() (accounts for orientation rotation)lotHalfDepth - rearSetback - halfDepth (can't exceed rear)-lotHalfDepth + frontSetback + halfDepth (can't exceed front)Returns clamped (cx, cy) — MapEngine applies these to the marker position.
_applySnap(idx, offsetX, offsetY) provides magnetic snap:
SetbackEngine._buildingExtents()(offsetX, offsetY)Returns axis-aligned bounding box half-dimensions for a building:
halfW and halfD are the rotated bounding box halves_clampToLot(), _applySnap(), updateBldgDimLabels(), drawBuilding()| Symptom | Cause | Fix |
|---|---|---|
| Building escapes lot boundary | _clampToLot() not accounting for stacking | Check stack loop in _clampToLot |
| Setback zone doesn't match inputs | UI inputs not synced to state | Check save() UI sync step |
| Polygon lot shape wrong | Vertex order or coordinate format | Check parcelPolygon array — should be [[lat,lng],...] |
| Snap jumps to wrong edge | Threshold too large or wrong edge calculation | Check _applySnap threshold and edge detection |
| Building orientation doesn't match | _buildingExtents using wrong rotation | Check bldg.orientation vs state.rotation |
| Setback validation fails | front+rear >= lotDepth | Reduce values to leave room |