Prototype
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
# Yard Map
|
||||
|
||||
Static yard mapping site built with Leaflet and plain browser modules.
|
||||
|
||||
## Status
|
||||
|
||||
The project currently has:
|
||||
|
||||
- A static Leaflet map with OSM raster tiles.
|
||||
- Client-side JavaScript-authored yard geometry converted to GeoJSON at load time.
|
||||
- Typed feature classes with centralized styling.
|
||||
- Per-anchor local coordinate rotation for offset-based authoring.
|
||||
- Feature relationship metadata (`id`, `parentId`, `groupIds`) and a top-level group catalog for future visibility controls.
|
||||
- Example yard data mostly copied from `buildings.gpkg` and then preserved as JS modules.
|
||||
|
||||
The next likely product direction is map-layer visibility controls driven by the existing feature groups and parent-child relationships.
|
||||
|
||||
## Authoring model
|
||||
|
||||
Geometry stays in JavaScript, then gets converted to GeoJSON client-side at load time.
|
||||
|
||||
- Use absolute coordinates with `point(lat, lon)`.
|
||||
- Use absolute GeoJSON-style coordinates with `lngLat(lon, lat)` or `.trace([[lon, lat], ...])`.
|
||||
- Use local offsets with `offset(origin)` inside `.add(...)`, for example `.add(offset(lotCorner), south(ft(15)), east(ft(10)))`.
|
||||
- Build typed features with classes like `new House()`, `new Garage()`, `new Tree()`, and `new Sprinkler()` so styles live in one place.
|
||||
- Add relationships with `.childOf(...)` and `.inGroup(...)` so future UI can show or hide related features together.
|
||||
|
||||
The example yard is now split by concern:
|
||||
|
||||
- `src/data/boundaries.js`
|
||||
- `src/data/buildings.js`
|
||||
- `src/data/pavement.js`
|
||||
- `src/data/plants.js`
|
||||
- `src/data/irrigation.js`
|
||||
|
||||
The typed feature registry lives in `src/lib/feature-types.js`, feature classes live in `src/lib/yard-features.js`, and shared coordinate helpers live in `src/lib/geometry.js`.
|
||||
|
||||
Local `north`, `south`, `east`, and `west` offsets are rotated per anchor. In this example, `topLeftLotCorner` in `src/data/anchors.js` carries `assumedNorthClockwiseDegrees` from `src/data/settings.js`. A negative value means that anchor's local north is counterclockwise from true north, so local east drifts a bit toward true north.
|
||||
|
||||
Most example geometry was copied from `buildings.gpkg` and preserved as JS-authored coordinates. Tree records also carry custom attributes like canopy diameter, height, and planted date for popup rendering.
|
||||
|
||||
Feature relationships are exported with each GeoJSON feature as stable `id`, `parentId`, and `groupIds` properties, and the collection also exposes a top-level `groups` array. The current sample marks the porch and deck as part of the house and groups the Medora junipers under `Juniper Trees`.
|
||||
|
||||
## Project structure
|
||||
|
||||
- `src/lib/geometry.js`: low-level coordinate and offset helpers.
|
||||
- `src/lib/feature-types.js`: centralized default styling by feature kind.
|
||||
- `src/lib/yard-features.js`: typed feature classes, feature/group metadata, and GeoJSON export.
|
||||
- `src/data/settings.js`: local authoring settings such as lot rotation.
|
||||
- `src/data/anchors.js`: named anchor points for offset-based authoring.
|
||||
- `src/data/boundaries.js`: lot boundary and fence features.
|
||||
- `src/data/buildings.js`: house, garage, porch, deck, and building-related groups.
|
||||
- `src/data/pavement.js`: driveway and walkway geometry.
|
||||
- `src/data/plants.js`: flower beds, trees, and tree groups.
|
||||
- `src/data/irrigation.js`: sprinkler features.
|
||||
- `src/data/yard.js`: top-level yard collection assembly.
|
||||
- `src/main.js`: Leaflet rendering, legend generation, and popup rendering.
|
||||
|
||||
## Key decisions
|
||||
|
||||
- Geometry is authored in JavaScript, not GeoJSON, so yard data can mix exact coordinates with local offset expressions.
|
||||
- Styling is defined by feature type rather than repeated inline for each feature.
|
||||
- Local offsets rotate per anchor, not globally, so future anchors can carry different orientations.
|
||||
- Grouping is stored in the data model now so later show/hide behavior can be implemented without restructuring features.
|
||||
- The example GPKG data was used as a one-time source to seed JS-authored geometry, not as a runtime dependency.
|
||||
|
||||
## GeoPackage notes
|
||||
|
||||
- `buildings.gpkg` was used to seed most sample geometry.
|
||||
- The `lot_boundary` layer had mixed or incorrect CRS metadata.
|
||||
- The usable lot polygon was `fid = 2`, and it had to be treated as `EPSG:26914` during one-time extraction before converting to JS coordinates.
|
||||
|
||||
## Validation
|
||||
|
||||
Useful local checks:
|
||||
|
||||
```bash
|
||||
node -e "import('./src/data/yard.js').then(({ yardGeoJSON }) => console.log(yardGeoJSON.features.length))"
|
||||
```
|
||||
|
||||
```bash
|
||||
python3 -m http.server 4173
|
||||
```
|
||||
|
||||
The first check validates that the authored yard data still imports and exports cleanly. The second runs the static site locally.
|
||||
|
||||
## Run locally
|
||||
|
||||
Because the app uses ES modules, serve it over HTTP instead of opening `index.html` directly.
|
||||
|
||||
```bash
|
||||
python3 -m http.server 4173
|
||||
```
|
||||
|
||||
Then open <http://localhost:4173>.
|
||||
|
||||
## Zoom behavior
|
||||
|
||||
The yard overlays are vector data, so they stay sharp at any zoom level the map allows.
|
||||
The current basemap is still raster OSM tiles, so above zoom 19 Leaflet reuses and scales those tiles instead of fetching higher-resolution imagery.
|
||||
|
||||
If you want a truly crisp basemap at arbitrary close zoom, you need a vector tile or self-hosted tile source rather than the standard public OSM raster tile endpoint.
|
||||
|
||||
## Future direction
|
||||
|
||||
- Add UI controls for toggling groups and possibly parent-linked feature clusters.
|
||||
- Decide whether toggles should operate on feature groups, feature kinds, parent-child trees, or all three.
|
||||
- If sharper basemap zoom is needed, replace the raster OSM background with a vector tile or self-hosted tile solution.
|
||||
- If more data import is needed from GIS sources, prefer one-time extraction into JS-authored modules rather than making the app depend on runtime GIS tooling.
|
||||
Reference in New Issue
Block a user