Use local PMTiles basemap
No files matched your search
@@ -0,0 +1,103 @@
|
|||||||
|
# Yard Map Agent Notes
|
||||||
|
|
||||||
|
This file is a fast handoff for future coding agents working in this repo.
|
||||||
|
|
||||||
|
## What this project is
|
||||||
|
|
||||||
|
Static client-side yard mapping app.
|
||||||
|
|
||||||
|
- Rendering: MapLibre GL JS.
|
||||||
|
- Basemap: committed Mandan-area Protomaps vector tiles in `tiles/mandan.pmtiles`.
|
||||||
|
- Yard data: authored in JavaScript modules, converted to GeoJSON in the browser.
|
||||||
|
- Runtime: plain ES modules, no bundler.
|
||||||
|
|
||||||
|
## Current architecture
|
||||||
|
|
||||||
|
Core files:
|
||||||
|
|
||||||
|
- `src/lib/geometry.js`: absolute points, local offsets, feet conversion, per-anchor rotation support.
|
||||||
|
- `src/lib/feature-types.js`: feature-kind labels, geometry constraints, detail field schemas, and style defaults.
|
||||||
|
- `src/lib/yard-features.js`: typed feature classes, stable ids, groups, parent-child relationships, schema metadata, GeoJSON export.
|
||||||
|
- `src/data/*.js`: yard content split by domain.
|
||||||
|
- `src/main.js`: MapLibre map, yard layers, legend, popup rendering.
|
||||||
|
|
||||||
|
Top-level exported data shape from `src/data/yard.js`:
|
||||||
|
|
||||||
|
- `type: "FeatureCollection"`
|
||||||
|
- `schemaVersion: 2`
|
||||||
|
- `lifecycleFields: { plantedDate: "date", removedDate: "date" }`
|
||||||
|
- `featureTypes: [...]`
|
||||||
|
- `features: [...]`
|
||||||
|
- `groups: [...]`
|
||||||
|
|
||||||
|
Each feature currently exports:
|
||||||
|
|
||||||
|
- `properties.id`
|
||||||
|
- `properties.kind`
|
||||||
|
- `properties.label`
|
||||||
|
- `properties.name`
|
||||||
|
- `properties.plantedDate`
|
||||||
|
- `properties.removedDate`
|
||||||
|
- `properties.parentId`
|
||||||
|
- `properties.groupIds`
|
||||||
|
- `properties.details`
|
||||||
|
|
||||||
|
## Important decisions already made
|
||||||
|
|
||||||
|
1. Data is JS-authored on purpose.
|
||||||
|
This allows mixing exact imported geometry with expressions like `offset(anchor, east(ft(10)))`.
|
||||||
|
|
||||||
|
2. Styling belongs to feature types, not individual features by default.
|
||||||
|
If you need a new semantic type, prefer adding a new typed feature or feature-type definition rather than hand-styling scattered instances.
|
||||||
|
|
||||||
|
3. Local rotation is per anchor.
|
||||||
|
`offset(...)` reads `assumedNorthClockwiseDegrees` from the anchor point used as the origin. Do not reintroduce a global lot rotation unless there is a strong reason.
|
||||||
|
|
||||||
|
4. Grouping and parent-child metadata are already part of the data model.
|
||||||
|
Future visibility controls should consume `groupIds` and `parentId` rather than inventing a second relationship system.
|
||||||
|
|
||||||
|
5. The GPKG was only a seed source.
|
||||||
|
The app does not depend on GIS tooling at runtime.
|
||||||
|
|
||||||
|
## Known data caveat
|
||||||
|
|
||||||
|
`buildings.gpkg` has a CRS issue in `lot_boundary`.
|
||||||
|
|
||||||
|
- The usable lot polygon was `fid = 2`.
|
||||||
|
- It had to be treated as `EPSG:26914` during extraction.
|
||||||
|
- Do not trust that layer's metadata blindly if you re-import from the GPKG.
|
||||||
|
|
||||||
|
## What is already modeled
|
||||||
|
|
||||||
|
- Porch and deck are children of the main house and also part of the `House Parts` group.
|
||||||
|
- Medora junipers are part of the `Juniper Trees` group.
|
||||||
|
- A test tree exists that is offset from the top-left lot corner using per-anchor rotation.
|
||||||
|
|
||||||
|
## Likely next steps
|
||||||
|
|
||||||
|
1. Add show/hide controls driven by `yardGeoJSON.groups` and possibly `parentId`.
|
||||||
|
2. Decide whether toggles should be by feature kind, by group, by parent object, or a combination.
|
||||||
|
3. The basemap uses local vector tiles and is overzoomed from source zoom 15
|
||||||
|
through the yard map's maximum zoom of 24. Symbol layers are deliberately
|
||||||
|
omitted so the map has no remote font or sprite dependency.
|
||||||
|
|
||||||
|
## Useful validation commands
|
||||||
|
|
||||||
|
Validate data export:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node -e "import('./src/data/yard.js').then(({ yardGeoJSON }) => console.log(yardGeoJSON.features.length))"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run local server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m http.server 4173
|
||||||
|
```
|
||||||
|
|
||||||
|
## Editing guidance
|
||||||
|
|
||||||
|
- Preserve the typed-feature pattern.
|
||||||
|
- Prefer adding semantic types or groups over ad hoc properties when possible.
|
||||||
|
- Keep authored geometry readable; avoid generated noise unless the user explicitly wants bulk-import output.
|
||||||
|
- If adding new anchors, attach rotation metadata to the anchor itself.
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
# Yard Map
|
||||||
|
|
||||||
|
Static yard mapping site built with MapLibre, PMTiles, and plain browser modules.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
The project currently has:
|
||||||
|
|
||||||
|
- A static MapLibre map backed by a local Mandan-area PMTiles vector archive.
|
||||||
|
- Client-side JavaScript-authored yard geometry converted to GeoJSON at load time.
|
||||||
|
- Typed feature classes with centralized styling.
|
||||||
|
- Schema-versioned yard data with a top-level feature type catalog.
|
||||||
|
- 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`. Feature type definitions include the label, required geometry type, known detail fields, and default map style.
|
||||||
|
|
||||||
|
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 lifecycle dates for popup rendering.
|
||||||
|
|
||||||
|
Feature relationships are exported with each GeoJSON feature as stable `id`, `parentId`, and `groupIds` properties. Each feature also exports universal `plantedDate` and `removedDate` lifecycle fields for timeline filtering. The collection exposes `schemaVersion`, `lifecycleFields`, `featureTypes`, and `groups` at the top level. Style is resolved from the feature type registry at render time rather than stored on each exported feature. 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`: MapLibre rendering, legend generation, and popup rendering.
|
||||||
|
- `tiles/mandan.pmtiles`: locally served vector basemap for the Mandan area.
|
||||||
|
- `scripts/extract-mandan-pmtiles.sh`: reproducible Mandan tile extraction.
|
||||||
|
- `docs/vector-tiles.md`: tile update and hosting notes.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
Both the yard overlays and the local basemap are vector data, so linework stays
|
||||||
|
sharp as the map zooms in. The Protomaps archive tops out at its source maximum
|
||||||
|
zoom and MapLibre overzooms those vector tiles to the yard map's maximum zoom
|
||||||
|
of 24.
|
||||||
|
|
||||||
|
## 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 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.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Mandan vector tiles
|
||||||
|
|
||||||
|
The yard map reads the committed `tiles/mandan.pmtiles` archive directly in
|
||||||
|
the browser using MapLibre GL JS. No tile server or internet-hosted raster tile
|
||||||
|
service is required. The map omits the Protomaps symbol layers so it does not
|
||||||
|
need remotely hosted font glyphs or sprites; the basemap is fully local.
|
||||||
|
|
||||||
|
The archive covers Mandan and a modest surrounding margin:
|
||||||
|
`-101.05,46.74,-100.75,46.93`. PMTiles extraction is tile-aligned, so the
|
||||||
|
actual archive includes a little neighboring context.
|
||||||
|
|
||||||
|
## Build an update
|
||||||
|
|
||||||
|
Install the [`pmtiles` CLI](https://docs.protomaps.com/pmtiles/cli), choose a
|
||||||
|
dated Version 4 daily build from
|
||||||
|
[`maps.protomaps.com/builds`](https://maps.protomaps.com/builds), and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scripts/extract-mandan-pmtiles.sh \
|
||||||
|
https://build.protomaps.com/YYYYMMDD.pmtiles
|
||||||
|
```
|
||||||
|
|
||||||
|
The script refuses to overwrite an existing archive. Move the old archive
|
||||||
|
aside before deliberately replacing it.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Yard Map</title>
|
||||||
|
<link rel="stylesheet" href="./vendor/maplibre/maplibre-gl.css" />
|
||||||
|
<link rel="stylesheet" href="./styles.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="app-shell">
|
||||||
|
<aside class="panel">
|
||||||
|
<p class="eyebrow">Static map</p>
|
||||||
|
<h1>Yard Atlas</h1>
|
||||||
|
<p class="intro">
|
||||||
|
MapLibre renders a local PMTiles vector map underneath a client-side
|
||||||
|
geometry pipeline. Source files stay as JavaScript so you can author
|
||||||
|
points and shapes with absolute coordinates or offset math.
|
||||||
|
</p>
|
||||||
|
<div class="legend" id="legend"></div>
|
||||||
|
<section class="notes">
|
||||||
|
<h2>Authoring style</h2>
|
||||||
|
<pre><code>new House()
|
||||||
|
.trace([
|
||||||
|
[-100.8988347540, 46.8268080234],
|
||||||
|
[-100.8986668041, 46.8268307100],
|
||||||
|
])
|
||||||
|
|
||||||
|
new Sprinkler("Front bed sprinkler")
|
||||||
|
.add(offset(lotCorner), south(ft(15)), east(ft(10)))</code></pre>
|
||||||
|
</section>
|
||||||
|
</aside>
|
||||||
|
<main>
|
||||||
|
<div class="map-frame">
|
||||||
|
<p id="map-status" class="map-status" role="status">Loading the map…</p>
|
||||||
|
<div id="map" aria-label="Map of yard"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="./src/error-overlay.js"></script>
|
||||||
|
<script src="./vendor/pmtiles.js"></script>
|
||||||
|
<script src="./vendor/basemaps.js"></script>
|
||||||
|
<script type="module" src="./src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "yardmap",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"check": "node --check src/main.js && node -e \"import('./src/data/yard.js')\""
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@protomaps/basemaps": "^5.7.2",
|
||||||
|
"maplibre-gl": "^6.0.0",
|
||||||
|
"pmtiles": "^4.4.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ $# -lt 1 || $# -gt 2 ]]; then
|
||||||
|
echo "Usage: $0 PROTOMAPS_SOURCE_URL [OUTPUT_FILE]" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v pmtiles >/dev/null 2>&1; then
|
||||||
|
echo "The pmtiles CLI is required: https://docs.protomaps.com/pmtiles/cli" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source_url=$1
|
||||||
|
output_file=${2:-tiles/mandan.pmtiles}
|
||||||
|
|
||||||
|
if [[ -e "$output_file" ]]; then
|
||||||
|
echo "Refusing to overwrite existing file: $output_file" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mandan city plus a modest margin for labels and roads. PMTiles extracts
|
||||||
|
# tile-aligned bounds, so the resulting archive includes some nearby context.
|
||||||
|
pmtiles extract \
|
||||||
|
"$source_url" \
|
||||||
|
"$output_file" \
|
||||||
|
--bbox=-101.05,46.74,-100.75,46.93
|
||||||
|
|
||||||
|
pmtiles show "$output_file"
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-labelledby="title desc">
|
||||||
|
<title id="title">Daylily</title>
|
||||||
|
<desc id="desc">Abstract daylily clump with spindly fronds and flower stalks.</desc>
|
||||||
|
<defs>
|
||||||
|
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||||
|
<feDropShadow dx="0" dy="1.5" stdDeviation="1.2" flood-color="#1d2d16" flood-opacity="0.28" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#shadow)">
|
||||||
|
<g stroke="#315f2b">
|
||||||
|
<path d="M32 58 C24 47 16 40 8 34" stroke-width="3.1" />
|
||||||
|
<path d="M32 58 C25 45 22 35 20 22" stroke-width="2.7" />
|
||||||
|
<path d="M32 58 C30 43 31 29 35 14" stroke-width="2.7" />
|
||||||
|
<path d="M32 58 C40 45 47 37 56 30" stroke-width="3.1" />
|
||||||
|
<path d="M32 58 C38 48 42 40 44 27" stroke-width="2.5" />
|
||||||
|
</g>
|
||||||
|
<g stroke="#5f8d39">
|
||||||
|
<path d="M32 58 C21 51 13 48 5 48" stroke-width="2.4" />
|
||||||
|
<path d="M32 58 C24 49 19 44 13 39" stroke-width="2.2" />
|
||||||
|
<path d="M32 58 C29 47 28 38 29 27" stroke-width="2.2" />
|
||||||
|
<path d="M32 58 C35 47 37 37 40 26" stroke-width="2.2" />
|
||||||
|
<path d="M32 58 C42 50 50 46 60 44" stroke-width="2.4" />
|
||||||
|
<path d="M32 58 C43 53 51 52 58 55" stroke-width="2.1" />
|
||||||
|
</g>
|
||||||
|
<g stroke="#6f7f32">
|
||||||
|
<path d="M32 57 C33 43 34 30 35 16" stroke-width="1.7" />
|
||||||
|
<path d="M31 57 C28 43 27 31 25 18" stroke-width="1.5" />
|
||||||
|
<path d="M33 57 C42 45 47 34 50 22" stroke-width="1.5" />
|
||||||
|
</g>
|
||||||
|
<g fill="#f0b44c" stroke="#9f5e1d" stroke-width="1.4">
|
||||||
|
<path d="M35 15 C30 13 29 8 32 4 C36 7 38 11 35 15" />
|
||||||
|
<path d="M35 15 C39 11 44 12 47 16 C42 18 38 18 35 15" />
|
||||||
|
<path d="M35 15 C39 18 39 23 36 27 C33 23 32 19 35 15" />
|
||||||
|
<circle cx="35" cy="15" r="1.7" fill="#743719" stroke="none" />
|
||||||
|
<path d="M25 18 C21 15 21 11 24 8 C27 11 28 15 25 18" />
|
||||||
|
<path d="M25 18 C29 16 32 18 33 22 C29 23 26 21 25 18" />
|
||||||
|
<path d="M25 18 C23 22 19 23 16 21 C18 17 21 16 25 18" />
|
||||||
|
<circle cx="25" cy="18" r="1.5" fill="#743719" stroke="none" />
|
||||||
|
<path d="M50 22 C46 19 47 15 50 12 C53 15 54 19 50 22" />
|
||||||
|
<path d="M50 22 C54 20 58 22 59 26 C55 27 52 25 50 22" />
|
||||||
|
<path d="M50 22 C49 26 45 28 42 26 C44 23 47 21 50 22" />
|
||||||
|
<circle cx="50" cy="22" r="1.4" fill="#743719" stroke="none" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,33 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-labelledby="title desc">
|
||||||
|
<title id="title">Flower</title>
|
||||||
|
<desc id="desc">Abstract flower with paired leaves and a dahlia-like bloom.</desc>
|
||||||
|
<defs>
|
||||||
|
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
||||||
|
<feDropShadow dx="0" dy="1.5" stdDeviation="1.2" flood-color="#1d2d16" flood-opacity="0.28" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#shadow)">
|
||||||
|
<path d="M32 58 C32 47 32 37 32 26" stroke="#315f2b" stroke-width="3" />
|
||||||
|
<path d="M31 46 C23 38 15 37 9 42 C17 47 24 49 31 46" fill="#5f8d39" stroke="#315f2b" stroke-width="1.8" />
|
||||||
|
<path d="M33 43 C42 35 50 35 56 41 C48 47 40 48 33 43" fill="#6f9d42" stroke="#315f2b" stroke-width="1.8" />
|
||||||
|
<path d="M31 54 C24 50 18 51 13 56 C20 59 26 59 31 54" fill="#547f34" stroke="#315f2b" stroke-width="1.5" />
|
||||||
|
<path d="M33 52 C40 48 47 49 52 55 C45 58 38 58 33 52" fill="#6a963d" stroke="#315f2b" stroke-width="1.5" />
|
||||||
|
<g fill="#c556a0" stroke="#742c5c" stroke-width="1.15">
|
||||||
|
<path d="M32 27 C28 20 29 13 32 7 C36 13 36 20 32 27" />
|
||||||
|
<path d="M32 27 C27 21 22 17 16 16 C18 23 24 27 32 27" />
|
||||||
|
<path d="M32 27 C25 25 19 27 14 32 C21 35 27 33 32 27" />
|
||||||
|
<path d="M32 27 C27 31 24 37 24 44 C30 41 33 35 32 27" />
|
||||||
|
<path d="M32 27 C36 33 42 36 49 36 C46 30 40 27 32 27" />
|
||||||
|
<path d="M32 27 C38 25 43 20 46 14 C39 15 34 20 32 27" />
|
||||||
|
</g>
|
||||||
|
<g fill="#df79bd" stroke="#8f3b75" stroke-width="1">
|
||||||
|
<path d="M32 27 C30 22 31 17 33 12 C36 17 35 23 32 27" />
|
||||||
|
<path d="M32 27 C28 24 25 21 21 20 C22 25 27 28 32 27" />
|
||||||
|
<path d="M32 27 C28 28 24 31 22 35 C27 36 31 33 32 27" />
|
||||||
|
<path d="M32 27 C35 31 39 33 44 33 C42 28 37 26 32 27" />
|
||||||
|
<path d="M32 27 C35 23 38 19 42 17 C41 22 37 26 32 27" />
|
||||||
|
</g>
|
||||||
|
<circle cx="32" cy="27" r="4.4" fill="#7a2d63" stroke="#5f214d" stroke-width="1.1" />
|
||||||
|
<circle cx="32" cy="27" r="2.2" fill="#f0b44c" stroke="none" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
import { anchor } from "../lib/geometry.js";
|
||||||
|
|
||||||
|
export const topLeftLotCorner = anchor(-100.898958, 46.826799, {
|
||||||
|
assumedNorthClockwiseDegrees: -11.25,
|
||||||
|
});
|
||||||
|
export const lotCorner = topLeftLotCorner;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import * as geo from "../lib/geometry.js";
|
||||||
|
import { Fence, LotBoundary } from "../lib/yard-features.js";
|
||||||
|
import { lotCorner } from "./anchors.js";
|
||||||
|
|
||||||
|
const lotBoundary = new LotBoundary()
|
||||||
|
.add(geo.offset(lotCorner))
|
||||||
|
.add(geo.offset(lotCorner), geo.east(geo.ft(144)))
|
||||||
|
.add(geo.offset(lotCorner), geo.east(geo.ft(144)), geo.south(geo.ft(51)))
|
||||||
|
.add(geo.offset(lotCorner), geo.south(geo.ft(51)));
|
||||||
|
|
||||||
|
const picketFence = new Fence("Short picket fence", {
|
||||||
|
fenceType: "Short picket",
|
||||||
|
}).trace([
|
||||||
|
[-100.89860584453643, 46.82671142438681],
|
||||||
|
[-100.89891903869233, 46.82666876370629],
|
||||||
|
[-100.89895733199393, 46.82679939652137],
|
||||||
|
[-100.89883731628171, 46.82681591825169],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const boundaryFeatures = [lotBoundary, picketFence];
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Deck, defineGroup, Garage, House, Porch } from "../lib/yard-features.js";
|
||||||
|
|
||||||
|
export const housePartsGroup = defineGroup("group:house-parts", "House Parts");
|
||||||
|
|
||||||
|
const house = new House().withId("feature:house-main").trace([
|
||||||
|
[-100.89883475400929, 46.826808023423844],
|
||||||
|
[-100.8986668040935, 46.826830709973976],
|
||||||
|
[-100.89866031675769, 46.826807530237865],
|
||||||
|
[-100.89869131180652, 46.82680358474988],
|
||||||
|
[-100.89867545387456, 46.82675525249843],
|
||||||
|
[-100.89881168792644, 46.82673552503637],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const garage = new Garage().trace([
|
||||||
|
[-100.89850173743805, 46.82679569377302],
|
||||||
|
[-100.89839289435957, 46.82681098253964],
|
||||||
|
[-100.89837054909181, 46.82674095008918],
|
||||||
|
[-100.8984801129854, 46.826727140862815],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const porch = new Porch().childOf(house).inGroup(housePartsGroup).trace([
|
||||||
|
[-100.89886286579778, 46.8268040779359],
|
||||||
|
[-100.8988346639074, 46.8268079617756],
|
||||||
|
[-100.8988116428755, 46.8267355250364],
|
||||||
|
[-100.89875969913811, 46.826743015307995],
|
||||||
|
[-100.89875316675139, 46.826722208995406],
|
||||||
|
[-100.8988050654378, 46.82671481119343],
|
||||||
|
[-100.89881515684904, 46.8267162907539],
|
||||||
|
[-100.89882614927917, 46.8267201129516],
|
||||||
|
[-100.89883678130174, 46.82672738745619],
|
||||||
|
[-100.89884281812813, 46.82673191860895],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const deck = new Deck().childOf(house).inGroup(housePartsGroup).trace([
|
||||||
|
[-100.89869090634811, 46.826803553925714],
|
||||||
|
[-100.89864495438617, 46.826809472157606],
|
||||||
|
[-100.89863017767685, 46.8267616330979],
|
||||||
|
[-100.89867522861992, 46.82675522167426],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const buildingFeatures = [house, garage, porch, deck];
|
||||||
|
export const buildingGroups = [housePartsGroup];
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import * as geo from "../lib/geometry.js";
|
||||||
|
import { defineGroup, YardGridLine } from "../lib/yard-features.js";
|
||||||
|
import { lotCorner } from "./anchors.js";
|
||||||
|
|
||||||
|
const GRID_SPACING_FEET = 10;
|
||||||
|
const MIN_EAST_FEET = -20;
|
||||||
|
const MAX_EAST_FEET = 180;
|
||||||
|
const MIN_NORTH_FEET = -140;
|
||||||
|
const MAX_NORTH_FEET = 20;
|
||||||
|
|
||||||
|
export const yardGridGroup = defineGroup("group:yard-grid", "Yard Grid");
|
||||||
|
|
||||||
|
function localPoint(eastFeet, northFeet) {
|
||||||
|
return geo.offset(
|
||||||
|
lotCorner,
|
||||||
|
geo.east(geo.ft(eastFeet)),
|
||||||
|
northFeet >= 0 ? geo.north(geo.ft(northFeet)) : geo.south(geo.ft(Math.abs(northFeet))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeNorthLine(eastFeet) {
|
||||||
|
return new YardGridLine(`Grid east ${eastFeet} ft`, {
|
||||||
|
axis: "north",
|
||||||
|
offsetFeet: eastFeet,
|
||||||
|
spacingFeet: GRID_SPACING_FEET,
|
||||||
|
})
|
||||||
|
.inGroup(yardGridGroup)
|
||||||
|
.add(localPoint(eastFeet, MIN_NORTH_FEET))
|
||||||
|
.add(localPoint(eastFeet, MAX_NORTH_FEET));
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeEastLine(northFeet) {
|
||||||
|
return new YardGridLine(`Grid north ${northFeet} ft`, {
|
||||||
|
axis: "east",
|
||||||
|
offsetFeet: northFeet,
|
||||||
|
spacingFeet: GRID_SPACING_FEET,
|
||||||
|
})
|
||||||
|
.inGroup(yardGridGroup)
|
||||||
|
.add(localPoint(MIN_EAST_FEET, northFeet))
|
||||||
|
.add(localPoint(MAX_EAST_FEET, northFeet));
|
||||||
|
}
|
||||||
|
|
||||||
|
function rangeByFeet(minFeet, maxFeet, spacingFeet) {
|
||||||
|
const values = [];
|
||||||
|
|
||||||
|
for (let value = minFeet; value <= maxFeet; value += spacingFeet) {
|
||||||
|
values.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
const northLines = rangeByFeet(MIN_EAST_FEET, MAX_EAST_FEET, GRID_SPACING_FEET).map(makeNorthLine);
|
||||||
|
const eastLines = rangeByFeet(MIN_NORTH_FEET, MAX_NORTH_FEET, GRID_SPACING_FEET).map(makeEastLine);
|
||||||
|
|
||||||
|
export const gridFeatures = [...northLines, ...eastLines];
|
||||||
|
export const gridGroups = [yardGridGroup];
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { east, ft, offset, south } from "../lib/geometry.js";
|
||||||
|
import { Sprinkler } from "../lib/yard-features.js";
|
||||||
|
import { lotCorner } from "./anchors.js";
|
||||||
|
|
||||||
|
export const irrigationFeatures = [
|
||||||
|
new Sprinkler("Front bed sprinkler").add(offset(lotCorner), south(ft(15)), east(ft(10))),
|
||||||
|
new Sprinkler("Garage side sprinkler").add(offset(lotCorner), south(ft(92)), east(ft(40))),
|
||||||
|
];
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { Driveway, Walkway } from "../lib/yard-features.js";
|
||||||
|
|
||||||
|
const frontWalk = new Walkway("Front walk").trace([
|
||||||
|
[-100.89894913835376, 46.82676927748655],
|
||||||
|
[-100.89887345276941, 46.82677975769509],
|
||||||
|
[-100.89887849847504, 46.82679985503042],
|
||||||
|
[-100.89887651623354, 46.82680417040822],
|
||||||
|
[-100.8988709299166, 46.826808732378645],
|
||||||
|
[-100.89886462278457, 46.82681082841896],
|
||||||
|
[-100.89883254651308, 46.82681514379587],
|
||||||
|
[-100.89883047416976, 46.826808562845976],
|
||||||
|
[-100.89886426237707, 46.82680492559929],
|
||||||
|
[-100.89886660502609, 46.826802891207],
|
||||||
|
[-100.89886716816289, 46.82679990126662],
|
||||||
|
[-100.89886270811955, 46.82678063618305],
|
||||||
|
[-100.89885982485919, 46.82678254727965],
|
||||||
|
[-100.89885694159882, 46.82678341035552],
|
||||||
|
[-100.89885243650448, 46.826766457077134],
|
||||||
|
[-100.89885784261767, 46.82676596389077],
|
||||||
|
[-100.89886288832331, 46.82676682696687],
|
||||||
|
[-100.89886694290817, 46.82676836817423],
|
||||||
|
[-100.8989459622624, 46.826758196205],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const driveway = new Driveway().trace([
|
||||||
|
[-100.89851482473702, 46.82685818966149],
|
||||||
|
[-100.8984941013032, 46.826796541436565],
|
||||||
|
[-100.89837336477572, 46.82681355635369],
|
||||||
|
[-100.89839320971627, 46.8268766687031],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const garageWalk = new Walkway("Garage walk").trace([
|
||||||
|
[-100.89862628077022, 46.82677780036217],
|
||||||
|
[-100.8986050167251, 46.82677755376906],
|
||||||
|
[-100.89853023215954, 46.82678544474858],
|
||||||
|
[-100.89851239198609, 46.82679937725647],
|
||||||
|
[-100.89850049853712, 46.82681602228328],
|
||||||
|
[-100.8984941013032, 46.826796541436565],
|
||||||
|
[-100.89850173743805, 46.82679569377302],
|
||||||
|
[-100.89849635385036, 46.82677854014156],
|
||||||
|
[-100.89862267669479, 46.82676559400101],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const stepPad = new Walkway("Step pad").trace([
|
||||||
|
[-100.89837579752665, 46.82675708653554],
|
||||||
|
[-100.89835705633432, 46.826759675764286],
|
||||||
|
[-100.89835309185132, 46.82674722280572],
|
||||||
|
[-100.89837111222856, 46.82674500346631],
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const pavementFeatures = [frontWalk, driveway, garageWalk, stepPad];
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
import { Daylily, defineGroup, Flower, FlowerBed, Tree } from "../lib/yard-features.js";
|
||||||
|
import * as geo from "../lib/geometry.js";
|
||||||
|
import { lotCorner } from "./anchors.js";
|
||||||
|
|
||||||
|
export const juniperTreesGroup = defineGroup("group:juniper-trees", "Juniper Trees");
|
||||||
|
|
||||||
|
const flowerBeds = [
|
||||||
|
new FlowerBed("Herbs").trace([
|
||||||
|
[-100.89863446807426, 46.82677625460535],
|
||||||
|
[-100.89862628077022, 46.82677780036216],
|
||||||
|
[-100.89863677743469, 46.82681615158733],
|
||||||
|
[-100.89864678466313, 46.826814966528865],
|
||||||
|
]),
|
||||||
|
new FlowerBed("Garden").trace([
|
||||||
|
[-100.89865910125202, 46.82684024777001],
|
||||||
|
[-100.89865409763779, 46.82682773882406],
|
||||||
|
[-100.89853785983037, 46.82684209119338],
|
||||||
|
[-100.89854344078469, 46.82685618021274],
|
||||||
|
]),
|
||||||
|
new FlowerBed("Back day lily").trace([
|
||||||
|
[-100.89854344078469, 46.82685618021274],
|
||||||
|
[-100.89852458100802, 46.82685815530862],
|
||||||
|
[-100.89850764569832, 46.82680482769446],
|
||||||
|
[-100.89851239198609, 46.82679937725647],
|
||||||
|
[-100.89851803782018, 46.82680087749872],
|
||||||
|
[-100.89852554324152, 46.826804564348095],
|
||||||
|
]),
|
||||||
|
new FlowerBed("Coneflowers").trace([
|
||||||
|
[-100.89852458100802, 46.82685815530862],
|
||||||
|
[-100.89851482473702, 46.82685818966149],
|
||||||
|
[-100.89850049853712, 46.82681602228328],
|
||||||
|
[-100.89850764569832, 46.82680482769446],
|
||||||
|
]),
|
||||||
|
new FlowerBed("Pathway border").trace([
|
||||||
|
[-100.89881515684904, 46.82671629075389],
|
||||||
|
[-100.89881830278543, 46.82671252471132],
|
||||||
|
[-100.89882138193263, 46.82670673108083],
|
||||||
|
[-100.89881445385141, 46.8266828981853],
|
||||||
|
[-100.89877269291729, 46.82668908683872],
|
||||||
|
[-100.89877211557717, 46.8266923786754],
|
||||||
|
[-100.89876884398328, 46.82669501214458],
|
||||||
|
[-100.89876326302891, 46.82669764561363],
|
||||||
|
[-100.89875979898829, 46.82670304422476],
|
||||||
|
[-100.89875979898829, 46.826708574508785],
|
||||||
|
[-100.89876461015585, 46.826720556788906],
|
||||||
|
[-100.8988050654378, 46.82671481119343],
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
const daylilies = [
|
||||||
|
new Daylily("Not sure", {
|
||||||
|
gardenOrgId: "4765",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(112)), geo.south(geo.ft(2))),
|
||||||
|
new Daylily("Wayside King Royale", {
|
||||||
|
gardenOrgId: "5090",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(112)), geo.south(geo.ft(4))),
|
||||||
|
new Daylily("Joan Derifield", {
|
||||||
|
gardenOrgId: "4765",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(112)), geo.south(geo.ft(6))),
|
||||||
|
new Daylily("Predatory Flamingo", {
|
||||||
|
gardenOrgId: "61201",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(112)), geo.south(geo.ft(8))),
|
||||||
|
new Daylily("Unknown", {
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(109)), geo.south(geo.ft(7))),
|
||||||
|
new Daylily("Unknown", {
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(109)), geo.south(geo.ft(9))),
|
||||||
|
new Daylily("Unknown", {
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(107)), geo.south(geo.ft(8))),
|
||||||
|
new Daylily("Unknown", {
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(107)), geo.south(geo.ft(10))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(24))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(26))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(28))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(30))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(32))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(34))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(36))),
|
||||||
|
new Daylily("Orange Daylily", {
|
||||||
|
gardenOrgId: "48484",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(38))),
|
||||||
|
new Daylily("You Had Me at Hello", {
|
||||||
|
gardenOrgId: "235117",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(28)), geo.south(geo.ft(45))),
|
||||||
|
new Daylily("Mapping North Dakota", {
|
||||||
|
gardenOrgId: "56003",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(28)), geo.south(geo.ft(47))),
|
||||||
|
new Daylily("Daylily").add(geo.offset(lotCorner), geo.east(geo.ft(31)), geo.south(geo.ft(47))),
|
||||||
|
];
|
||||||
|
|
||||||
|
const flowers = [
|
||||||
|
new Flower("Purple Coneflower", {
|
||||||
|
gardenOrgId: "71445",
|
||||||
|
plantedDate: "2024-05-01",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(111.5)), geo.south(geo.ft(15))),
|
||||||
|
new Flower("Purple Coneflower", {
|
||||||
|
gardenOrgId: "71445",
|
||||||
|
plantedDate: "2024-05-01",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(111.5)), geo.south(geo.ft(17))),
|
||||||
|
new Flower("Purple Coneflower", {
|
||||||
|
gardenOrgId: "71445",
|
||||||
|
plantedDate: "2024-05-01",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(112.5)), geo.south(geo.ft(16))),
|
||||||
|
new Flower("Purple Coneflower", {
|
||||||
|
gardenOrgId: "71445",
|
||||||
|
plantedDate: "2024-05-01",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(112.5)), geo.south(geo.ft(14))),
|
||||||
|
new Flower("Tiny Tortuga Turtlehead", {
|
||||||
|
gardenOrgId: "697986",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(8))),
|
||||||
|
new Flower("Tiny Tortuga Turtlehead", {
|
||||||
|
gardenOrgId: "697986",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(17))),
|
||||||
|
new Flower("Peony", {
|
||||||
|
gardenOrgId: "697986",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(19)), geo.south(geo.ft(1.5))),
|
||||||
|
new Flower("Peony", {
|
||||||
|
gardenOrgId: "697986",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(75)), geo.south(geo.ft(2))),
|
||||||
|
];
|
||||||
|
|
||||||
|
const houseplants = [
|
||||||
|
new Flower("Variegata", {
|
||||||
|
gardenOrgId: "126796",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(60)), geo.south(geo.ft(28))),
|
||||||
|
]
|
||||||
|
|
||||||
|
const cutDownTrees = [
|
||||||
|
new Tree("Maybe elm", {
|
||||||
|
canopyDiameterMeters: 15,
|
||||||
|
heightMeters: 15,
|
||||||
|
removedDate: "2021-05-05",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(65)), geo.south(geo.ft(-2))),
|
||||||
|
new Tree("Big pine tree", {
|
||||||
|
canopyDiameterMeters: 8,
|
||||||
|
heightMeters: 15,
|
||||||
|
removedDate: "2021-05-06",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(98)), geo.south(geo.ft(-15))),
|
||||||
|
new Tree("Walnut by house", {
|
||||||
|
canopyDiameterMeters: 6,
|
||||||
|
heightMeters: 7,
|
||||||
|
removedDate: "2021-05-01",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(32)), geo.south(geo.ft(40))),
|
||||||
|
new Tree("Walnut by shed", {
|
||||||
|
canopyDiameterMeters: 7,
|
||||||
|
heightMeters: 7,
|
||||||
|
removedDate: "2021-05-01",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(100)), geo.south(geo.ft(40))),
|
||||||
|
];
|
||||||
|
|
||||||
|
const trees = [
|
||||||
|
new Tree("Northern Empress Japanese Elm", {
|
||||||
|
species: "Northern Empress Japanese Elm",
|
||||||
|
canopyDiameterMeters: 6,
|
||||||
|
heightMeters: 7,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(9)), geo.south(geo.ft(16))),
|
||||||
|
new Tree("Hot Wings Maple", {
|
||||||
|
species: "Hot Wings Maple",
|
||||||
|
canopyDiameterMeters: 5,
|
||||||
|
heightMeters: 5,
|
||||||
|
gardenOrgId: "536120",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(60)), geo.south(geo.ft(40))),
|
||||||
|
new Tree("Prairie Expedition American Elm", {
|
||||||
|
species: "Prairie Expedition American Elm",
|
||||||
|
canopyDiameterMeters: 5,
|
||||||
|
heightMeters: 5,
|
||||||
|
gardenOrgId: "736267",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(95)), geo.south(geo.ft(15))),
|
||||||
|
new Tree("Dwarf Korean Lilac", {
|
||||||
|
species: "Dwarf Korean Lilac",
|
||||||
|
canopyDiameterMeters: 1.75,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
gardenOrgId: "79137",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(3))),
|
||||||
|
new Tree("Dwarf Korean Lilac", {
|
||||||
|
species: "Dwarf Korean Lilac",
|
||||||
|
canopyDiameterMeters: 1.75,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
gardenOrgId: "79137",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(20))),
|
||||||
|
new Tree("Dwarf Korean Lilac", {
|
||||||
|
species: "Dwarf Korean Lilac",
|
||||||
|
canopyDiameterMeters: 1.75,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
gardenOrgId: "79137",
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(3)), geo.south(geo.ft(37))),
|
||||||
|
new Tree("Boulevard Linden", {
|
||||||
|
species: "Boulevard Linden",
|
||||||
|
canopyDiameterMeters: 3,
|
||||||
|
heightMeters: 6,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.lngLat(-100.8990003556445, 46.826776648309774)),
|
||||||
|
new Tree("Boulevard Linden 2", {
|
||||||
|
species: "Boulevard Linden",
|
||||||
|
canopyDiameterMeters: 3,
|
||||||
|
heightMeters: 6,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).add(geo.lngLat(-100.89898269567485, 46.826709328342595)),
|
||||||
|
new Tree("Evergreen", {
|
||||||
|
species: "Evergreen",
|
||||||
|
canopyDiameterMeters: 8,
|
||||||
|
heightMeters: 15,
|
||||||
|
}).add(geo.lngLat(-100.89888268258135, 46.826680107011924)),
|
||||||
|
];
|
||||||
|
|
||||||
|
const bushes = [
|
||||||
|
new Tree("Medora Juniper 1", {
|
||||||
|
species: "Medora Juniper",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89880933964611, 46.826705259550664)),
|
||||||
|
new Tree("Medora Juniper 2", {
|
||||||
|
species: "Medora Juniper",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89877004677517, 46.82670396593881)),
|
||||||
|
new Tree("Medora Juniper 3", {
|
||||||
|
species: "Medora Juniper",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.898799106227, 46.82669830398086)),
|
||||||
|
new Tree("Medora Juniper 4", {
|
||||||
|
species: "Medora Juniper",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.89878871410515, 46.82669251034885)),
|
||||||
|
new Tree("Medora Juniper 5", {
|
||||||
|
species: "Medora Juniper",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 2.5,
|
||||||
|
plantedDate: "2021-09-21",
|
||||||
|
}).inGroup(juniperTreesGroup).add(geo.lngLat(-100.8987812086838, 46.82671120797719)),
|
||||||
|
new Tree("Black Currant", {
|
||||||
|
species: "Black Currant",
|
||||||
|
canopyDiameterMeters: 2,
|
||||||
|
heightMeters: 2,
|
||||||
|
gardenOrgId: "87767",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(107)), geo.south(geo.ft(3))),
|
||||||
|
new Tree("Elderberry", {
|
||||||
|
species: "Elderberry",
|
||||||
|
canopyDiameterMeters: 3,
|
||||||
|
heightMeters: 3,
|
||||||
|
gardenOrgId: "78882",
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(142)), geo.south(geo.ft(52))),
|
||||||
|
new Tree("Spirea", {
|
||||||
|
species: "Spirea",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 1,
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(70)), geo.south(geo.ft(31))),
|
||||||
|
new Tree("Spirea", {
|
||||||
|
species: "Spirea",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 1,
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(74)), geo.south(geo.ft(31))),
|
||||||
|
new Tree("Spirea", {
|
||||||
|
species: "Spirea",
|
||||||
|
canopyDiameterMeters: 1.5,
|
||||||
|
heightMeters: 1,
|
||||||
|
}).add(geo.offset(lotCorner), geo.east(geo.ft(78)), geo.south(geo.ft(31))),
|
||||||
|
];
|
||||||
|
|
||||||
|
export const plantFeatures = [...flowerBeds, ...daylilies, ...flowers, ...houseplants, ...trees, ...bushes, ...cutDownTrees];
|
||||||
|
export const plantGroups = [juniperTreesGroup];
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { collectYardData } from "../lib/yard-features.js";
|
||||||
|
import { boundaryFeatures } from "./boundaries.js";
|
||||||
|
import { buildingFeatures, buildingGroups } from "./buildings.js";
|
||||||
|
import { gridFeatures, gridGroups } from "./grid.js";
|
||||||
|
import { irrigationFeatures } from "./irrigation.js";
|
||||||
|
import { pavementFeatures } from "./pavement.js";
|
||||||
|
import { plantFeatures, plantGroups } from "./plants.js";
|
||||||
|
|
||||||
|
export const yardGeoJSON = collectYardData(
|
||||||
|
[
|
||||||
|
...boundaryFeatures,
|
||||||
|
...gridFeatures,
|
||||||
|
...buildingFeatures,
|
||||||
|
...pavementFeatures,
|
||||||
|
...plantFeatures,
|
||||||
|
...irrigationFeatures,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
...buildingGroups,
|
||||||
|
...gridGroups,
|
||||||
|
...plantGroups,
|
||||||
|
],
|
||||||
|
);
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
const overlay = document.createElement("section");
|
||||||
|
overlay.className = "error-overlay";
|
||||||
|
overlay.hidden = true;
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="error-overlay-header">
|
||||||
|
<strong>JavaScript error</strong>
|
||||||
|
<div class="error-overlay-actions">
|
||||||
|
<button type="button" data-action="copy">Copy</button>
|
||||||
|
<button type="button" data-action="dismiss" aria-label="Dismiss error">Dismiss</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<pre></pre>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const messageNode = overlay.querySelector("pre");
|
||||||
|
const copyButton = overlay.querySelector("[data-action='copy']");
|
||||||
|
const dismissButton = overlay.querySelector("[data-action='dismiss']");
|
||||||
|
|
||||||
|
copyButton.addEventListener("click", async () => {
|
||||||
|
await copyText(messageNode.textContent);
|
||||||
|
showCopyStatus();
|
||||||
|
});
|
||||||
|
|
||||||
|
dismissButton.addEventListener("click", () => {
|
||||||
|
overlay.hidden = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
document.body.append(overlay);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("error", (event) => {
|
||||||
|
showError(formatErrorEvent(event));
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("unhandledrejection", (event) => {
|
||||||
|
showError(formatReason(event.reason));
|
||||||
|
});
|
||||||
|
|
||||||
|
function showError(message) {
|
||||||
|
messageNode.textContent = message;
|
||||||
|
copyButton.textContent = "Copy";
|
||||||
|
overlay.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyText(value) {
|
||||||
|
if (navigator.clipboard?.writeText) {
|
||||||
|
await navigator.clipboard.writeText(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textArea = document.createElement("textarea");
|
||||||
|
textArea.value = value;
|
||||||
|
textArea.setAttribute("readonly", "");
|
||||||
|
textArea.className = "error-overlay-copy-buffer";
|
||||||
|
document.body.append(textArea);
|
||||||
|
textArea.select();
|
||||||
|
document.execCommand("copy");
|
||||||
|
textArea.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showCopyStatus() {
|
||||||
|
copyButton.textContent = "Copied";
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
copyButton.textContent = "Copy";
|
||||||
|
}, 1400);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatErrorEvent(event) {
|
||||||
|
const location = [event.filename, event.lineno, event.colno].filter(Boolean).join(":");
|
||||||
|
const detail = formatReason(event.error ?? event.message);
|
||||||
|
return location ? `${detail}\n\n${location}` : detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatReason(reason) {
|
||||||
|
if (reason instanceof Error) {
|
||||||
|
return reason.stack ?? `${reason.name}: ${reason.message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(reason);
|
||||||
|
}
|
||||||
@@ -0,0 +1,311 @@
|
|||||||
|
export const featureTypes = {
|
||||||
|
lotBoundary: {
|
||||||
|
label: "Lot Boundary",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#7b684d",
|
||||||
|
weight: 2,
|
||||||
|
dashArray: "8 5",
|
||||||
|
fillColor: "#dccaab",
|
||||||
|
fillOpacity: 0.08,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fence: {
|
||||||
|
label: "Fence",
|
||||||
|
geometryType: "LineString",
|
||||||
|
detailFields: {
|
||||||
|
fenceType: "string",
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "#705033",
|
||||||
|
weight: 4,
|
||||||
|
opacity: 0.95,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yardGrid: {
|
||||||
|
label: "Yard Grid",
|
||||||
|
geometryType: "LineString",
|
||||||
|
detailFields: {
|
||||||
|
axis: "string",
|
||||||
|
offsetFeet: "number",
|
||||||
|
spacingFeet: "number",
|
||||||
|
},
|
||||||
|
style: (details) => ({
|
||||||
|
color: details.offsetFeet === 0 ? "#1f4f63" : "#2f7f98",
|
||||||
|
weight: details.offsetFeet === 0 ? 3 : 2,
|
||||||
|
opacity: details.offsetFeet === 0 ? 0.75 : 0.55,
|
||||||
|
dashArray: details.offsetFeet === 0 ? undefined : "6 5",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
house: {
|
||||||
|
label: "House",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#8d5a35",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#c98d58",
|
||||||
|
fillOpacity: 0.35,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
garage: {
|
||||||
|
label: "Garage",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#60636b",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#a4acb9",
|
||||||
|
fillOpacity: 0.45,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
porch: {
|
||||||
|
label: "Porch",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#aa7148",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#deb588",
|
||||||
|
fillOpacity: 0.38,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
deck: {
|
||||||
|
label: "Deck",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#7f5a3c",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#b98c66",
|
||||||
|
fillOpacity: 0.32,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
walkway: {
|
||||||
|
label: "Walkway",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#b8b3a6",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#d6d1c3",
|
||||||
|
fillOpacity: 0.75,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
driveway: {
|
||||||
|
label: "Driveway",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {},
|
||||||
|
style: {
|
||||||
|
color: "#9c9890",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#bbb7af",
|
||||||
|
fillOpacity: 0.8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flowerBed: {
|
||||||
|
label: "Flower Bed",
|
||||||
|
geometryType: "Polygon",
|
||||||
|
detailFields: {
|
||||||
|
soil: "string",
|
||||||
|
mulch: "string",
|
||||||
|
sunExposure: "string",
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "#7f7f31",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#bfc97b",
|
||||||
|
fillOpacity: 0.38,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plant: {
|
||||||
|
label: "Plant",
|
||||||
|
geometryType: "Point",
|
||||||
|
detailFields: {
|
||||||
|
commonName: "string",
|
||||||
|
genus: "string",
|
||||||
|
species: "string",
|
||||||
|
cultivar: "string",
|
||||||
|
gardenOrgId: "string",
|
||||||
|
note: "string",
|
||||||
|
},
|
||||||
|
externalLinks: [
|
||||||
|
{
|
||||||
|
label: "Garden.org",
|
||||||
|
url: (details) =>
|
||||||
|
details.gardenOrgId
|
||||||
|
? `https://garden.org/plants/view/${encodeURIComponent(details.gardenOrgId)}/`
|
||||||
|
: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
style: {
|
||||||
|
color: "#3d7140",
|
||||||
|
weight: 2,
|
||||||
|
radius: 5,
|
||||||
|
fillColor: "#78a658",
|
||||||
|
fillOpacity: 0.8,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flower: {
|
||||||
|
label: "Flower",
|
||||||
|
parentKind: "plant",
|
||||||
|
geometryType: "Point",
|
||||||
|
detailFields: {
|
||||||
|
commonName: "string",
|
||||||
|
genus: "string",
|
||||||
|
species: "string",
|
||||||
|
cultivar: "string",
|
||||||
|
bloomColor: "string",
|
||||||
|
bloomSeason: "string",
|
||||||
|
note: "string",
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "#9c3f74",
|
||||||
|
weight: 2,
|
||||||
|
fillColor: "#d979aa",
|
||||||
|
fillOpacity: 0.85,
|
||||||
|
iconUrl: "./src/assets/icons/flower.svg",
|
||||||
|
iconDiameterMeters: 0.4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
daylily: {
|
||||||
|
label: "Daylily",
|
||||||
|
parentKind: "flower",
|
||||||
|
geometryType: "Point",
|
||||||
|
detailFields: {
|
||||||
|
commonName: "string",
|
||||||
|
genus: "string",
|
||||||
|
cultivar: "string",
|
||||||
|
bloomColor: "string",
|
||||||
|
bloomSeason: "string",
|
||||||
|
note: "string",
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "#9f5e1d",
|
||||||
|
weight: 2,
|
||||||
|
radius: 5,
|
||||||
|
fillColor: "#f0b44c",
|
||||||
|
fillOpacity: 0.88,
|
||||||
|
iconUrl: "./src/assets/icons/daylily.svg",
|
||||||
|
iconDiameterMeters: 2.5 / 3.280839895,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shrub: {
|
||||||
|
label: "Shrub",
|
||||||
|
parentKind: "plant",
|
||||||
|
geometryType: "Point",
|
||||||
|
detailFields: {
|
||||||
|
commonName: "string",
|
||||||
|
genus: "string",
|
||||||
|
species: "string",
|
||||||
|
cultivar: "string",
|
||||||
|
canopyDiameterMeters: "number",
|
||||||
|
heightMeters: "number",
|
||||||
|
note: "string",
|
||||||
|
},
|
||||||
|
style: (details) => ({
|
||||||
|
color: "#426a3d",
|
||||||
|
weight: 1,
|
||||||
|
radiusMeters: (details.canopyDiameterMeters ?? 1) / 2,
|
||||||
|
fillColor: "#7e9d58",
|
||||||
|
fillOpacity: 0.62,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
tree: {
|
||||||
|
label: "Tree",
|
||||||
|
parentKind: "plant",
|
||||||
|
geometryType: "Point",
|
||||||
|
detailFields: {
|
||||||
|
commonName: "string",
|
||||||
|
genus: "string",
|
||||||
|
species: "string",
|
||||||
|
cultivar: "string",
|
||||||
|
canopyDiameterMeters: "number",
|
||||||
|
heightMeters: "number",
|
||||||
|
note: "string",
|
||||||
|
},
|
||||||
|
style: (details) => ({
|
||||||
|
color: "#2f6b3d",
|
||||||
|
weight: 1,
|
||||||
|
radiusMeters: (details.canopyDiameterMeters ?? 2) / 2,
|
||||||
|
fillColor: "#5c9e64",
|
||||||
|
fillOpacity: 0.55,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
sprinkler: {
|
||||||
|
label: "Sprinkler",
|
||||||
|
geometryType: "Point",
|
||||||
|
detailFields: {
|
||||||
|
zone: "string",
|
||||||
|
headType: "string",
|
||||||
|
flowRateGallonsPerMinute: "number",
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "#2d7dd2",
|
||||||
|
radius: 5,
|
||||||
|
fillColor: "#88bdf2",
|
||||||
|
fillOpacity: 0.95,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getFeatureType(kind) {
|
||||||
|
const definition = featureTypes[kind];
|
||||||
|
if (!definition) {
|
||||||
|
throw new Error(`Unknown feature type: ${kind}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listFeatureTypeSchemas() {
|
||||||
|
return Object.entries(featureTypes).map(([kind, definition]) => ({
|
||||||
|
kind,
|
||||||
|
label: definition.label,
|
||||||
|
parentKind: definition.parentKind ?? null,
|
||||||
|
geometryType: definition.geometryType,
|
||||||
|
detailFields: getInheritedDetailFields(kind),
|
||||||
|
externalLinks: getInheritedExternalLinks(kind).map((link) => ({
|
||||||
|
label: link.label,
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveFeatureStyle(kind, details = {}) {
|
||||||
|
const { style } = getFeatureType(kind);
|
||||||
|
return typeof style === "function" ? style(details) : { ...style };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveFeatureLinks(kind, details = {}) {
|
||||||
|
return getInheritedExternalLinks(kind)
|
||||||
|
.map((link) => ({
|
||||||
|
label: link.label,
|
||||||
|
url: link.url(details),
|
||||||
|
}))
|
||||||
|
.filter((link) => link.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFeatureTypeLineage(kind) {
|
||||||
|
const lineage = [];
|
||||||
|
let currentKind = kind;
|
||||||
|
|
||||||
|
while (currentKind) {
|
||||||
|
const definition = getFeatureType(currentKind);
|
||||||
|
lineage.unshift(definition);
|
||||||
|
currentKind = definition.parentKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lineage;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInheritedDetailFields(kind) {
|
||||||
|
return Object.assign(
|
||||||
|
{},
|
||||||
|
...getFeatureTypeLineage(kind).map((definition) => definition.detailFields ?? {}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInheritedExternalLinks(kind) {
|
||||||
|
return getFeatureTypeLineage(kind).flatMap((definition) => definition.externalLinks ?? []);
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
const FEET_PER_METER = 3.280839895;
|
||||||
|
const METERS_PER_FOOT = 1 / FEET_PER_METER;
|
||||||
|
const EARTH_METERS_PER_DEGREE_LAT = 111320;
|
||||||
|
|
||||||
|
function toRadians(value) {
|
||||||
|
return (value * Math.PI) / 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotateLocalToTrueNorthEast(northMeters, eastMeters, assumedNorthClockwiseDegrees = 0) {
|
||||||
|
const clockwiseRadians = toRadians(assumedNorthClockwiseDegrees);
|
||||||
|
const trueNorthMeters =
|
||||||
|
northMeters * Math.cos(clockwiseRadians) - eastMeters * Math.sin(clockwiseRadians);
|
||||||
|
const trueEastMeters =
|
||||||
|
northMeters * Math.sin(clockwiseRadians) + eastMeters * Math.cos(clockwiseRadians);
|
||||||
|
|
||||||
|
return {
|
||||||
|
northMeters: trueNorthMeters,
|
||||||
|
eastMeters: trueEastMeters,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function point(lat, lon) {
|
||||||
|
return { lat, lon };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lngLat(lon, lat) {
|
||||||
|
return point(lat, lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function anchor(lon, lat, options = {}) {
|
||||||
|
return {
|
||||||
|
...lngLat(lon, lat),
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pointsFromLngLat(coordinates) {
|
||||||
|
return coordinates.map(([lon, lat]) => lngLat(lon, lat));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ft(value) {
|
||||||
|
return value * METERS_PER_FOOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPoint(value) {
|
||||||
|
return Boolean(value) && typeof value.lat === "number" && typeof value.lon === "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMove(value) {
|
||||||
|
return (
|
||||||
|
Boolean(value) &&
|
||||||
|
typeof value.northMeters === "number" &&
|
||||||
|
typeof value.eastMeters === "number"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOffsetAnchor(value) {
|
||||||
|
return Boolean(value) && value.kind === "offset-anchor" && isPoint(value.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
function translate(origin, northMeters, eastMeters) {
|
||||||
|
const latDelta = northMeters / EARTH_METERS_PER_DEGREE_LAT;
|
||||||
|
const lonDelta = eastMeters / (EARTH_METERS_PER_DEGREE_LAT * Math.cos(toRadians(origin.lat)));
|
||||||
|
|
||||||
|
return point(origin.lat + latDelta, origin.lon + lonDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function offset(origin, ...moves) {
|
||||||
|
if (moves.length === 0) {
|
||||||
|
return { kind: "offset-anchor", origin };
|
||||||
|
}
|
||||||
|
|
||||||
|
const net = moves.reduce(
|
||||||
|
(accumulator, move) => ({
|
||||||
|
northMeters: accumulator.northMeters + move.northMeters,
|
||||||
|
eastMeters: accumulator.eastMeters + move.eastMeters,
|
||||||
|
}),
|
||||||
|
{ northMeters: 0, eastMeters: 0 },
|
||||||
|
);
|
||||||
|
|
||||||
|
const adjusted = rotateLocalToTrueNorthEast(
|
||||||
|
net.northMeters,
|
||||||
|
net.eastMeters,
|
||||||
|
origin.assumedNorthClockwiseDegrees ?? 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
return translate(origin, adjusted.northMeters, adjusted.eastMeters);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function north(distanceMeters) {
|
||||||
|
return { northMeters: distanceMeters, eastMeters: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function south(distanceMeters) {
|
||||||
|
return { northMeters: -distanceMeters, eastMeters: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function east(distanceMeters) {
|
||||||
|
return { northMeters: 0, eastMeters: distanceMeters };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function west(distanceMeters) {
|
||||||
|
return { northMeters: 0, eastMeters: -distanceMeters };
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildFeature(type, geometryType, style = {}) {
|
||||||
|
const coordinates = [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
add(...values) {
|
||||||
|
coordinates.push(resolveCoordinate(values));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
toGeoJSON() {
|
||||||
|
if (geometryType === "Point") {
|
||||||
|
const [first] = coordinates;
|
||||||
|
return {
|
||||||
|
type: "Feature",
|
||||||
|
properties: { type, style },
|
||||||
|
geometry: {
|
||||||
|
type: "Point",
|
||||||
|
coordinates: [first.lon, first.lat],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const ring = coordinates.map((coordinate) => [coordinate.lon, coordinate.lat]);
|
||||||
|
const geometry =
|
||||||
|
geometryType === "LineString"
|
||||||
|
? { type: "LineString", coordinates: ring }
|
||||||
|
: { type: "Polygon", coordinates: [closeRing(ring)] };
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "Feature",
|
||||||
|
properties: { type, style },
|
||||||
|
geometry,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveCoordinate(values) {
|
||||||
|
if (values.length === 1 && isPoint(values[0])) {
|
||||||
|
return values[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const [first, ...rest] = values;
|
||||||
|
if (isOffsetAnchor(first) && rest.every(isMove)) {
|
||||||
|
return offset(first.origin, ...rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("add(...) expects a point, or offset(origin) followed by directional moves");
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeRing(coordinates) {
|
||||||
|
if (coordinates.length === 0) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [firstLon, firstLat] = coordinates[0];
|
||||||
|
const [lastLon, lastLat] = coordinates[coordinates.length - 1];
|
||||||
|
if (firstLon === lastLon && firstLat === lastLat) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...coordinates, coordinates[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function polygon(type, style) {
|
||||||
|
return buildFeature(type, "Polygon", style);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function path(type, style) {
|
||||||
|
return buildFeature(type, "LineString", style);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function marker(type, style) {
|
||||||
|
return buildFeature(type, "Point", style);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sprinkler(name) {
|
||||||
|
return marker(name, {
|
||||||
|
color: "#2d7dd2",
|
||||||
|
radius: 5,
|
||||||
|
fillColor: "#88bdf2",
|
||||||
|
fillOpacity: 0.95,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tree(name) {
|
||||||
|
return marker(name, {
|
||||||
|
color: "#2f6b3d",
|
||||||
|
radius: 9,
|
||||||
|
fillColor: "#5c9e64",
|
||||||
|
fillOpacity: 0.85,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function collectGeoJSON(...collections) {
|
||||||
|
return {
|
||||||
|
type: "FeatureCollection",
|
||||||
|
features: collections.flat().map((entry) => entry.toGeoJSON()),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
import { collectGeoJSON, offset, pointsFromLngLat } from "./geometry.js";
|
||||||
|
import { getFeatureType, listFeatureTypeSchemas } from "./feature-types.js";
|
||||||
|
|
||||||
|
export const YARD_SCHEMA_VERSION = 2;
|
||||||
|
|
||||||
|
class YardFeature {
|
||||||
|
constructor(kind, geometryType, name, details = {}) {
|
||||||
|
const featureType = getFeatureType(kind);
|
||||||
|
if (featureType.geometryType !== geometryType) {
|
||||||
|
throw new Error(
|
||||||
|
`${kind} features must use ${featureType.geometryType} geometry, got ${geometryType}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.kind = kind;
|
||||||
|
this.geometryType = geometryType;
|
||||||
|
this.name = name ?? featureType.label;
|
||||||
|
this.id = buildFeatureId(kind, this.name);
|
||||||
|
const { plantedDate = null, removedDate = null, ...restDetails } = details;
|
||||||
|
this.plantedDate = plantedDate;
|
||||||
|
this.removedDate = removedDate;
|
||||||
|
this.details = { ...restDetails };
|
||||||
|
this.coordinates = [];
|
||||||
|
this.parentId = null;
|
||||||
|
this.groupIds = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
add(...values) {
|
||||||
|
this.coordinates.push(resolveCoordinate(values));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace(coordinates) {
|
||||||
|
for (const coordinate of pointsFromLngLat(coordinates)) {
|
||||||
|
this.add(coordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
withDetails(details) {
|
||||||
|
Object.assign(this.details, details);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
withId(id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
plantedOn(plantedDate) {
|
||||||
|
this.plantedDate = plantedDate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
removedOn(removedDate) {
|
||||||
|
this.removedDate = removedDate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
withLifecycleDates(plantedDate, removedDate = null) {
|
||||||
|
this.plantedDate = plantedDate;
|
||||||
|
this.removedDate = removedDate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
childOf(parent) {
|
||||||
|
this.parentId = resolveFeatureReference(parent);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inGroup(...groups) {
|
||||||
|
this.groupIds.push(...groups.map(resolveGroupReference));
|
||||||
|
this.groupIds = [...new Set(this.groupIds)];
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toGeoJSON() {
|
||||||
|
const label = getFeatureType(this.kind).label;
|
||||||
|
const properties = {
|
||||||
|
id: this.id,
|
||||||
|
kind: this.kind,
|
||||||
|
label,
|
||||||
|
name: this.name,
|
||||||
|
plantedDate: this.plantedDate,
|
||||||
|
removedDate: this.removedDate,
|
||||||
|
parentId: this.parentId,
|
||||||
|
groupIds: this.groupIds,
|
||||||
|
details: this.details,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.geometryType === "Point") {
|
||||||
|
const [first] = this.coordinates;
|
||||||
|
return {
|
||||||
|
type: "Feature",
|
||||||
|
properties,
|
||||||
|
geometry: {
|
||||||
|
type: "Point",
|
||||||
|
coordinates: [first.lon, first.lat],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const coordinates = this.coordinates.map((coordinate) => [coordinate.lon, coordinate.lat]);
|
||||||
|
const geometry =
|
||||||
|
this.geometryType === "LineString"
|
||||||
|
? { type: "LineString", coordinates }
|
||||||
|
: { type: "Polygon", coordinates: [closeRing(coordinates)] };
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "Feature",
|
||||||
|
properties,
|
||||||
|
geometry,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildFeatureId(kind, name) {
|
||||||
|
return `${kind}:${slugify(name)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function slugify(value) {
|
||||||
|
return String(value)
|
||||||
|
.toLowerCase()
|
||||||
|
.replaceAll(/[^a-z0-9]+/g, "-")
|
||||||
|
.replaceAll(/^-+|-+$/g, "")
|
||||||
|
.replaceAll(/-{2,}/g, "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveFeatureReference(featureOrId) {
|
||||||
|
if (typeof featureOrId === "string") {
|
||||||
|
return featureOrId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featureOrId && typeof featureOrId.id === "string") {
|
||||||
|
return featureOrId.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("Expected a feature or feature id");
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveGroupReference(groupOrId) {
|
||||||
|
if (typeof groupOrId === "string") {
|
||||||
|
return groupOrId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupOrId && typeof groupOrId.id === "string") {
|
||||||
|
return groupOrId.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("Expected a group or group id");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function defineGroup(id, label, options = {}) {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
parentGroupId: options.parentGroupId ?? null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class PolygonFeature extends YardFeature {
|
||||||
|
constructor(kind, name, details) {
|
||||||
|
super(kind, "Polygon", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LineFeature extends YardFeature {
|
||||||
|
constructor(kind, name, details) {
|
||||||
|
super(kind, "LineString", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PointFeature extends YardFeature {
|
||||||
|
constructor(kind, name, details) {
|
||||||
|
super(kind, "Point", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeRing(coordinates) {
|
||||||
|
if (coordinates.length === 0) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [firstLon, firstLat] = coordinates[0];
|
||||||
|
const [lastLon, lastLat] = coordinates[coordinates.length - 1];
|
||||||
|
if (firstLon === lastLon && firstLat === lastLat) {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...coordinates, coordinates[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPoint(value) {
|
||||||
|
return Boolean(value) && typeof value.lat === "number" && typeof value.lon === "number";
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMove(value) {
|
||||||
|
return (
|
||||||
|
Boolean(value) &&
|
||||||
|
typeof value.northMeters === "number" &&
|
||||||
|
typeof value.eastMeters === "number"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOffsetAnchor(value) {
|
||||||
|
return Boolean(value) && value.kind === "offset-anchor" && isPoint(value.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveCoordinate(values) {
|
||||||
|
if (values.length === 1 && isPoint(values[0])) {
|
||||||
|
return values[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const [first, ...rest] = values;
|
||||||
|
if (isOffsetAnchor(first) && rest.every(isMove)) {
|
||||||
|
if (rest.length === 0) {
|
||||||
|
return first.origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset(first.origin, ...rest);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("add(...) expects a point, or offset(origin) followed by directional moves");
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LotBoundary extends PolygonFeature {
|
||||||
|
constructor(name = "Lot Boundary", details = {}) {
|
||||||
|
super("lotBoundary", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Fence extends LineFeature {
|
||||||
|
constructor(name = "Fence", details = {}) {
|
||||||
|
super("fence", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class YardGridLine extends LineFeature {
|
||||||
|
constructor(name = "Yard Grid", details = {}) {
|
||||||
|
super("yardGrid", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class House extends PolygonFeature {
|
||||||
|
constructor(name = "House", details = {}) {
|
||||||
|
super("house", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Garage extends PolygonFeature {
|
||||||
|
constructor(name = "Garage", details = {}) {
|
||||||
|
super("garage", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Porch extends PolygonFeature {
|
||||||
|
constructor(name = "Porch", details = {}) {
|
||||||
|
super("porch", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Deck extends PolygonFeature {
|
||||||
|
constructor(name = "Deck", details = {}) {
|
||||||
|
super("deck", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Walkway extends PolygonFeature {
|
||||||
|
constructor(name = "Walkway", details = {}) {
|
||||||
|
super("walkway", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Driveway extends PolygonFeature {
|
||||||
|
constructor(name = "Driveway", details = {}) {
|
||||||
|
super("driveway", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FlowerBed extends PolygonFeature {
|
||||||
|
constructor(name = "Flower Bed", details = {}) {
|
||||||
|
super("flowerBed", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Plant extends PointFeature {
|
||||||
|
constructor(name = "Plant", details = {}, kind = "plant") {
|
||||||
|
super(kind, name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Flower extends Plant {
|
||||||
|
constructor(name = "Flower", details = {}, kind = "flower") {
|
||||||
|
super(name, details, kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Daylily extends Flower {
|
||||||
|
constructor(name = "Daylily", details = {}) {
|
||||||
|
super(name, {
|
||||||
|
commonName: "Daylily",
|
||||||
|
genus: "Hemerocallis",
|
||||||
|
...details,
|
||||||
|
}, "daylily");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Shrub extends Plant {
|
||||||
|
constructor(name = "Shrub", details = {}) {
|
||||||
|
super(name, details, "shrub");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Bush extends Shrub {
|
||||||
|
constructor(name = "Bush", details = {}) {
|
||||||
|
super(name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Tree extends Plant {
|
||||||
|
constructor(name = "Tree", details = {}) {
|
||||||
|
super(name, details, "tree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Sprinkler extends PointFeature {
|
||||||
|
constructor(name = "Sprinkler", details = {}) {
|
||||||
|
super("sprinkler", name, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function collectYardData(features, groups = []) {
|
||||||
|
const collection = collectGeoJSON(features);
|
||||||
|
collection.schemaVersion = YARD_SCHEMA_VERSION;
|
||||||
|
collection.lifecycleFields = {
|
||||||
|
plantedDate: "date",
|
||||||
|
removedDate: "date",
|
||||||
|
};
|
||||||
|
collection.featureTypes = listFeatureTypeSchemas();
|
||||||
|
collection.groups = groups.map((group) => ({
|
||||||
|
id: group.id,
|
||||||
|
label: group.label,
|
||||||
|
parentGroupId: group.parentGroupId ?? null,
|
||||||
|
}));
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { collectGeoJSON };
|
||||||
@@ -0,0 +1,403 @@
|
|||||||
|
import {
|
||||||
|
Map as MapLibreMap,
|
||||||
|
NavigationControl,
|
||||||
|
Popup,
|
||||||
|
addProtocol,
|
||||||
|
} from "../vendor/maplibre/maplibre-gl.mjs";
|
||||||
|
import { yardGeoJSON } from "./data/yard.js";
|
||||||
|
import { resolveFeatureLinks, resolveFeatureStyle } from "./lib/feature-types.js";
|
||||||
|
|
||||||
|
const MAP_MAX_ZOOM = 24;
|
||||||
|
const MANDAN_BOUNDS = [
|
||||||
|
[-101.05, 46.74],
|
||||||
|
[-100.75, 46.93],
|
||||||
|
];
|
||||||
|
const TIMELINE_PRESETS = [
|
||||||
|
{ id: "purchase", label: "Axvigs purchase house", date: "2021-02-01" },
|
||||||
|
{ id: "trees-2021", label: "2021 trees planted", date: "2021-09-22" },
|
||||||
|
{ id: "today", label: "Today", date: getTodayDateString() },
|
||||||
|
];
|
||||||
|
|
||||||
|
const mapElement = document.getElementById("map");
|
||||||
|
const statusElement = document.getElementById("map-status");
|
||||||
|
const legend = document.getElementById("legend");
|
||||||
|
const protocol = new globalThis.pmtiles.Protocol();
|
||||||
|
addProtocol("pmtiles", protocol.tile);
|
||||||
|
const basemapLayers = globalThis.basemaps
|
||||||
|
.layers("protomaps", globalThis.basemaps.namedFlavor("light"), { lang: "en" })
|
||||||
|
.filter((layer) => layer.type !== "symbol");
|
||||||
|
|
||||||
|
const map = new MapLibreMap({
|
||||||
|
container: mapElement,
|
||||||
|
center: [-100.89875, 46.82682],
|
||||||
|
zoom: 20,
|
||||||
|
maxZoom: MAP_MAX_ZOOM,
|
||||||
|
maxBounds: MANDAN_BOUNDS,
|
||||||
|
style: {
|
||||||
|
version: 8,
|
||||||
|
sources: {
|
||||||
|
protomaps: {
|
||||||
|
type: "vector",
|
||||||
|
url: `pmtiles://${new URL("./tiles/mandan.pmtiles", document.baseURI).href}`,
|
||||||
|
attribution:
|
||||||
|
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
layers: basemapLayers,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
map.addControl(new NavigationControl(), "bottom-right");
|
||||||
|
|
||||||
|
let selectedTimelineDate = TIMELINE_PRESETS.at(-1).date;
|
||||||
|
let renderedLayerIds = [];
|
||||||
|
let renderedSourceIds = [];
|
||||||
|
let renderedLayerHandlers = [];
|
||||||
|
|
||||||
|
map.on("load", () => {
|
||||||
|
renderYardForDate(selectedTimelineDate);
|
||||||
|
addTimelineControl();
|
||||||
|
map.fitBounds(getGeoJSONBounds(yardGeoJSON), {
|
||||||
|
padding: 70,
|
||||||
|
maxZoom: MAP_MAX_ZOOM,
|
||||||
|
duration: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
map.on("sourcedata", (event) => {
|
||||||
|
if (event.sourceId === "protomaps" && event.isSourceLoaded) {
|
||||||
|
statusElement.hidden = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
map.on("error", (event) => {
|
||||||
|
const message = event.error?.message || "The vector tile archive could not be loaded.";
|
||||||
|
statusElement.textContent = `Map unavailable: ${message}`;
|
||||||
|
statusElement.hidden = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderYardForDate(date) {
|
||||||
|
removeRenderedYard();
|
||||||
|
const features = yardGeoJSON.features.filter((feature) => featureExistsOnDate(feature, date));
|
||||||
|
|
||||||
|
features.forEach((feature, index) => addFeatureLayer(feature, index));
|
||||||
|
renderLegend(features);
|
||||||
|
syncTimelineButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeRenderedYard() {
|
||||||
|
for (const { layerId, event, handler } of renderedLayerHandlers) {
|
||||||
|
map.off(event, layerId, handler);
|
||||||
|
}
|
||||||
|
for (const layerId of renderedLayerIds.reverse()) {
|
||||||
|
if (map.getLayer(layerId)) {
|
||||||
|
map.removeLayer(layerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const sourceId of renderedSourceIds) {
|
||||||
|
if (map.getSource(sourceId)) {
|
||||||
|
map.removeSource(sourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderedLayerIds = [];
|
||||||
|
renderedSourceIds = [];
|
||||||
|
renderedLayerHandlers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function addFeatureLayer(feature, index) {
|
||||||
|
const sourceId = `yard-source-${index}`;
|
||||||
|
const layerId = `yard-layer-${index}`;
|
||||||
|
const style = resolveFeatureStyle(feature.properties.kind, feature.properties.details);
|
||||||
|
const layer = buildMapLibreLayer(layerId, sourceId, feature, style);
|
||||||
|
|
||||||
|
map.addSource(sourceId, { type: "geojson", data: feature });
|
||||||
|
map.addLayer(layer);
|
||||||
|
renderedSourceIds.push(sourceId);
|
||||||
|
renderedLayerIds.push(layerId);
|
||||||
|
|
||||||
|
const handleMouseEnter = () => {
|
||||||
|
map.getCanvas().style.cursor = "pointer";
|
||||||
|
};
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
map.getCanvas().style.cursor = "";
|
||||||
|
};
|
||||||
|
const handleClick = (event) => {
|
||||||
|
const coordinates =
|
||||||
|
feature.geometry.type === "Point"
|
||||||
|
? feature.geometry.coordinates
|
||||||
|
: [event.lngLat.lng, event.lngLat.lat];
|
||||||
|
new Popup({ offset: 10 })
|
||||||
|
.setLngLat(coordinates)
|
||||||
|
.setHTML(buildPopupContent(feature.properties))
|
||||||
|
.addTo(map);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [event, handler] of [
|
||||||
|
["mouseenter", handleMouseEnter],
|
||||||
|
["mouseleave", handleMouseLeave],
|
||||||
|
["click", handleClick],
|
||||||
|
]) {
|
||||||
|
map.on(event, layerId, handler);
|
||||||
|
renderedLayerHandlers.push({ layerId, event, handler });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMapLibreLayer(id, source, feature, style) {
|
||||||
|
if (feature.geometry.type === "Polygon" || feature.geometry.type === "MultiPolygon") {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
source,
|
||||||
|
type: "fill",
|
||||||
|
paint: {
|
||||||
|
"fill-color": style.fillColor ?? style.color ?? "#333333",
|
||||||
|
"fill-opacity": style.fillOpacity ?? 0.25,
|
||||||
|
"fill-outline-color": style.color ?? "#333333",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feature.geometry.type === "LineString" || feature.geometry.type === "MultiLineString") {
|
||||||
|
const layer = {
|
||||||
|
id,
|
||||||
|
source,
|
||||||
|
type: "line",
|
||||||
|
paint: {
|
||||||
|
"line-color": style.color ?? "#333333",
|
||||||
|
"line-opacity": style.opacity ?? 1,
|
||||||
|
"line-width": style.weight ?? 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (style.dashArray) {
|
||||||
|
layer.paint["line-dasharray"] = style.dashArray.split(/\s+/).map(Number);
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
source,
|
||||||
|
type: "circle",
|
||||||
|
paint: {
|
||||||
|
"circle-color": style.fillColor ?? style.color ?? "#333333",
|
||||||
|
"circle-opacity": style.fillOpacity ?? 0.85,
|
||||||
|
"circle-stroke-color": style.color ?? "#333333",
|
||||||
|
"circle-stroke-width": style.weight ?? 2,
|
||||||
|
"circle-radius": getCircleRadius(style, feature.geometry.coordinates[1]),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCircleRadius(style, latitude) {
|
||||||
|
const radiusMeters =
|
||||||
|
style.radiusMeters ??
|
||||||
|
(typeof style.iconDiameterMeters === "number" ? style.iconDiameterMeters / 2 : null);
|
||||||
|
if (radiusMeters === null) {
|
||||||
|
return style.radius ?? 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
const metersPerPixelAtZoomZero = 156543.03392 * Math.cos((latitude * Math.PI) / 180);
|
||||||
|
return [
|
||||||
|
"interpolate",
|
||||||
|
["exponential", 2],
|
||||||
|
["zoom"],
|
||||||
|
15,
|
||||||
|
(radiusMeters * 2 ** 15) / metersPerPixelAtZoomZero,
|
||||||
|
MAP_MAX_ZOOM,
|
||||||
|
(radiusMeters * 2 ** MAP_MAX_ZOOM) / metersPerPixelAtZoomZero,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function featureExistsOnDate(feature, date) {
|
||||||
|
const { plantedDate, removedDate } = feature.properties;
|
||||||
|
return (!plantedDate || plantedDate <= date) && (!removedDate || date <= removedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const timelineButtons = new globalThis.Map();
|
||||||
|
|
||||||
|
function addTimelineControl() {
|
||||||
|
class TimelineControl {
|
||||||
|
onAdd() {
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.className = "maplibregl-ctrl timeline-control";
|
||||||
|
|
||||||
|
const title = document.createElement("div");
|
||||||
|
title.className = "timeline-control-title";
|
||||||
|
title.textContent = "Timeline";
|
||||||
|
|
||||||
|
const buttonGroup = document.createElement("div");
|
||||||
|
buttonGroup.className = "timeline-buttons";
|
||||||
|
buttonGroup.setAttribute("role", "group");
|
||||||
|
buttonGroup.setAttribute("aria-label", "Choose map date");
|
||||||
|
|
||||||
|
for (const preset of TIMELINE_PRESETS) {
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.type = "button";
|
||||||
|
button.textContent = preset.label;
|
||||||
|
button.title = preset.date;
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
selectedTimelineDate = preset.date;
|
||||||
|
renderYardForDate(selectedTimelineDate);
|
||||||
|
});
|
||||||
|
timelineButtons.set(preset.id, button);
|
||||||
|
buttonGroup.append(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
container.append(title, buttonGroup);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
map.addControl(new TimelineControl(), "top-right");
|
||||||
|
syncTimelineButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncTimelineButtons() {
|
||||||
|
for (const preset of TIMELINE_PRESETS) {
|
||||||
|
const button = timelineButtons.get(preset.id);
|
||||||
|
if (!button) continue;
|
||||||
|
const isSelected = preset.date === selectedTimelineDate;
|
||||||
|
button.classList.toggle("is-selected", isSelected);
|
||||||
|
button.setAttribute("aria-pressed", String(isSelected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderLegend(features) {
|
||||||
|
const summary = new globalThis.Map();
|
||||||
|
|
||||||
|
for (const feature of features) {
|
||||||
|
const key = feature.properties.kind;
|
||||||
|
const style = resolveFeatureStyle(key, feature.properties.details);
|
||||||
|
const existing = summary.get(key) ?? {
|
||||||
|
label: feature.properties.label,
|
||||||
|
count: 0,
|
||||||
|
color: style.fillColor ?? style.color ?? "#333333",
|
||||||
|
};
|
||||||
|
existing.count += 1;
|
||||||
|
summary.set(key, existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
legend.replaceChildren(
|
||||||
|
...[...summary.values()].map((entry) => {
|
||||||
|
const row = document.createElement("div");
|
||||||
|
row.className = "legend-item";
|
||||||
|
const swatch = document.createElement("span");
|
||||||
|
swatch.className = "legend-swatch";
|
||||||
|
swatch.style.background = entry.color;
|
||||||
|
const label = document.createElement("span");
|
||||||
|
label.textContent = `${entry.label} (${entry.count})`;
|
||||||
|
row.append(swatch, label);
|
||||||
|
return row;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTodayDateString(date = new Date()) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGeoJSONBounds(collection) {
|
||||||
|
let west = Infinity;
|
||||||
|
let south = Infinity;
|
||||||
|
let east = -Infinity;
|
||||||
|
let north = -Infinity;
|
||||||
|
|
||||||
|
visitCoordinates(collection.features.map((feature) => feature.geometry.coordinates), ([lon, lat]) => {
|
||||||
|
west = Math.min(west, lon);
|
||||||
|
south = Math.min(south, lat);
|
||||||
|
east = Math.max(east, lon);
|
||||||
|
north = Math.max(north, lat);
|
||||||
|
});
|
||||||
|
return [
|
||||||
|
[west, south],
|
||||||
|
[east, north],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function visitCoordinates(coordinates, callback) {
|
||||||
|
if (typeof coordinates[0] === "number") {
|
||||||
|
callback(coordinates);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const coordinate of coordinates) {
|
||||||
|
visitCoordinates(coordinate, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPopupContent(properties) {
|
||||||
|
const { kind, label, name, plantedDate, removedDate, details, parentId, groupIds } = properties;
|
||||||
|
const entries = Object.entries(details ?? {}).filter(
|
||||||
|
([key, value]) => value !== null && value !== undefined && shouldShowDetailField(key),
|
||||||
|
);
|
||||||
|
const lifecycleEntries = [];
|
||||||
|
const relationshipEntries = [];
|
||||||
|
const linkEntries = resolveFeatureLinks(kind, details);
|
||||||
|
|
||||||
|
if (plantedDate) lifecycleEntries.push(["plantedDate", plantedDate]);
|
||||||
|
if (removedDate) lifecycleEntries.push(["removedDate", removedDate]);
|
||||||
|
if (parentId) relationshipEntries.push(["parentFeature", parentId]);
|
||||||
|
if (groupIds?.length) relationshipEntries.push(["groups", groupIds.join(", ")]);
|
||||||
|
|
||||||
|
const title = `<strong>${escapeHtml(name)}</strong>`;
|
||||||
|
const subtitle = name === label ? "" : `<div>${escapeHtml(label)}</div>`;
|
||||||
|
const allEntries = [...lifecycleEntries, ...entries, ...relationshipEntries];
|
||||||
|
const detailRows = allEntries
|
||||||
|
.map(
|
||||||
|
([key, value]) =>
|
||||||
|
`<div><span>${escapeHtml(formatDetailLabel(key))}:</span> ${escapeHtml(formatDetailValue(key, value))}</div>`,
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
const linkRows = linkEntries
|
||||||
|
.map(
|
||||||
|
(link) =>
|
||||||
|
`<div><a href="${escapeHtml(link.url)}" target="_blank" rel="noreferrer">${escapeHtml(link.label)}</a></div>`,
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
return `${title}${subtitle}<div>${detailRows}${linkRows}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldShowDetailField(key) {
|
||||||
|
return !key.endsWith("Url") && key !== "gardenOrgId";
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDetailLabel(key) {
|
||||||
|
const labels = {
|
||||||
|
canopyDiameterMeters: "Canopy diameter",
|
||||||
|
heightMeters: "Height",
|
||||||
|
plantedDate: "Planted",
|
||||||
|
removedDate: "Removed",
|
||||||
|
commonName: "Common name",
|
||||||
|
genus: "Genus",
|
||||||
|
cultivar: "Cultivar",
|
||||||
|
bloomColor: "Bloom color",
|
||||||
|
bloomSeason: "Bloom season",
|
||||||
|
species: "Species",
|
||||||
|
fenceType: "Fence type",
|
||||||
|
axis: "Axis",
|
||||||
|
offsetFeet: "Offset",
|
||||||
|
spacingFeet: "Spacing",
|
||||||
|
note: "Note",
|
||||||
|
parentFeature: "Parent",
|
||||||
|
groups: "Groups",
|
||||||
|
};
|
||||||
|
return labels[key] ?? key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDetailValue(key, value) {
|
||||||
|
if (key === "canopyDiameterMeters" || key === "heightMeters") return `${value} m`;
|
||||||
|
if (key === "offsetFeet" || key === "spacingFeet") return `${value} ft`;
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHtml(value) {
|
||||||
|
return String(value)
|
||||||
|
.replaceAll("&", "&")
|
||||||
|
.replaceAll("<", "<")
|
||||||
|
.replaceAll(">", ">")
|
||||||
|
.replaceAll('"', """)
|
||||||
|
.replaceAll("'", "'");
|
||||||
|
}
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
:root {
|
||||||
|
color-scheme: light;
|
||||||
|
--bg: #f3efe2;
|
||||||
|
--panel: rgba(253, 250, 240, 0.88);
|
||||||
|
--panel-border: rgba(78, 62, 36, 0.15);
|
||||||
|
--ink: #2e2619;
|
||||||
|
--muted: #64563f;
|
||||||
|
--accent: #466b45;
|
||||||
|
--accent-soft: #cedbbf;
|
||||||
|
--shadow: 0 24px 80px rgba(60, 44, 22, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
font-family: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", serif;
|
||||||
|
color: var(--ink);
|
||||||
|
background:
|
||||||
|
radial-gradient(circle at top left, rgba(255, 255, 255, 0.72), transparent 30%),
|
||||||
|
linear-gradient(135deg, #e7e0c7 0%, #f7f3e8 50%, #e4ead9 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-shell {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(280px, 360px) minmax(0, 1fr);
|
||||||
|
min-height: 100vh;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
padding: 1.5rem;
|
||||||
|
border: 1px solid var(--panel-border);
|
||||||
|
border-radius: 24px;
|
||||||
|
background: var(--panel);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.eyebrow {
|
||||||
|
margin: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0.4rem 0 1rem;
|
||||||
|
font-size: clamp(2.2rem, 4vw, 3.6rem);
|
||||||
|
line-height: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro,
|
||||||
|
.notes {
|
||||||
|
color: var(--muted);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.65rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-swatch {
|
||||||
|
width: 0.9rem;
|
||||||
|
height: 0.9rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
flex: none;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes h2 {
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
color: var(--ink);
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.9rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: rgba(70, 107, 69, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: "JetBrains Mono", "Fira Code", monospace;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
main,
|
||||||
|
.map-frame {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-frame {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map {
|
||||||
|
min-height: calc(100vh - 2rem);
|
||||||
|
border-radius: 28px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.maplibregl-popup-content {
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maplibregl-popup-content {
|
||||||
|
font-family: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-status {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
top: 1rem;
|
||||||
|
left: 50%;
|
||||||
|
margin: 0;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
padding: 0.55rem 0.8rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(253, 250, 240, 0.94);
|
||||||
|
box-shadow: 0 8px 24px rgba(60, 44, 22, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-status[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-control {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.45rem;
|
||||||
|
min-width: 12rem;
|
||||||
|
padding: 0.7rem;
|
||||||
|
border: 1px solid var(--panel-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(253, 250, 240, 0.94);
|
||||||
|
box-shadow: 0 12px 36px rgba(60, 44, 22, 0.16);
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-control-title {
|
||||||
|
font-size: 0.76rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-buttons {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-buttons button {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid rgba(70, 107, 69, 0.28);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.42rem 0.55rem;
|
||||||
|
background: #fffdf6;
|
||||||
|
color: var(--ink);
|
||||||
|
font: inherit;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-buttons button:hover,
|
||||||
|
.timeline-buttons button:focus-visible {
|
||||||
|
border-color: rgba(70, 107, 69, 0.58);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-buttons button.is-selected {
|
||||||
|
border-color: var(--accent);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay {
|
||||||
|
position: fixed;
|
||||||
|
right: 1rem;
|
||||||
|
bottom: 1rem;
|
||||||
|
z-index: 10000;
|
||||||
|
width: min(42rem, calc(100vw - 2rem));
|
||||||
|
max-height: min(28rem, calc(100vh - 2rem));
|
||||||
|
overflow: auto;
|
||||||
|
border: 1px solid rgba(111, 23, 23, 0.32);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fff7f4;
|
||||||
|
box-shadow: 0 18px 60px rgba(59, 20, 20, 0.22);
|
||||||
|
color: #331514;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0.8rem 1rem;
|
||||||
|
border-bottom: 1px solid rgba(111, 23, 23, 0.18);
|
||||||
|
background: #f6d5ce;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay button {
|
||||||
|
border: 1px solid rgba(111, 23, 23, 0.28);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.35rem 0.55rem;
|
||||||
|
background: #fffaf8;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay pre {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-overlay-copy-buffer {
|
||||||
|
position: fixed;
|
||||||
|
top: -100vh;
|
||||||
|
left: -100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.app-shell {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map {
|
||||||
|
min-height: 65vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"use strict";var basemaps=(()=>{var d=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var l=(a,e)=>d(a,"name",{value:e,configurable:!0});var v=(a,e)=>{for(var i in e)d(a,i,{get:e[i],enumerable:!0})},j=(a,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of x(e))!z.call(a,r)&&r!==i&&d(a,r,{get:()=>e[r],enumerable:!(n=w(e,r))||n.enumerable});return a};var S=a=>j(d({},"__esModule",{value:!0}),a);var $={};v($,{BLACK:()=>h,DARK:()=>p,GRAYSCALE:()=>b,LIGHT:()=>f,WHITE:()=>m,get_country_name:()=>_,get_multiline_name:()=>o,language_script_pairs:()=>g,layers:()=>D,namedFlavor:()=>L});function t(a,e){let i="script";return a==="name"?i="script":a==="name2"?i="script2":a==="name3"&&(i="script3"),[["coalesce",["get",`pgf:${a}`],["get",a]],{"text-font":["case",["==",["get",i],"Devanagari"],["literal",["Noto Sans Devanagari Regular v1"]],["literal",[e||"Noto Sans Regular"]]]}]}l(t,"get_name_block");function c(a,e,i){let n="name";return i==="name"?n="":i==="name2"?n="2":i==="name3"&&(n="3"),e==="Latin"?["has",`script${n}`]:a==="ja"?["all",["!=",["get",`script${n}`],"Han"],["!=",["get",`script${n}`],"Hiragana"],["!=",["get",`script${n}`],"Katakana"],["!=",["get",`script${n}`],"Mixed-Japanese"]]:["!=",["get",`script${n}`],e]}l(c,"is_not_in_target_script");function s(a){return a==="Devanagari"?{"text-font":["literal",["Noto Sans Devanagari Regular v1"]]}:{}}l(s,"get_font_formatting");function u(a){let e=g.find(i=>i.lang===a);return e===void 0?"Latin":e.script}l(u,"get_default_script");function _(a,e){let i=e||u(a),n;return i==="Devanagari"?n="pgf:":n="",["format",["coalesce",["get",`${n}name:${a}`],["get","name:en"]],s(i)]}l(_,"get_country_name");function o(a,e,i){let n=e||u(a),r;return n==="Devanagari"?r="pgf:":r="",["case",["all",["any",["has","name"],["has","pgf:name"]],["!",["any",["has","name2"],["has","pgf:name2"]]],["!",["any",["has","name3"],["has","pgf:name3"]]]],["case",c(a,n,"name"),["case",["any",["is-supported-script",["get","name"]],["has","pgf:name"]],["format",["coalesce",["get",`${r}name:${a}`],["get","name:en"]],s(n),`
|
||||||
|
`,{},["case",["all",["!",["has",`${r}name:${a}`]],["has","name:en"],["!",["has","script"]]],"",["coalesce",["get","pgf:name"],["get","name"]]],{"text-font":["case",["==",["get","script"],"Devanagari"],["literal",["Noto Sans Devanagari Regular v1"]],["literal",[i||"Noto Sans Regular"]]]}],["get","name:en"]],["format",["coalesce",["get",`${r}name:${a}`],["get","pgf:name"],["get","name"]],s(n)]],["all",["any",["has","name"],["has","pgf:name"]],["any",["has","name2"],["has","pgf:name2"]],["!",["any",["has","name3"],["has","pgf:name3"]]]],["case",["all",c(a,n,"name"),c(a,n,"name2")],["format",["get",`${r}name:${a}`],s(n),`
|
||||||
|
`,{},...t("name",i),`
|
||||||
|
`,{},...t("name2",i)],["case",c(a,n,"name2"),["format",["coalesce",["get",`${r}name:${a}`],["get","pgf:name"],["get","name"]],s(n),`
|
||||||
|
`,{},...t("name2",i)],["format",["coalesce",["get",`${r}name:${a}`],["get","pgf:name2"],["get","name2"]],s(n),`
|
||||||
|
`,{},...t("name",i)]]],["case",["all",c(a,n,"name"),c(a,n,"name2"),c(a,n,"name3")],["format",["get",`${r}name:${a}`],s(n),`
|
||||||
|
`,{},...t("name",i),`
|
||||||
|
`,{},...t("name2",i),`
|
||||||
|
`,{},...t("name3",i)],["case",["!",c(a,n,"name")],["format",["coalesce",["get",`${r}name:${a}`],["get","pgf:name"],["get","name"]],s(n),`
|
||||||
|
`,{},...t("name2",i),`
|
||||||
|
`,{},...t("name3",i)],["!",c(a,n,"name2")],["format",["coalesce",["get",`${r}name:${a}`],["get","pgf:name2"],["get","name2"]],s(n),`
|
||||||
|
`,{},...t("name",i),`
|
||||||
|
`,{},...t("name3",i)],["format",["coalesce",["get",`${r}name:${a}`],["get","pgf:name3"],["get","name3"]],s(n),`
|
||||||
|
`,{},...t("name",i),`
|
||||||
|
`,{},...t("name2",i)]]]]}l(o,"get_multiline_name");var g=[{lang:"ar",full_name:"Arabic",script:"Arabic"},{lang:"cs",full_name:"Czech",script:"Latin"},{lang:"bg",full_name:"Bulgarian",script:"Cyrillic"},{lang:"da",full_name:"Danish",script:"Latin"},{lang:"de",full_name:"German",script:"Latin"},{lang:"el",full_name:"Greek",script:"Greek"},{lang:"en",full_name:"English",script:"Latin"},{lang:"es",full_name:"Spanish",script:"Latin"},{lang:"et",full_name:"Estonian",script:"Latin"},{lang:"fa",full_name:"Persian",script:"Arabic"},{lang:"fi",full_name:"Finnish",script:"Latin"},{lang:"fr",full_name:"French",script:"Latin"},{lang:"ga",full_name:"Irish",script:"Latin"},{lang:"he",full_name:"Hebrew",script:"Hebrew"},{lang:"hi",full_name:"Hindi",script:"Devanagari"},{lang:"hr",full_name:"Croatian",script:"Latin"},{lang:"hu",full_name:"Hungarian",script:"Latin"},{lang:"id",full_name:"Indonesian",script:"Latin"},{lang:"it",full_name:"Italian",script:"Latin"},{lang:"ja",full_name:"Japanese",script:""},{lang:"ko",full_name:"Korean",script:"Hangul"},{lang:"lt",full_name:"Lithuanian",script:"Latin"},{lang:"lv",full_name:"Latvian",script:"Latin"},{lang:"ne",full_name:"Nepali",script:"Devanagari"},{lang:"nl",full_name:"Dutch",script:"Latin"},{lang:"no",full_name:"Norwegian",script:"Latin"},{lang:"mr",full_name:"Marathi",script:"Devanagari"},{lang:"mt",full_name:"Maltese",script:"Latin"},{lang:"pl",full_name:"Polish",script:"Latin"},{lang:"pt",full_name:"Portuguese",script:"Latin"},{lang:"ro",full_name:"Romanian",script:"Latin"},{lang:"ru",full_name:"Russian",script:"Cyrillic"},{lang:"sk",full_name:"Slovak",script:"Latin"},{lang:"sl",full_name:"Slovenian",script:"Latin"},{lang:"sv",full_name:"Swedish",script:"Latin"},{lang:"tr",full_name:"Turkish",script:"Latin"},{lang:"uk",full_name:"Ukrainian",script:"Cyrillic"},{lang:"ur",full_name:"Urdu",script:"Arabic"},{lang:"vi",full_name:"Vietnamese",script:"Latin"},{lang:"zh-Hans",full_name:"Chinese (Simplified)",script:"Han"},{lang:"zh-Hant",full_name:"Chinese (Traditional)",script:"Han"}];function y(a,e){return[{id:"background",type:"background",paint:{"background-color":e.background}},{id:"earth",type:"fill",filter:["==","$type","Polygon"],source:a,"source-layer":"earth",paint:{"fill-color":e.earth}},...e.landcover?[{id:"landcover",type:"fill",source:a,"source-layer":"landcover",paint:{"fill-color":["match",["get","kind"],"grassland",e.landcover.grassland,"barren",e.landcover.barren,"urban_area",e.landcover.urban_area,"farmland",e.landcover.farmland,"glacier",e.landcover.glacier,"scrub",e.landcover.scrub,e.landcover.forest],"fill-opacity":["interpolate",["linear"],["zoom"],5,1,7,0]}}]:[],{id:"landuse_park",type:"fill",source:a,"source-layer":"landuse",filter:["in","kind","national_park","park","cemetery","protected_area","nature_reserve","forest","golf_course","wood","scrub","grassland","grass","glacier","sand","military","naval_base","airfield"],paint:{"fill-opacity":["interpolate",["linear"],["zoom"],6,0,11,1],"fill-color":["case",["in",["get","kind"],["literal",["national_park","park","cemetery","protected_area","nature_reserve","forest","golf_course"]]],e.park_b,["==",["get","kind"],"wood"],e.wood_b,["in",["get","kind"],["literal",["scrub","grassland","grass"]]],e.scrub_b,["==",["get","kind"],"glacier"],e.glacier,["==",["get","kind"],"sand"],e.sand,["in",["get","kind"],["literal",["military","naval_base","airfield"]]],e.zoo,e.earth]}},{id:"landuse_urban_green",type:"fill",source:a,"source-layer":"landuse",filter:["in","kind","allotments","village_green","playground"],paint:{"fill-color":e.park_b,"fill-opacity":.7}},{id:"landuse_hospital",type:"fill",source:a,"source-layer":"landuse",filter:["==","kind","hospital"],paint:{"fill-color":e.hospital}},{id:"landuse_industrial",type:"fill",source:a,"source-layer":"landuse",filter:["==","kind","industrial"],paint:{"fill-color":e.industrial}},{id:"landuse_school",type:"fill",source:a,"source-layer":"landuse",filter:["in","kind","school","university","college"],paint:{"fill-color":e.school}},{id:"landuse_beach",type:"fill",source:a,"source-layer":"landuse",filter:["in","kind","beach"],paint:{"fill-color":e.beach}},{id:"landuse_zoo",type:"fill",source:a,"source-layer":"landuse",filter:["in","kind","zoo"],paint:{"fill-color":e.zoo}},{id:"landuse_aerodrome",type:"fill",source:a,"source-layer":"landuse",filter:["in","kind","aerodrome"],paint:{"fill-color":e.aerodrome}},{id:"roads_runway",type:"line",source:a,"source-layer":"roads",filter:["==","kind_detail","runway"],paint:{"line-color":e.runway,"line-width":["interpolate",["exponential",1.6],["zoom"],10,0,12,4,18,30]}},{id:"roads_taxiway",type:"line",source:a,"source-layer":"roads",minzoom:13,filter:["==","kind_detail","taxiway"],paint:{"line-color":e.runway,"line-width":["interpolate",["exponential",1.6],["zoom"],13,0,13.5,1,15,6]}},{id:"landuse_runway",type:"fill",source:a,"source-layer":"landuse",filter:["any",["in","kind","runway","taxiway"]],paint:{"fill-color":e.runway}},{id:"water",ty
Line truncated
|
||||||
|
//# sourceMappingURL=basemaps.js.map
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 696 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 618 B |
@@ -0,0 +1,661 @@
|
|||||||
|
/* required styles */
|
||||||
|
|
||||||
|
.leaflet-pane,
|
||||||
|
.leaflet-tile,
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow,
|
||||||
|
.leaflet-tile-container,
|
||||||
|
.leaflet-pane > svg,
|
||||||
|
.leaflet-pane > canvas,
|
||||||
|
.leaflet-zoom-box,
|
||||||
|
.leaflet-image-layer,
|
||||||
|
.leaflet-layer {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.leaflet-container {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.leaflet-tile,
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
}
|
||||||
|
/* Prevents IE11 from highlighting tiles in blue */
|
||||||
|
.leaflet-tile::selection {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||||
|
.leaflet-safari .leaflet-tile {
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
}
|
||||||
|
/* hack that prevents hw layers "stretching" when loading new tiles */
|
||||||
|
.leaflet-safari .leaflet-tile-container {
|
||||||
|
width: 1600px;
|
||||||
|
height: 1600px;
|
||||||
|
-webkit-transform-origin: 0 0;
|
||||||
|
}
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
||||||
|
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
||||||
|
.leaflet-container .leaflet-overlay-pane svg {
|
||||||
|
max-width: none !important;
|
||||||
|
max-height: none !important;
|
||||||
|
}
|
||||||
|
.leaflet-container .leaflet-marker-pane img,
|
||||||
|
.leaflet-container .leaflet-shadow-pane img,
|
||||||
|
.leaflet-container .leaflet-tile-pane img,
|
||||||
|
.leaflet-container img.leaflet-image-layer,
|
||||||
|
.leaflet-container .leaflet-tile {
|
||||||
|
max-width: none !important;
|
||||||
|
max-height: none !important;
|
||||||
|
width: auto;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-container img.leaflet-tile {
|
||||||
|
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
|
||||||
|
mix-blend-mode: plus-lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-container.leaflet-touch-zoom {
|
||||||
|
-ms-touch-action: pan-x pan-y;
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
|
}
|
||||||
|
.leaflet-container.leaflet-touch-drag {
|
||||||
|
-ms-touch-action: pinch-zoom;
|
||||||
|
/* Fallback for FF which doesn't support pinch-zoom */
|
||||||
|
touch-action: none;
|
||||||
|
touch-action: pinch-zoom;
|
||||||
|
}
|
||||||
|
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
||||||
|
-ms-touch-action: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
.leaflet-container {
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.leaflet-container a {
|
||||||
|
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
||||||
|
}
|
||||||
|
.leaflet-tile {
|
||||||
|
filter: inherit;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.leaflet-tile-loaded {
|
||||||
|
visibility: inherit;
|
||||||
|
}
|
||||||
|
.leaflet-zoom-box {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
z-index: 800;
|
||||||
|
}
|
||||||
|
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||||
|
.leaflet-overlay-pane svg {
|
||||||
|
-moz-user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-pane { z-index: 400; }
|
||||||
|
|
||||||
|
.leaflet-tile-pane { z-index: 200; }
|
||||||
|
.leaflet-overlay-pane { z-index: 400; }
|
||||||
|
.leaflet-shadow-pane { z-index: 500; }
|
||||||
|
.leaflet-marker-pane { z-index: 600; }
|
||||||
|
.leaflet-tooltip-pane { z-index: 650; }
|
||||||
|
.leaflet-popup-pane { z-index: 700; }
|
||||||
|
|
||||||
|
.leaflet-map-pane canvas { z-index: 100; }
|
||||||
|
.leaflet-map-pane svg { z-index: 200; }
|
||||||
|
|
||||||
|
.leaflet-vml-shape {
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
.lvml {
|
||||||
|
behavior: url(#default#VML);
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* control positioning */
|
||||||
|
|
||||||
|
.leaflet-control {
|
||||||
|
position: relative;
|
||||||
|
z-index: 800;
|
||||||
|
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.leaflet-top,
|
||||||
|
.leaflet-bottom {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.leaflet-top {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.leaflet-right {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.leaflet-bottom {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.leaflet-left {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.leaflet-control {
|
||||||
|
float: left;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
.leaflet-right .leaflet-control {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.leaflet-top .leaflet-control {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.leaflet-bottom .leaflet-control {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.leaflet-left .leaflet-control {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.leaflet-right .leaflet-control {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* zoom and fade animations */
|
||||||
|
|
||||||
|
.leaflet-fade-anim .leaflet-popup {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: opacity 0.2s linear;
|
||||||
|
-moz-transition: opacity 0.2s linear;
|
||||||
|
transition: opacity 0.2s linear;
|
||||||
|
}
|
||||||
|
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.leaflet-zoom-animated {
|
||||||
|
-webkit-transform-origin: 0 0;
|
||||||
|
-ms-transform-origin: 0 0;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
}
|
||||||
|
svg.leaflet-zoom-animated {
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||||
|
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||||
|
}
|
||||||
|
.leaflet-zoom-anim .leaflet-tile,
|
||||||
|
.leaflet-pan-anim .leaflet-tile {
|
||||||
|
-webkit-transition: none;
|
||||||
|
-moz-transition: none;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* cursors */
|
||||||
|
|
||||||
|
.leaflet-interactive {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.leaflet-grab {
|
||||||
|
cursor: -webkit-grab;
|
||||||
|
cursor: -moz-grab;
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
.leaflet-crosshair,
|
||||||
|
.leaflet-crosshair .leaflet-interactive {
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.leaflet-popup-pane,
|
||||||
|
.leaflet-control {
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
.leaflet-dragging .leaflet-grab,
|
||||||
|
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
||||||
|
.leaflet-dragging .leaflet-marker-draggable {
|
||||||
|
cursor: move;
|
||||||
|
cursor: -webkit-grabbing;
|
||||||
|
cursor: -moz-grabbing;
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* marker & overlays interactivity */
|
||||||
|
.leaflet-marker-icon,
|
||||||
|
.leaflet-marker-shadow,
|
||||||
|
.leaflet-image-layer,
|
||||||
|
.leaflet-pane > svg path,
|
||||||
|
.leaflet-tile-container {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-marker-icon.leaflet-interactive,
|
||||||
|
.leaflet-image-layer.leaflet-interactive,
|
||||||
|
.leaflet-pane > svg path.leaflet-interactive,
|
||||||
|
svg.leaflet-image-layer.leaflet-interactive path {
|
||||||
|
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* visual tweaks */
|
||||||
|
|
||||||
|
.leaflet-container {
|
||||||
|
background: #ddd;
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
.leaflet-container a {
|
||||||
|
color: #0078A8;
|
||||||
|
}
|
||||||
|
.leaflet-zoom-box {
|
||||||
|
border: 2px dotted #38f;
|
||||||
|
background: rgba(255,255,255,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* general typography */
|
||||||
|
.leaflet-container {
|
||||||
|
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* general toolbar styles */
|
||||||
|
|
||||||
|
.leaflet-bar {
|
||||||
|
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.leaflet-bar a {
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
line-height: 26px;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.leaflet-bar a,
|
||||||
|
.leaflet-control-layers-toggle {
|
||||||
|
background-position: 50% 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.leaflet-bar a:hover,
|
||||||
|
.leaflet-bar a:focus {
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
.leaflet-bar a:first-child {
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
}
|
||||||
|
.leaflet-bar a:last-child {
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.leaflet-bar a.leaflet-disabled {
|
||||||
|
cursor: default;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-touch .leaflet-bar a {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
.leaflet-touch .leaflet-bar a:first-child {
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
}
|
||||||
|
.leaflet-touch .leaflet-bar a:last-child {
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zoom control */
|
||||||
|
|
||||||
|
.leaflet-control-zoom-in,
|
||||||
|
.leaflet-control-zoom-out {
|
||||||
|
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||||
|
text-indent: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* layers control */
|
||||||
|
|
||||||
|
.leaflet-control-layers {
|
||||||
|
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-toggle {
|
||||||
|
background-image: url(images/layers.png);
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
.leaflet-retina .leaflet-control-layers-toggle {
|
||||||
|
background-image: url(images/layers-2x.png);
|
||||||
|
background-size: 26px 26px;
|
||||||
|
}
|
||||||
|
.leaflet-touch .leaflet-control-layers-toggle {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers .leaflet-control-layers-list,
|
||||||
|
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-expanded {
|
||||||
|
padding: 6px 10px 6px 6px;
|
||||||
|
color: #333;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-scrollbar {
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-selector {
|
||||||
|
margin-top: 2px;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers label {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
font-size: 1.08333em;
|
||||||
|
}
|
||||||
|
.leaflet-control-layers-separator {
|
||||||
|
height: 0;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
margin: 5px -10px 5px -6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default icon URLs */
|
||||||
|
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
|
||||||
|
background-image: url(images/marker-icon.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* attribution and scale controls */
|
||||||
|
|
||||||
|
.leaflet-container .leaflet-control-attribution {
|
||||||
|
background: #fff;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.leaflet-control-attribution,
|
||||||
|
.leaflet-control-scale-line {
|
||||||
|
padding: 0 5px;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.leaflet-control-attribution a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.leaflet-control-attribution a:hover,
|
||||||
|
.leaflet-control-attribution a:focus {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.leaflet-attribution-flag {
|
||||||
|
display: inline !important;
|
||||||
|
vertical-align: baseline !important;
|
||||||
|
width: 1em;
|
||||||
|
height: 0.6669em;
|
||||||
|
}
|
||||||
|
.leaflet-left .leaflet-control-scale {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
.leaflet-bottom .leaflet-control-scale {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.leaflet-control-scale-line {
|
||||||
|
border: 2px solid #777;
|
||||||
|
border-top: none;
|
||||||
|
line-height: 1.1;
|
||||||
|
padding: 2px 5px 1px;
|
||||||
|
white-space: nowrap;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
text-shadow: 1px 1px #fff;
|
||||||
|
}
|
||||||
|
.leaflet-control-scale-line:not(:first-child) {
|
||||||
|
border-top: 2px solid #777;
|
||||||
|
border-bottom: none;
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||||
|
border-bottom: 2px solid #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-touch .leaflet-control-attribution,
|
||||||
|
.leaflet-touch .leaflet-control-layers,
|
||||||
|
.leaflet-touch .leaflet-bar {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.leaflet-touch .leaflet-control-layers,
|
||||||
|
.leaflet-touch .leaflet-bar {
|
||||||
|
border: 2px solid rgba(0,0,0,0.2);
|
||||||
|
background-clip: padding-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* popup */
|
||||||
|
|
||||||
|
.leaflet-popup {
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper {
|
||||||
|
padding: 1px;
|
||||||
|
text-align: left;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content {
|
||||||
|
margin: 13px 24px 13px 20px;
|
||||||
|
line-height: 1.3;
|
||||||
|
font-size: 13px;
|
||||||
|
font-size: 1.08333em;
|
||||||
|
min-height: 1px;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content p {
|
||||||
|
margin: 17px 0;
|
||||||
|
margin: 1.3em 0;
|
||||||
|
}
|
||||||
|
.leaflet-popup-tip-container {
|
||||||
|
width: 40px;
|
||||||
|
height: 20px;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -1px;
|
||||||
|
margin-left: -20px;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.leaflet-popup-tip {
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
padding: 1px;
|
||||||
|
|
||||||
|
margin: -10px auto 0;
|
||||||
|
pointer-events: auto;
|
||||||
|
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
-moz-transform: rotate(45deg);
|
||||||
|
-ms-transform: rotate(45deg);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper,
|
||||||
|
.leaflet-popup-tip {
|
||||||
|
background: white;
|
||||||
|
color: #333;
|
||||||
|
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
.leaflet-container a.leaflet-popup-close-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
font: 16px/24px Tahoma, Verdana, sans-serif;
|
||||||
|
color: #757575;
|
||||||
|
text-decoration: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.leaflet-container a.leaflet-popup-close-button:hover,
|
||||||
|
.leaflet-container a.leaflet-popup-close-button:focus {
|
||||||
|
color: #585858;
|
||||||
|
}
|
||||||
|
.leaflet-popup-scrolled {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||||
|
-ms-zoom: 1;
|
||||||
|
}
|
||||||
|
.leaflet-oldie .leaflet-popup-tip {
|
||||||
|
width: 24px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||||
|
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-oldie .leaflet-control-zoom,
|
||||||
|
.leaflet-oldie .leaflet-control-layers,
|
||||||
|
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||||
|
.leaflet-oldie .leaflet-popup-tip {
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* div icon */
|
||||||
|
|
||||||
|
.leaflet-div-icon {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tooltip */
|
||||||
|
/* Base styles for the element that has a tooltip */
|
||||||
|
.leaflet-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
padding: 6px;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #222;
|
||||||
|
white-space: nowrap;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
.leaflet-tooltip.leaflet-interactive {
|
||||||
|
cursor: pointer;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-top:before,
|
||||||
|
.leaflet-tooltip-bottom:before,
|
||||||
|
.leaflet-tooltip-left:before,
|
||||||
|
.leaflet-tooltip-right:before {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
border: 6px solid transparent;
|
||||||
|
background: transparent;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Directions */
|
||||||
|
|
||||||
|
.leaflet-tooltip-bottom {
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-top {
|
||||||
|
margin-top: -6px;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-bottom:before,
|
||||||
|
.leaflet-tooltip-top:before {
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -6px;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-top:before {
|
||||||
|
bottom: 0;
|
||||||
|
margin-bottom: -12px;
|
||||||
|
border-top-color: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-bottom:before {
|
||||||
|
top: 0;
|
||||||
|
margin-top: -12px;
|
||||||
|
margin-left: -6px;
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-left {
|
||||||
|
margin-left: -6px;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-right {
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-left:before,
|
||||||
|
.leaflet-tooltip-right:before {
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -6px;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-left:before {
|
||||||
|
right: 0;
|
||||||
|
margin-right: -12px;
|
||||||
|
border-left-color: #fff;
|
||||||
|
}
|
||||||
|
.leaflet-tooltip-right:before {
|
||||||
|
left: 0;
|
||||||
|
margin-left: -12px;
|
||||||
|
border-right-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Printing */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
/* Prevent printers from removing background-images of controls. */
|
||||||
|
.leaflet-control {
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/* @preserve
|
||||||
|
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
|
||||||
|
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
|
||||||
|
*/
|
||||||
|
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).leaflet={})}(this,function(t){"use strict";function l(t){for(var e,i,n=1,o=arguments.length;n<o;n++)for(e in i=arguments[n])t[e]=i[e];return t}var R=Object.create||function(t){return N.prototype=t,new N};function N(){}function a(t,e){var i,n=Array.prototype.slice;return t.bind?t.bind.apply(t,n.call(arguments,1)):(i=n.call(arguments,2),function(){return t.apply(e,i.length?i.concat(n.call(arguments)):arguments)})}var D=0;function h(t){return"_leaflet_id"in t||(t._leaflet_id=++D),t._leaflet_id}function j(t,e,i){var n,o,s=function(){n=!1,o&&(r.apply(i,o),o=!1)},r=function(){n?o=arguments:(t.apply(i,arguments),setTimeout(s,e),n=!0)};return r}function H(t,e,i){var n=e[1],e=e[0],o=n-e;return t===n&&i?t:((t-e)%o+o)%o+e}function u(){return!1}function i(t,e){return!1===e?t:(e=Math.pow(10,void 0===e?6:e),Math.round(t*e)/e)}function W(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function F(t){return W(t).split(/\s+/)}function c(t,e){for(var i in Object.prototype.hasOwnProperty.call(t,"options")||(t.options=t.options?R(t.options):{}),e)t.options[i]=e[i];return t.options}function U(t,e,i){var n,o=[];for(n in t)o.push(encodeURIComponent(i?n.toUpperCase():n)+"="+encodeURIComponent(t[n]));return(e&&-1!==e.indexOf("?")?"&":"?")+o.join("&")}var V=/\{ *([\w_ -]+) *\}/g;function q(t,i){return t.replace(V,function(t,e){e=i[e];if(void 0===e)throw new Error("No value provided for variable "+t);return e="function"==typeof e?e(i):e})}var d=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)};function G(t,e){for(var i=0;i<t.length;i++)if(t[i]===e)return i;return-1}var K="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function Y(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}var X=0;function J(t){var e=+new Date,i=Math.max(0,16-(e-X));return X=e+i,window.setTimeout(t,i)}var $=window.requestAnimationFrame||Y("RequestAnimationFrame")||J,Q=window.cancelAnimationFrame||Y("CancelAnimationFrame")||Y("CancelRequestAnimationFrame")||function(t){window.clearTimeout(t)};function x(t,e,i){if(!i||$!==J)return $.call(window,a(t,e));t.call(e)}function r(t){t&&Q.call(window,t)}var tt={__proto__:null,extend:l,create:R,bind:a,get lastId(){return D},stamp:h,throttle:j,wrapNum:H,falseFn:u,formatNum:i,trim:W,splitWords:F,setOptions:c,getParamString:U,template:q,isArray:d,indexOf:G,emptyImageUrl:K,requestFn:$,cancelFn:Q,requestAnimFrame:x,cancelAnimFrame:r};function et(){}et.extend=function(t){function e(){c(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()}var i,n=e.__super__=this.prototype,o=R(n);for(i in(o.constructor=e).prototype=o,this)Object.prototype.hasOwnProperty.call(this,i)&&"prototype"!==i&&"__super__"!==i&&(e[i]=this[i]);if(t.statics&&l(e,t.statics),t.includes){var s=t.includes;if("undefined"!=typeof L&&L&&L.Mixin){s=d(s)?s:[s];for(var r=0;r<s.length;r++)s[r]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",(new Error).stack)}l.apply(null,[o].concat(t.includes))}return l(o,t),delete o.statics,delete o.includes,o.options&&(o.options=n.options?R(n.options):{},l(o.options,t.options)),o._initHooks=[],o.callInitHooks=function(){if(!this._initHooksCalled){n.callInitHooks&&n.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=o._initHooks.length;t<e;t++)o._initHooks[t].call(this)}},e},et.include=function(t){var e=this.prototype.options;return l(this.prototype,t),t.options&&(this.prototype.options=e,this.mergeOptions(t.options)),this},et.mergeOptions=function(t){return l(this.prototype.options,t),this},et.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i),this};var e={on:function(t,e,i){if("object"==typeof t)for(var n in t)this._on(n,t[n],e);else for(var o=0,s=(t=F(t)).length;o<s;o++)this._on(t[o],e,i);return this},off:function(t,e,i){if(arguments.length)if("object"==typeof t)for(var n in t)this._off(n,t[n],e);else{t=F(t);for(var o=1===arguments.length,s=0,r=t.length;s<r;s++)o?this._off(t[s]):this._off(t[s],e,i)}else delete this._events;return this},_on:function(t,e,i,n){"function"!=typeof e?console.warn("wrong listener type: "+typeof e):!1===this._listens(t,e,i)&&(e={fn:e,ctx:i=i===this?void 0:i},n&&(e.once=!0),this._events=this._events||{},this._events[t]=this._events[t]||[],this._events[t].push(e))},_off:function(t,e,i){var n,o,s;if(this._events&&(n=this._events[t]))if(1===arguments.length){if(this._firingCount)for(o=0,s=n.length;o<s;o++)n[o].fn=u;delete this._events[t]}else"function"!=typeof e?console.warn("wrong listener type: "+typeof e):!1!==(e=this._listens(Line truncated
|
||||||
|
//# sourceMappingURL=leaflet.js.map
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* MapLibre GL JS
|
||||||
|
* @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.0.0/LICENSE.txt
|
||||||
|
*/
|
||||||
|
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));function l(e,t){this.x=e,this.y=t}l.prototype={clone(){return new l(this.x,this.y)},add(e){return this.clone()._add(e)},sub(e){return this.clone()._sub(e)},multByPoint(e){return this.clone()._multByPoint(e)},divByPoint(e){return this.clone()._divByPoint(e)},mult(e){return this.clone()._mult(e)},div(e){return this.clone()._div(e)},rotate(e){return this.clone()._rotate(e)},rotateAround(e,t){return this.clone()._rotateAround(e,t)},matMult(e){return this.clone()._matMult(e)},unit(){return this.clone()._unit()},perp(){return this.clone()._perp()},round(){return this.clone()._round()},mag(){return Math.sqrt(this.x*this.x+this.y*this.y)},equals(e){return this.x===e.x&&this.y===e.y},dist(e){return Math.sqrt(this.distSqr(e))},distSqr(e){let t=e.x-this.x,n=e.y-this.y;return t*t+n*n},angle(){return Math.atan2(this.y,this.x)},angleTo(e){return Math.atan2(this.y-e.y,this.x-e.x)},angleWith(e){return this.angleWithSep(e.x,e.y)},angleWithSep(e,t){return Math.atan2(this.x*t-this.y*e,this.x*e+this.y*t)},_matMult(e){let t=e[0]*this.x+e[1]*this.y,n=e[2]*this.x+e[3]*this.y;return this.x=t,this.y=n,this},_add(e){return this.x+=e.x,this.y+=e.y,this},_sub(e){return this.x-=e.x,this.y-=e.y,this},_mult(e){return this.x*=e,this.y*=e,this},_div(e){return this.x/=e,this.y/=e,this},_multByPoint(e){return this.x*=e.x,this.y*=e.y,this},_divByPoint(e){return this.x/=e.x,this.y/=e.y,this},_unit(){return this._div(this.mag()),this},_perp(){let e=this.y;return this.y=this.x,this.x=-e,this},_rotate(e){let t=Math.cos(e),n=Math.sin(e),r=t*this.x-n*this.y,i=n*this.x+t*this.y;return this.x=r,this.y=i,this},_rotateAround(e,t){let n=Math.cos(e),r=Math.sin(e),i=t.x+n*(this.x-t.x)-r*(this.y-t.y),a=t.y+r*(this.x-t.x)+n*(this.y-t.y);return this.x=i,this.y=a,this},_round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},constructor:l},l.convert=function(e){if(e instanceof l)return e;if(Array.isArray(e))return new l(+e[0],+e[1]);if(e.x!==void 0&&e.y!==void 0)return new l(+e.x,+e.y);throw Error(`Expected [x, y] or {x, y} point format`)};function u(e,t,n,r){let i=3*e,a=3*(n-e)-i,o=1-i-a,s=3*t,c=3*(r-t)-s,l=1-s-c;return function(e,t=1e-6){if(e<=0)return 0;if(e>=1)return 1;let n=e;for(let r=0;r<8;r++){let r=((o*n+a)*n+i)*n-e;if(Math.abs(r)<t)return((l*n+c)*n+s)*n;let u=(3*o*n+2*a)*n+i;if(Math.abs(u)<1e-6)break;n-=r/u}let r=0,u=1;n=e;for(let s=0;s<20;s++){let s=((o*n+a)*n+i)*n;if(Math.abs(s-e)<t)break;e>s?r=n:u=n,n=(r+u)*.5}return((l*n+c)*n+s)*n}}let d;function f(){return d??=typeof OffscreenCanvas<`u`&&new OffscreenCanvas(1,1).getContext(`2d`)&&typeof createImageBitmap==`function`,d}let p;function m(){if(p==null&&(p=!1,f())){let e=new OffscreenCanvas(5,5).getContext(`2d`,{willReadFrequently:!0});if(e){for(let t=0;t<25;t++){let n=t*4;e.fillStyle=`rgb(${n},${n+1},${n+2})`,e.fillRect(t%5,Math.floor(t/5),1,1)}let t=e.getImageData(0,0,5,5).data;for(let e=0;e<100;e++)if(e%4!=3&&t[e]!==e){p=!0;break}}}return p||!1}var h=typeof Float32Array<`u`?Float32Array:Array;Math.PI/180,180/Math.PI;function g(){var e=new h(9);return h!=Float32Array&&(e[1]=0,e[2]=0,e[3]=0,e[5]=0,e[6]=0,e[7]=0),e[0]=1,e[4]=1,e[8]=1,e}function _(e){var t=e[0],n=e[1],r=e[2],i=e[3],a=e[4],o=e[5],s=e[6],c=e[7],l=e[8];return t*(l*a-o*c)+n*(-l*i+o*s)+r*(c*i-a*s)}function v(e,t){var n=Math.sin(t),r=Math.cos(t);return e[0]=r,e[1]=n,e[2]=0,e[3]=-n,e[4]=r,e[5]=0,e[6]=0,e[7]=0,e[8]=1,e}function y(e,t){var n=t[0],r=t[1],i=t[2],a=t[3],o=n+n,s=r+r,c=i+i,l=n*o,u=r*o,d=r*s,f=i*o,p=i*s,m=i*c,h=a*o,g=a*s,_=a*c;return e[0]=1-d-m,e[3]=u-_,e[6]=f+g,e[1]=u+_,e[4]=1-l-m,e[7]=p-h,e[2]=f-g,e[5]=p+h,e[8]=1-l-d,e}function b(){var e=new h(16);return h!=Float32Array&&(e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0),e[0]=1,e[5]=1,e[10]=1,e[15]=1,e}function x(e){var t=new h(16);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t}function S(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e}function C(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=1,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}function w(e,t){var n=t[0],r=t[1],i=t[2],a=t[3],o=t[4],s=t[5],c=t[6],l=t[7],u=t[8],d=t[9],f=t[10],p=t[11],m=t[12],h=t[13],g=t[14],_=t[15],v=n*s-r*o,y=nLine truncated
|
||||||
|
//# sourceMappingURL=maplibre-gl-shared.mjs.map
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* MapLibre GL JS
|
||||||
|
* @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.0.0/LICENSE.txt
|
||||||
|
*/
|
||||||
|
import{$ as e,An as t,Ar as n,Cn as r,Gt as i,K as a,Kt as o,L as s,M as c,On as l,Pr as u,Q as d,Tn as f,W as p,Y as m,Yn as h,Yt as g,Zn as _,_ as v,_n as y,_t as b,ar as x,c as S,cn as C,d as w,fr as ee,gt as T,i as E,in as D,it as O,j as k,ji as A,jt as j,l as M,ln as te,m as N,n as ne,nt as P,o as F,p as I,rr as L,tt as R,ur as z,ut as B,vn as V,xn as H}from"./maplibre-gl-shared.mjs";var U=class{constructor(e,t){this.keyCache={},e&&this.replace(e,t)}replace(e,t){this._layerConfigs={},this._layers={},this.update(e,[],t)}update(e,t,n){for(let t of e){this._layerConfigs[t.id]=t;let e=this._layers[t.id]=c(t,n);e._featureFilter=C(e.filter,`layers[${t.id}].filter`,n),this.keyCache[t.id]&&delete this.keyCache[t.id]}for(let e of t)delete this.keyCache[e],delete this._layerConfigs[e],delete this._layers[e];this.familiesBySource={};let r=te(Object.values(this._layerConfigs),this.keyCache);for(let e of r){let t=e.map(e=>this._layers[e.id]),n=t[0];if(n.isHidden())continue;let r=n.source||``,i=this.familiesBySource[r];i||=this.familiesBySource[r]={};let a=n.sourceLayer||`_geojsonTileLayer`,o=i[a];o||=i[a]=[],o.push(t)}}},W=class{constructor(e){let t={},n=[];for(let r in e){let i=e[r],a=t[r]={};for(let e in i){let t=i[+e];if(!t||t.bitmap.width===0||t.bitmap.height===0)continue;let r={x:0,y:0,w:t.bitmap.width+2,h:t.bitmap.height+2};n.push(r),a[e]={rect:r,metrics:t.metrics}}}let{w:r,h:i}=a(n),o=new T({width:r||1,height:i||1});for(let n in e){let r=e[n];for(let e in r){let i=r[+e];if(!i||i.bitmap.width===0||i.bitmap.height===0)continue;let a=t[n][e].rect;T.copy(i.bitmap,o,{x:0,y:0},{x:a.x+1,y:a.y+1},i.bitmap)}}this.image=o,this.positions=t}};g(`GlyphAtlas`,W);var G=class{constructor(e){this.tileID=new v(e.tileID.overscaledZ,e.tileID.wrap,e.tileID.canonical.z,e.tileID.canonical.x,e.tileID.canonical.y),this.uid=e.uid,this.zoom=e.zoom,this.pixelRatio=e.pixelRatio,this.tileSize=e.tileSize,this.source=e.source,this.overscaling=this.tileID.overscaleFactor(),this.showCollisionBoxes=e.showCollisionBoxes,this.collectResourceTiming=!!e.collectResourceTiming,this.returnDependencies=!!e.returnDependencies,this.promoteId=e.promoteId,this.inFlightDependencies=[]}async parse(e,t,r,i,a){this.status=`parsing`,this.data=e,this.collisionBoxArray=new j;let o=new w(Object.keys(e.layers).sort()),c=new S(this.tileID,this.promoteId);c.bucketLayerIDs=[];let l={},u={featureIndex:c,iconDependencies:{},patternDependencies:{},glyphDependencies:{},dashDependencies:{},availableImages:r,subdivisionGranularity:a},f=t.familiesBySource[this.source];for(let t in f){let i=e.layers[t];if(!i)continue;i.version===1&&n(`Vector tile source "${this.source}" layer "${t}" does not use vector tile spec v2 and therefore may have some rendering errors.`);let a=o.encode(t),s=[];for(let e=0;e<i.length;e++){let n=i.feature(e),r=c.getId(n,t);s.push({feature:n,id:r,index:e,sourceLayerIndex:a})}for(let e of f[t]){let t=e[0];t.source!==this.source&&n(`layer.source = ${t.source} does not equal this.source = ${this.source}`),!t.isHidden(this.zoom,!0)&&(K(e,this.zoom,r),(l[t.id]=t.createBucket({index:c.bucketLayerIDs.length,layers:e,zoom:this.zoom,pixelRatio:this.pixelRatio,overscaling:this.overscaling,collisionBoxArray:this.collisionBoxArray,sourceLayerIndex:a,sourceID:this.source})).populate(s,u,this.tileID.canonical),c.bucketLayerIDs.push(e.map(e=>e.id)))}}let m=ee(u.glyphDependencies,e=>Object.keys(e).map(Number));for(let e of this.inFlightDependencies)e?.abort();this.inFlightDependencies=[];let h=Promise.resolve({});if(Object.keys(m).length){let e=new AbortController;this.inFlightDependencies.push(e),h=i.sendAsync({type:`GG`,data:{stacks:m,source:this.source,tileID:this.tileID,type:`glyphs`}},e)}let g=Object.keys(u.iconDependencies),_=Promise.resolve({});if(g.length){let e=new AbortController;this.inFlightDependencies.push(e),_=i.sendAsync({type:`GI`,data:{icons:g,source:this.source,tileID:this.tileID,type:`icons`}},e)}let v=Object.keys(u.patternDependencies),y=Promise.resolve({});if(v.length){let e=new AbortController;this.inFlightDependencies.push(e),y=i.sendAsync({type:`GI`,data:{icons:v,source:this.source,tileID:this.tileID,type:`patterns`}},e)}let b=u.dashDependencies,x=Promise.resolve({});if(Object.keys(b).length){let e=new AbortController;this.inFlightDependencies.push(e),x=i.sendAsync({type:`GDA`,data:{dashes:b}},e)}let[C,T,E,D]=await Promise.all([h,_,y,x]),k=new W(C),A=new p(T,E);for(let e in l){let t=l[e];t instanceof s?(K(t.layers,this.zoom,r),ne({bucket:t,glyphMap:C,glyphPositions:k.positions,imageMap:T,imagePositions:A.iconPositions,showCollisionBoxes:this.showCollisionBoxes,canonical:this.tileID.canonical,subdivisionGranularity:u.subdivisionGranularity})):t.hasDependencies&&(t instanceof O||t instanceof R||t instanceof d)&&(K(t.layers,this.zoom,r),t.addFeatures(u,this.tileID.canonical,A.patternPositions,D))}return this.status=`done`,{buckets:Object.values(l).filter(e=>!e.isEmpty()),featureIndex:c,collisionBoxArray:this.collisionBoxArray,glyphAtlasImage:k.iLine truncated
|
||||||
|
//# sourceMappingURL=maplibre-gl-worker.mjs.map
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
.maplibregl-map{font:12px/20px Helvetica Neue,Arial,Helvetica,sans-serif;overflow:hidden;position:relative;-webkit-tap-highlight-color:rgb(0 0 0/0)}.maplibregl-canvas{position:absolute;left:0;top:0}.maplibregl-map:fullscreen{width:100%;height:100%}.maplibregl-ctrl-group button.maplibregl-ctrl-compass{touch-action:none}.maplibregl-canvas-container.maplibregl-interactive,.maplibregl-ctrl-group button.maplibregl-ctrl-compass{cursor:grab;-webkit-user-select:none;-moz-user-select:none;user-select:none}.maplibregl-canvas-container.maplibregl-interactive.maplibregl-track-pointer{cursor:pointer}.maplibregl-canvas-container.maplibregl-interactive:active,.maplibregl-ctrl-group button.maplibregl-ctrl-compass:active{cursor:grabbing}.maplibregl-canvas-container.maplibregl-touch-zoom-rotate,.maplibregl-canvas-container.maplibregl-touch-zoom-rotate .maplibregl-canvas{touch-action:pan-x pan-y}.maplibregl-canvas-container.maplibregl-touch-drag-pan,.maplibregl-canvas-container.maplibregl-touch-drag-pan .maplibregl-canvas{touch-action:pinch-zoom}.maplibregl-canvas-container.maplibregl-touch-zoom-rotate.maplibregl-touch-drag-pan,.maplibregl-canvas-container.maplibregl-touch-zoom-rotate.maplibregl-touch-drag-pan .maplibregl-canvas{touch-action:none}.maplibregl-canvas-container.maplibregl-touch-drag-pan.maplibregl-cooperative-gestures,.maplibregl-canvas-container.maplibregl-touch-drag-pan.maplibregl-cooperative-gestures .maplibregl-canvas{touch-action:pan-x pan-y}.maplibregl-ctrl-bottom-left,.maplibregl-ctrl-bottom-right,.maplibregl-ctrl-top-left,.maplibregl-ctrl-top-right{position:absolute;pointer-events:none;z-index:2}.maplibregl-ctrl-top-left{top:0;left:0}.maplibregl-ctrl-top-right{top:0;right:0}.maplibregl-ctrl-bottom-left{bottom:0;left:0}.maplibregl-ctrl-bottom-right{right:0;bottom:0}.maplibregl-ctrl{clear:both;pointer-events:auto;transform:translate(0)}.maplibregl-ctrl-top-left .maplibregl-ctrl{margin:10px 0 0 10px;float:left}.maplibregl-ctrl-top-right .maplibregl-ctrl{margin:10px 10px 0 0;float:right}.maplibregl-ctrl-bottom-left .maplibregl-ctrl{margin:0 0 10px 10px;float:left}.maplibregl-ctrl-bottom-right .maplibregl-ctrl{margin:0 10px 10px 0;float:right}.maplibregl-ctrl-group{border-radius:4px;background:#fff}.maplibregl-ctrl-group:not(:empty){box-shadow:0 0 0 2px rgba(0,0,0,.1)}@media (forced-colors:active){.maplibregl-ctrl-group:not(:empty){box-shadow:0 0 0 2px ButtonText}}.maplibregl-ctrl-group button{width:29px;height:29px;display:block;padding:0;outline:none;border:0;box-sizing:border-box;background-color:transparent;cursor:pointer}.maplibregl-ctrl-group button+button{border-top:1px solid #ddd}.maplibregl-ctrl button .maplibregl-ctrl-icon{display:block;width:100%;height:100%;background-repeat:no-repeat;background-position:50%}@media (forced-colors:active){.maplibregl-ctrl-icon{background-color:transparent}.maplibregl-ctrl-group button+button{border-top:1px solid ButtonText}}.maplibregl-ctrl button::-moz-focus-inner{border:0;padding:0}.maplibregl-ctrl-attrib-button:focus,.maplibregl-ctrl-group button:focus{box-shadow:0 0 2px 2px #0096ff}.maplibregl-ctrl button:disabled{cursor:not-allowed}.maplibregl-ctrl button:disabled .maplibregl-ctrl-icon{opacity:.25}@media (hover:hover){.maplibregl-ctrl button:not(:disabled):hover{background-color:rgba(0,0,0,.05)}}.maplibregl-ctrl button:not(:disabled):active{background-color:rgba(0,0,0,.05)}.maplibregl-ctrl-group button:focus:focus-visible{box-shadow:0 0 2px 2px #0096ff}.maplibregl-ctrl-group button:focus:not(:focus-visible){box-shadow:none}.maplibregl-ctrl-group button:focus:first-child{border-radius:4px 4px 0 0}.maplibregl-ctrl-group button:focus:last-child{border-radius:0 0 4px 4px}.maplibregl-ctrl-group button:focus:only-child{border-radius:inherit}.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5'/%3E%3C/svg%3E")}@media (forced-colors:active){.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon{background-image:url("data:image/svLine truncated
|
||||||
@@ -0,0 +1,806 @@
|
|||||||
|
/**
|
||||||
|
* MapLibre GL JS
|
||||||
|
* @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.0.0/LICENSE.txt
|
||||||
|
*/
|
||||||
|
import{$n as e,$r as t,$t as n,A as r,Ai as i,Ar as a,At as o,B as s,Bn as c,Br as l,Bt as u,C as d,Ci as f,Cn as p,Cr as m,Ct as h,D as g,Di as _,Dn as v,Dr as y,Dt as b,E as x,Ei as S,En as C,Er as w,Et as T,F as ee,Fn as E,Fr as D,Ft as O,G as te,Gn as k,Gr as A,Gt as ne,Hn as re,Hr as ie,Ht as ae,I as oe,In as j,Ir as se,It as ce,J as le,Jn as ue,Jr as de,Jt as fe,K as pe,Kn as me,Kr as he,L as ge,Ln as _e,Lr as ve,Lt as ye,M as be,Mn as xe,Mr as Se,Mt as Ce,N as we,Nn as Te,Nr as Ee,Nt as De,O as Oe,Oi as ke,On as Ae,Or as je,Ot as Me,P as Ne,Pn as Pe,Pr as M,Pt as Fe,Qn as Ie,Qr as Le,Qt as Re,R as ze,Rn as Be,Rr as Ve,Rt as He,S as N,Si as Ue,Sn as We,Sr as Ge,St as P,T as Ke,Ti as F,Tn as qe,Tr as Je,Tt as Ye,U as Xe,Un as Ze,Ur as Qe,Ut as $e,V as et,Vn as I,Vr as tt,Vt as nt,Wn as rt,Wr as it,Wt as at,X as ot,Xn as st,Xr as ct,Xt as lt,Yn as ut,Yr as dt,Z as ft,Zn as L,Zr as pt,Zt as mt,_ as ht,_i as gt,_n as _t,_r as vt,_t as yt,a as bt,ai as xt,an as St,ar as Ct,at as wt,b as Tt,bi as Et,bn as Dt,br as Ot,bt as kt,ci as At,cn as jt,cr as Mt,ct as Nt,di as Pt,dn as Ft,dr as It,dt as Lt,ei as Rt,en as zt,er as Bt,et as Vt,f as Ht,fi as Ut,fn as R,fr as Wt,ft as Gt,g as Kt,gi as qt,gn as Jt,gr as Yt,gt as Xt,h as Zt,hi as Qt,hn as $t,hr as en,ht as tn,ii as nn,ir as rn,j as an,ji as z,jn as on,jr as sn,jt as cn,k as B,ki as ln,kn as un,kr as dn,kt as fn,li as pn,lr as mn,lt as hn,mi as gn,mn as _n,mr as vn,mt as yn,ni as bn,nn as xn,nr as Sn,oi as Cn,on as wn,or as Tn,ot as En,pi as Dn,pn as On,pr as kn,pt as An,q as jn,qn as Mn,qr as Nn,qt as Pn,r as Fn,ri as In,rn as Ln,rt as Rn,s as zn,si as Bn,sn as Vn,sr as Hn,st as Un,t as Wn,ti as Gn,tn as V,tr as Kn,u as qn,ui as Jn,un as Yn,ur as Xn,v as Zn,vi as Qn,vn as $n,vr as er,vt as tr,w as nr,wi as rr,wn as ir,wr as ar,wt as or,x as sr,xi as cr,xn as lr,xr as ur,xt as H,y as dr,yi as fr,yn as pr,yr as mr,yt as hr,z as gr,zn as _r,zr as vr,zt as yr}from"./maplibre-gl-shared.mjs";var br=`6.0.0`;function xr(){var e=new ke(4);return ke!=Float32Array&&(e[1]=0,e[2]=0),e[0]=1,e[3]=1,e}function Sr(e,t){var n=t[0],r=t[1],i=t[2],a=t[3],o=n*a-i*r;return o?(o=1/o,e[0]=a*o,e[1]=-r*o,e[2]=-i*o,e[3]=n*o,e):null}function Cr(e,t,n){var r=t[0],i=t[1],a=t[2],o=t[3],s=Math.sin(n),c=Math.cos(n);return e[0]=r*c+a*s,e[1]=i*c+o*s,e[2]=r*-s+a*c,e[3]=i*-s+o*c,e}let wr,Tr,Er;const Dr={frame(e,t,n,r){let i=r||window,a=i.requestAnimationFrame(e=>{o(),t(e)}),{unsubscribe:o}=w(e.signal,`abort`,()=>{o(),i.cancelAnimationFrame(a),n(new v(e.signal.reason))},!1)},frameAsync(e,t){return new Promise((n,r)=>{this.frame(e,n,r,t)})},getImageData(e,t=0){return this.getImageCanvasContext(e).getImageData(-t,-t,e.width+2*t,e.height+2*t)},getImageCanvasContext(e){let t=window.document.createElement(`canvas`),n=t.getContext(`2d`,{willReadFrequently:!0});if(!n)throw Error(`failed to create canvas 2d context`);return t.width=e.width,t.height=e.height,n.drawImage(e,0,0,e.width,e.height),n},resolveURL(e){return wr||=document.createElement(`a`),wr.href=e,wr.href},get hardwareConcurrency(){return typeof navigator<`u`&&navigator.hardwareConcurrency||4},get prefersReducedMotion(){return Er===void 0?matchMedia?(Tr??=matchMedia(`(prefers-reduced-motion: reduce)`),Tr.matches):!1:Er},set prefersReducedMotion(e){Er=e}},Or=new class{constructor(){this._frozenAt=null}getCurrentTime(){return this._frozenAt===null?performance.now():this._frozenAt}setNow(e){this._frozenAt=e}restoreNow(){this._frozenAt=null}isFrozen(){return this._frozenAt!==null}};function U(){return Or.getCurrentTime()}function kr(e){Or.setNow(e)}function Ar(){Or.restoreNow()}function jr(){return Or.isFrozen()}var W=class e{static{this.docStyle=typeof window<`u`&&window.document?.documentElement.style}static{this.selectProp=!e.docStyle||`userSelect`in e.docStyle?`userSelect`:`webkitUserSelect`}static create(e,t,n){let r=window.document.createElement(e);return t!==void 0&&(r.className=t),n&&n.appendChild(r),r}static createNS(e,t){return window.document.createElementNS(e,t)}static disableDrag(){e.docStyle&&e.selectProp&&(e.userSelect=e.docStyle[e.selectProp],e.docStyle[e.selectProp]=`none`)}static enableDrag(){e.docStyle&&e.selectProp&&(e.docStyle[e.selectProp]=e.userSelect)}static suppressClickInternal(t){t.preventDefault(),t.stopPropagation(),window.removeEventListener(`click`,e.suppressClickInternal,!0)}static suppressClick(){window.addEventListener(`click`,e.suppressClickInternal,!0),window.setTimeout(()=>{window.removeEventListener(`click`,e.suppressClickInternal,!0)},0)}static getScale(e){let t=e.getBoundingClientRect();return{x:t.width/e.offsetWidth||1,y:t.height/e.offsetHeight||1,boundingClientRect:t}}static getPoint(e,t,n){let r=t.boundingClientRect;return new z((n.clientX-r.left)/t.x-e.clientLeft,(n.clientY-r.top)/t.y-e.clientTop)}static mousePos(t,n){let r=e.getScale(t);return e.getPoint(t,r,n)}static touchPos(t,n){let r=[],i=e.getScale(t);for(let a of n)r.push(e.getPoint(t,i,a));return r}static sanitize(t){let n=new DOMParser().parsLine truncated
|
||||||
|
precision mediump float;
|
||||||
|
#else
|
||||||
|
#if !defined(lowp)
|
||||||
|
#define lowp
|
||||||
|
#endif
|
||||||
|
#if !defined(mediump)
|
||||||
|
#define mediump
|
||||||
|
#endif
|
||||||
|
#if !defined(highp)
|
||||||
|
#define highp
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
out highp vec4 fragColor;`,ts=`#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#else
|
||||||
|
#if !defined(lowp)
|
||||||
|
#define lowp
|
||||||
|
#endif
|
||||||
|
#if !defined(mediump)
|
||||||
|
#define mediump
|
||||||
|
#endif
|
||||||
|
#if !defined(highp)
|
||||||
|
#define highp
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
vec2 unpack_float(const float packedValue) {int packedIntValue=int(packedValue);int v0=packedIntValue/256;return vec2(v0,packedIntValue-v0*256);}vec2 unpack_opacity(const float packedOpacity) {int intOpacity=int(packedOpacity)/2;return vec2(float(intOpacity)/127.0,mod(packedOpacity,2.0));}vec4 decode_color(const vec2 encodedColor) {return vec4(unpack_float(encodedColor[0])/255.0,unpack_float(encodedColor[1])/255.0
|
||||||
|
);}float unpack_mix_vec2(const vec2 packedValue,const float t) {return mix(packedValue[0],packedValue[1],t);}vec4 unpack_mix_color(const vec4 packedColors,const float t) {vec4 minColor=decode_color(vec2(packedColors[0],packedColors[1]));vec4 maxColor=decode_color(vec2(packedColors[2],packedColors[3]));return mix(minColor,maxColor,t);}vec2 get_pattern_pos(const vec2 pixel_coord_upper,const vec2 pixel_coord_lower,const vec2 pattern_size,const float tile_units_to_pixels,const vec2 pos) {vec2 offset=mod(mod(mod(pixel_coord_upper,pattern_size)*256.0,pattern_size)*256.0+pixel_coord_lower,pattern_size);return (tile_units_to_pixels*pos+offset)/pattern_size;}mat3 rotationMatrixFromAxisAngle(vec3 u,float angle) {float c=cos(angle);float s=sin(angle);float c2=1.0-c;return mat3(u.x*u.x*c2+ c,u.x*u.y*c2-u.z*s,u.x*u.z*c2+u.y*s,u.y*u.x*c2+u.z*s,u.y*u.y*c2+ c,u.y*u.z*c2-u.x*s,u.z*u.x*c2-u.y*s,u.z*u.y*c2+u.x*s,u.z*u.z*c2+ c
|
||||||
|
);}
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
uniform sampler2D u_terrain;uniform float u_terrain_dim;uniform mat4 u_terrain_matrix;uniform vec4 u_terrain_unpack;uniform float u_terrain_exaggeration;uniform highp sampler2D u_depth;
|
||||||
|
#endif
|
||||||
|
const highp vec4 bitSh=vec4(256.*256.*256.,256.*256.,256.,1.);const highp vec4 bitShifts=vec4(1.)/bitSh;highp float unpack(highp vec4 color) {return dot(color,bitShifts);}highp float depthOpacity(vec3 frag) {
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
highp float d=unpack(texture(u_depth,frag.xy*0.5+0.5))+0.0001-frag.z;return 1.0-max(0.0,min(1.0,-d*500.0));
|
||||||
|
#else
|
||||||
|
return 1.0;
|
||||||
|
#endif
|
||||||
|
}float calculate_visibility(vec4 pos) {
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
vec3 frag=pos.xyz/pos.w;highp float d=depthOpacity(frag);if (d > 0.95) return 1.0;return (d+depthOpacity(frag+vec3(0.0,0.01,0.0)))/2.0;
|
||||||
|
#else
|
||||||
|
return 1.0;
|
||||||
|
#endif
|
||||||
|
}float ele(vec2 pos) {
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
vec4 rgb=(texture(u_terrain,pos)*255.0)*u_terrain_unpack;return rgb.r+rgb.g+rgb.b-u_terrain_unpack.a;
|
||||||
|
#else
|
||||||
|
return 0.0;
|
||||||
|
#endif
|
||||||
|
}float get_elevation(vec2 pos) {
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
#ifdef GLOBE
|
||||||
|
if ((pos.y <-32767.5) || (pos.y > 32766.5)) {return 0.0;}
|
||||||
|
#endif
|
||||||
|
vec2 coord=(u_terrain_matrix*vec4(pos,0.0,1.0)).xy*u_terrain_dim+1.0;vec2 f=fract(coord);vec2 c=(floor(coord)+0.5)/(u_terrain_dim+2.0);float d=1.0/(u_terrain_dim+2.0);float tl=ele(c);float tr=ele(c+vec2(d,0.0));float bl=ele(c+vec2(0.0,d));float br=ele(c+vec2(d,d));float elevation=mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);return elevation*u_terrain_exaggeration;
|
||||||
|
#else
|
||||||
|
return 0.0;
|
||||||
|
#endif
|
||||||
|
}const float PI=3.141592653589793;uniform mat4 u_projection_matrix;`,ns=`uniform vec4 u_color;uniform float u_opacity;void main() {fragColor=u_color*u_opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,rs=`layout(location=0) in vec2 a_pos;void main() {gl_Position=projectTile(a_pos);}`,is=`uniform vec2 u_pattern_tl_a;uniform vec2 u_pattern_br_a;uniform vec2 u_pattern_tl_b;uniform vec2 u_pattern_br_b;uniform vec2 u_texsize;uniform float u_mix;uniform float u_opacity;uniform sampler2D u_image;in vec2 v_pos_a;in vec2 v_pos_b;void main() {vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(u_pattern_tl_a/u_texsize,u_pattern_br_a/u_texsize,imagecoord);vec4 color1=texture(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(u_pattern_tl_b/u_texsize,u_pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture(u_image,pos2);fragColor=mix(color1,color2,u_mix)*u_opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,as=`uniform vec2 u_pattern_size_a;uniform vec2 u_pattern_size_b;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform float u_scale_a;uniform float u_scale_b;uniform float u_tile_units_to_pixels;layout(location=0) in vec2 a_pos;out vec2 v_pos_a;out vec2 v_pos_b;void main() {gl_Position=projectTile(a_pos);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,u_scale_a*u_pattern_size_a,u_tile_units_to_pixels,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,u_scale_b*u_pattern_size_b,u_tile_units_to_pixels,a_pos);}`,os=`in vec3 v_data;flat in float v_visibility;
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define mediump float radius
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define highp vec4 stroke_color
|
||||||
|
#pragma maplibre: define mediump float stroke_width
|
||||||
|
#pragma maplibre: define lowp float stroke_opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize mediump float radius
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize highp vec4 stroke_color
|
||||||
|
#pragma maplibre: initialize mediump float stroke_width
|
||||||
|
#pragma maplibre: initialize lowp float stroke_opacity
|
||||||
|
vec2 extrude=v_data.xy;float extrude_length=length(extrude);float antialiased_blur=v_data.z;float opacity_t=smoothstep(0.0,antialiased_blur,extrude_length-1.0);float color_t=stroke_width < 0.01 ? 0.0 : smoothstep(antialiased_blur,0.0,extrude_length-radius/(radius+stroke_width));fragColor=v_visibility*opacity_t*mix(color*opacity,stroke_color*stroke_opacity,color_t);const float epsilon=0.5/255.0;if (fragColor.r < epsilon && fragColor.g < epsilon && fragColor.b < epsilon && fragColor.a < epsilon) {discard;}
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,ss=`uniform bool u_scale_with_map;uniform bool u_pitch_with_map;uniform vec2 u_extrude_scale;uniform highp float u_globe_extrude_scale;uniform lowp float u_device_pixel_ratio;uniform highp float u_camera_to_center_distance;uniform vec2 u_translate;layout(location=0) in vec2 a_pos;out vec3 v_data;flat out float v_visibility;
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define mediump float radius
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define highp vec4 stroke_color
|
||||||
|
#pragma maplibre: define mediump float stroke_width
|
||||||
|
#pragma maplibre: define lowp float stroke_opacity
|
||||||
|
void main(void) {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize mediump float radius
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize highp vec4 stroke_color
|
||||||
|
#pragma maplibre: initialize mediump float stroke_width
|
||||||
|
#pragma maplibre: initialize lowp float stroke_opacity
|
||||||
|
vec2 pos_raw=a_pos+32768.0;vec2 extrude=vec2(mod(pos_raw,8.0)/7.0*2.0-1.0);vec2 circle_center=floor(pos_raw/8.0)+u_translate;float ele=get_elevation(circle_center);v_visibility=calculate_visibility(projectTileWithElevation(circle_center,ele));if (u_pitch_with_map) {
|
||||||
|
#ifdef GLOBE
|
||||||
|
vec3 center_vector=projectToSphere(circle_center);
|
||||||
|
#endif
|
||||||
|
float angle_scale=u_globe_extrude_scale;vec2 corner_position=circle_center;if (u_scale_with_map) {angle_scale*=(radius+stroke_width);corner_position+=extrude*u_extrude_scale*(radius+stroke_width);} else {
|
||||||
|
#ifdef GLOBE
|
||||||
|
vec4 projected_center=interpolateProjection(circle_center,center_vector,ele);
|
||||||
|
#else
|
||||||
|
vec4 projected_center=projectTileWithElevation(circle_center,ele);
|
||||||
|
#endif
|
||||||
|
corner_position+=extrude*u_extrude_scale*(radius+stroke_width)*(projected_center.w/u_camera_to_center_distance);angle_scale*=(radius+stroke_width)*(projected_center.w/u_camera_to_center_distance);}
|
||||||
|
#ifdef GLOBE
|
||||||
|
vec2 angles=extrude*angle_scale;vec3 corner_vector=globeRotateVector(center_vector,angles);gl_Position=interpolateProjection(corner_position,corner_vector,ele);
|
||||||
|
#else
|
||||||
|
gl_Position=projectTileWithElevation(corner_position,ele);
|
||||||
|
#endif
|
||||||
|
} else {gl_Position=projectTileWithElevation(circle_center,ele);if (gl_Position.z/gl_Position.w > 1.0) {gl_Position.xy=vec2(10000.0);}if (u_scale_with_map) {gl_Position.xy+=extrude*(radius+stroke_width)*u_extrude_scale*u_camera_to_center_distance;} else {gl_Position.xy+=extrude*(radius+stroke_width)*u_extrude_scale*gl_Position.w;}}float antialiasblur=-max(1.0/u_device_pixel_ratio/(radius+stroke_width),blur);v_data=vec3(extrude.x,extrude.y,antialiasblur);}`,cs=`void main() {fragColor=vec4(1.0);}`;const ls={prelude:J(es,ts),projectionMercator:J(``,`float projectLineThickness(float tileY) {return 1.0;}float projectCircleRadius(float tileY) {return 1.0;}vec4 projectTile(vec2 p) {vec4 result=u_projection_matrix*vec4(p,0.0,1.0);return result;}vec4 projectTile(vec2 p,vec2 rawPos) {vec4 result=u_projection_matrix*vec4(p,0.0,1.0);if (rawPos.y <-32767.5 || rawPos.y > 32766.5) {result.z=-10000000.0;}return result;}vec4 projectTileWithElevation(vec2 posInTile,float elevation) {return u_projection_matrix*vec4(posInTile,elevation,1.0);}vec4 projectTileFor3D(vec2 posInTile,float elevation) {return projectTileWithElevation(posInTile,elevation);}`),projectionGlobe:J(``,`#define GLOBE_RADIUS 6371008.8
|
||||||
|
uniform highp vec4 u_projection_tile_mercator_coords;uniform highp vec4 u_projection_clipping_plane;uniform highp float u_projection_transition;uniform mat4 u_projection_fallback_matrix;vec3 globeRotateVector(vec3 vec,vec2 angles) {vec3 axisRight=vec3(vec.z,0.0,-vec.x);vec3 axisUp=cross(axisRight,vec);axisRight=normalize(axisRight);axisUp=normalize(axisUp);vec2 t=tan(angles);return normalize(vec+axisRight*t.x+axisUp*t.y);}mat3 globeGetRotationMatrix(vec3 spherePos) {vec3 axisRight=vec3(spherePos.z,0.0,-spherePos.x);vec3 axisDown=cross(axisRight,spherePos);axisRight=normalize(axisRight);axisDown=normalize(axisDown);return mat3(axisRight,axisDown,spherePos
|
||||||
|
);}float circumferenceRatioAtTileY(float tileY) {float mercator_pos_y=u_projection_tile_mercator_coords.y+u_projection_tile_mercator_coords.w*tileY;float spherical_y=2.0*atan(exp(PI-(mercator_pos_y*PI*2.0)))-PI*0.5;return cos(spherical_y);}float projectLineThickness(float tileY) {float thickness=1.0/circumferenceRatioAtTileY(tileY);
|
||||||
|
if (u_projection_transition < 0.999) {return mix(1.0,thickness,u_projection_transition);} else {return thickness;}}vec3 projectToSphere(vec2 translatedPos,vec2 rawPos) {vec2 mercator_pos=u_projection_tile_mercator_coords.xy+u_projection_tile_mercator_coords.zw*translatedPos;vec2 spherical;spherical.x=mercator_pos.x*PI*2.0+PI;spherical.y=2.0*atan(exp(PI-(mercator_pos.y*PI*2.0)))-PI*0.5;float len=cos(spherical.y);vec3 pos=vec3(sin(spherical.x)*len,sin(spherical.y),cos(spherical.x)*len
|
||||||
|
);if (rawPos.y <-32767.5) {pos=vec3(0.0,1.0,0.0);}if (rawPos.y > 32766.5) {pos=vec3(0.0,-1.0,0.0);}return pos;}vec3 projectToSphere(vec2 posInTile) {return projectToSphere(posInTile,vec2(0.0,0.0));}float globeComputeClippingZ(vec3 spherePos) {return (1.0-(dot(spherePos,u_projection_clipping_plane.xyz)+u_projection_clipping_plane.w));}vec4 interpolateProjection(vec2 posInTile,vec3 spherePos,float elevation) {vec3 elevatedPos=spherePos*(1.0+elevation/GLOBE_RADIUS);vec4 globePosition=u_projection_matrix*vec4(elevatedPos,1.0);globePosition.z=globeComputeClippingZ(elevatedPos)*globePosition.w;if (u_projection_transition > 0.999) {return globePosition;}vec4 flatPosition=u_projection_fallback_matrix*vec4(posInTile,elevation,1.0);const float z_globeness_threshold=0.2;vec4 result=globePosition;result.z=mix(0.0,globePosition.z,clamp((u_projection_transition-z_globeness_threshold)/(1.0-z_globeness_threshold),0.0,1.0));result.xyw=mix(flatPosition.xyw,globePosition.xyw,u_projection_transition);if ((posInTile.y <-32767.5) || (posInTile.y > 32766.5)) {result=globePosition;const float poles_hidden_anim_percentage=0.02;result.z=mix(globePosition.z,100.0,pow(max((1.0-u_projection_transition)/poles_hidden_anim_percentage,0.0),8.0));}return result;}vec4 interpolateProjectionFor3D(vec2 posInTile,vec3 spherePos,float elevation) {vec3 elevatedPos=spherePos*(1.0+elevation/GLOBE_RADIUS);vec4 globePosition=u_projection_matrix*vec4(elevatedPos,1.0);if (u_projection_transition > 0.999) {return globePosition;}vec4 fallbackPosition=u_projection_fallback_matrix*vec4(posInTile,elevation,1.0);return mix(fallbackPosition,globePosition,u_projection_transition);}vec4 projectTile(vec2 posInTile) {return interpolateProjection(posInTile,projectToSphere(posInTile),0.0);}vec4 projectTile(vec2 posInTile,vec2 rawPos) {return interpolateProjection(posInTile,projectToSphere(posInTile,rawPos),0.0);}vec4 projectTileWithElevation(vec2 posInTile,float elevation) {return interpolateProjection(posInTile,projectToSphere(posInTile),elevation);}vec4 projectTileFor3D(vec2 posInTile,float elevation) {vec3 spherePos=projectToSphere(posInTile,posInTile);return interpolateProjectionFor3D(posInTile,spherePos,elevation);}`),background:J(ns,rs),backgroundPattern:J(is,as),circle:J(os,ss),clippingMask:J(cs,`layout(location=0) in vec2 a_pos;void main() {gl_Position=projectTile(a_pos);}`),heatmap:J(`uniform highp float u_intensity;in vec2 v_extrude;
|
||||||
|
#pragma maplibre: define highp float weight
|
||||||
|
#define GAUSS_COEF 0.3989422804014327
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp float weight
|
||||||
|
float d=-0.5*3.0*3.0*dot(v_extrude,v_extrude);float val=weight*u_intensity*GAUSS_COEF*exp(d);fragColor=vec4(val,1.0,1.0,1.0);
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform float u_extrude_scale;uniform float u_opacity;uniform float u_intensity;uniform highp float u_globe_extrude_scale;layout(location=0) in vec2 a_pos;out vec2 v_extrude;
|
||||||
|
#pragma maplibre: define highp float weight
|
||||||
|
#pragma maplibre: define mediump float radius
|
||||||
|
const highp float ZERO=1.0/255.0/16.0;
|
||||||
|
#define GAUSS_COEF 0.3989422804014327
|
||||||
|
void main(void) {
|
||||||
|
#pragma maplibre: initialize highp float weight
|
||||||
|
#pragma maplibre: initialize mediump float radius
|
||||||
|
vec2 pos_raw=a_pos+32768.0;vec2 unscaled_extrude=vec2(mod(pos_raw,8.0)/7.0*2.0-1.0);float S=sqrt(-2.0*log(ZERO/weight/u_intensity/GAUSS_COEF))/3.0;v_extrude=S*unscaled_extrude;vec2 extrude=v_extrude*radius*u_extrude_scale;vec2 circle_center=floor(pos_raw/8.0);
|
||||||
|
#ifdef GLOBE
|
||||||
|
vec2 angles=v_extrude*radius*u_globe_extrude_scale;vec3 center_vector=projectToSphere(circle_center);vec3 corner_vector=globeRotateVector(center_vector,angles);gl_Position=interpolateProjection(circle_center+extrude,corner_vector,0.0);
|
||||||
|
#else
|
||||||
|
gl_Position=projectTileFor3D(circle_center+extrude,get_elevation(circle_center));
|
||||||
|
#endif
|
||||||
|
}`),heatmapTexture:J(`uniform sampler2D u_image;uniform sampler2D u_color_ramp;uniform float u_opacity;in vec2 v_pos;void main() {float t=texture(u_image,v_pos).r;vec4 color=texture(u_color_ramp,vec2(t,0.5));fragColor=color*u_opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(0.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform mat4 u_matrix;uniform vec2 u_world;layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos*u_world,0,1);v_pos.x=a_pos.x;v_pos.y=1.0-a_pos.y;}`),collisionBox:J(`flat in float v_placed;flat in float v_notUsed;void main() {float alpha=0.5;fragColor=vec4(1.0,0.0,0.0,1.0)*alpha;if (v_placed > 0.5) {fragColor=vec4(0.0,0.0,1.0,0.5)*alpha;}if (v_notUsed > 0.5) {fragColor*=.1;}}`,`layout(location=0) in vec2 a_anchor_pos;layout(location=1) in vec2 a_placed;layout(location=2) in vec2 a_box_real;uniform vec2 u_pixel_extrude_scale;flat out float v_placed;flat out float v_notUsed;void main() {gl_Position=projectTileWithElevation(a_anchor_pos,get_elevation(a_anchor_pos));gl_Position.xy=((a_box_real+0.5)*u_pixel_extrude_scale*2.0-1.0)*vec2(1.0,-1.0)*gl_Position.w;if (gl_Position.z/gl_Position.w < 1.1) {gl_Position.z=0.5;}v_placed=a_placed.x;v_notUsed=a_placed.y;}`),collisionCircle:J(`flat in float v_radius;in vec2 v_extrude;flat in float v_collision;void main() {float alpha=0.5;float stroke_radius=0.9;float distance_to_center=length(v_extrude);float distance_to_edge=abs(distance_to_center-v_radius);float opacity_t=smoothstep(-stroke_radius,0.0,-distance_to_edge);vec4 color=mix(vec4(0.0,0.0,1.0,0.5),vec4(1.0,0.0,0.0,1.0),v_collision);fragColor=color*alpha*opacity_t;}`,`layout(location=0) in vec2 a_pos;layout(location=1) in float a_radius;layout(location=2) in vec2 a_flags;uniform vec2 u_viewport_size;flat out float v_radius;out vec2 v_extrude;flat out float v_collision;void main() {float radius=a_radius;float collision=a_flags.x;float vertexIdx=a_flags.y;vec2 quadVertexOffset=vec2(mix(-1.0,1.0,float(vertexIdx >=2.0)),mix(-1.0,1.0,float(vertexIdx >=1.0 && vertexIdx <=2.0)));vec2 quadVertexExtent=quadVertexOffset*radius;float padding_factor=1.2;v_radius=radius;v_extrude=quadVertexExtent*padding_factor;v_collision=collision;gl_Position=vec4((a_pos/u_viewport_size*2.0-1.0)*vec2(1.0,-1.0),0.0,1.0)+vec4(quadVertexExtent*padding_factor/u_viewport_size*2.0,0.0,0.0);}`),colorRelief:J(`#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
uniform sampler2D u_image;uniform vec4 u_unpack;uniform sampler2D u_elevation_stops;uniform sampler2D u_color_stops;uniform int u_color_ramp_size;uniform float u_opacity;in vec2 v_pos;float getElevation(vec2 coord) {vec4 data=texture(u_image,coord)*255.0;data.a=-1.0;return dot(data,u_unpack);}float getElevationStop(int stop) {float x=(float(stop)+0.5)/float(u_color_ramp_size);vec4 data=texture(u_elevation_stops,vec2(x,0))*255.0;data.a=-1.0;return dot(data,u_unpack);}void main() {float el=getElevation(v_pos);int r=(u_color_ramp_size-1);int l=0;float el_l=getElevationStop(l);float el_r=getElevationStop(r);while(r-l > 1){int m=(r+l)/2;float el_m=getElevationStop(m);if(el < el_m){r=m;el_r=el_m;}else
|
||||||
|
{l=m;el_l=el_m;}}float x=(float(l)+(el-el_l)/(el_r-el_l)+0.5)/float(u_color_ramp_size);fragColor=u_opacity*texture(u_color_stops,vec2(x,0));
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_dimension;layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=projectTile(a_pos,a_pos);highp vec2 epsilon=1.0/u_dimension;float scale=(u_dimension.x-2.0)/u_dimension.x;v_pos=(a_pos/8192.0)*scale+epsilon;if (a_pos.y <-32767.5) {v_pos.y=0.0;}if (a_pos.y > 32766.5) {v_pos.y=1.0;}}`),debug:J(`uniform highp vec4 u_color;uniform sampler2D u_overlay;in vec2 v_uv;void main() {vec4 overlay_color=texture(u_overlay,v_uv);fragColor=mix(u_color,overlay_color,overlay_color.a);}`,`layout(location=0) in vec2 a_pos;out vec2 v_uv;uniform float u_overlay_scale;void main() {v_uv=a_pos/8192.0;gl_Position=projectTileWithElevation(a_pos*u_overlay_scale,get_elevation(a_pos));}`),depth:J(cs,`layout(location=0) in vec2 a_pos;void main() {
|
||||||
|
#ifdef GLOBE
|
||||||
|
gl_Position=projectTileFor3D(a_pos,0.0);
|
||||||
|
#else
|
||||||
|
gl_Position=u_projection_matrix*vec4(a_pos,0.0,1.0);
|
||||||
|
#endif
|
||||||
|
}`),fill:J(`#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
fragColor=color*opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}gl_Position=projectTile(a_pos+u_fill_translate,a_pos);}`),fillOutline:J(`in vec2 v_pos;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define highp vec4 outline_color
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 outline_color
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
float dist=length(v_pos-gl_FragCoord.xy);float alpha=1.0-smoothstep(0.0,1.0,dist);fragColor=outline_color*(alpha*opacity);
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_world;uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;out vec2 v_pos;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define highp vec4 outline_color
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 outline_color
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}gl_Position=projectTile(a_pos+u_fill_translate,a_pos);v_pos=(gl_Position.xy/gl_Position.w+1.0)/2.0*u_world;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
}`),fillOutlinePattern:J(`uniform vec2 u_texsize;uniform sampler2D u_image;uniform float u_fade;in vec2 v_pos_a;in vec2 v_pos_b;in vec2 v_pos;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture(u_image,pos2);float dist=length(v_pos-gl_FragCoord.xy);float alpha=1.0-smoothstep(0.0,1.0,dist);fragColor=mix(color1,color2,u_fade)*alpha*opacity;
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_world;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec3 u_scale;uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;out vec2 v_pos_a;out vec2 v_pos_b;out vec2 v_pos;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_to
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;gl_Position=projectTile(a_pos+u_fill_translate,a_pos);vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,a_pos);v_pos=(gl_Position.xy/gl_Position.w+1.0)/2.0*u_world;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
}`),fillPattern:J(`#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;in vec2 v_pos_a;in vec2 v_pos_b;
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture(u_image,pos2);fragColor=mix(color1,color2,u_fade)*opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec3 u_scale;uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;out vec2 v_pos_a;out vec2 v_pos_b;
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_to
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileZoomRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;gl_Position=projectTile(a_pos+u_fill_translate,a_pos);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileZoomRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileZoomRatio,a_pos);}`),fillExtrusion:J(`in vec4 v_color;void main() {fragColor=v_color;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp vec3 u_lightpos_globe;uniform lowp float u_lightintensity;uniform float u_vertical_gradient;uniform lowp float u_opacity;uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;layout(location=1) in vec4 a_normal_ed;
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
layout(location=2) in vec2 a_centroid;
|
||||||
|
#endif
|
||||||
|
out vec4 v_color;
|
||||||
|
#pragma maplibre: define highp float base
|
||||||
|
#pragma maplibre: define highp float height
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp float base
|
||||||
|
#pragma maplibre: initialize highp float height
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
vec3 normal=a_normal_ed.xyz;
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
float height_terrain3d_offset=get_elevation(a_centroid);float base_terrain3d_offset=height_terrain3d_offset-(base > 0.0 ? 0.0 : 10.0);
|
||||||
|
#else
|
||||||
|
float height_terrain3d_offset=0.0;float base_terrain3d_offset=0.0;
|
||||||
|
#endif
|
||||||
|
base=max(0.0,base)+base_terrain3d_offset;height=max(0.0,height)+height_terrain3d_offset;float t=mod(normal.x,2.0);float elevation=t > 0.0 ? height : base;vec2 posInTile=a_pos+u_fill_translate;
|
||||||
|
#ifdef GLOBE
|
||||||
|
vec3 spherePos=projectToSphere(posInTile,a_pos);gl_Position=interpolateProjectionFor3D(posInTile,spherePos,elevation);
|
||||||
|
#else
|
||||||
|
gl_Position=u_projection_matrix*vec4(posInTile,elevation,1.0);
|
||||||
|
#endif
|
||||||
|
float colorvalue=color.r*0.2126+color.g*0.7152+color.b*0.0722;v_color=vec4(0.0,0.0,0.0,1.0);vec4 ambientlight=vec4(0.03,0.03,0.03,1.0);color+=ambientlight;vec3 normalForLighting=normal/16384.0;float directional=clamp(dot(normalForLighting,u_lightpos),0.0,1.0);
|
||||||
|
#ifdef GLOBE
|
||||||
|
mat3 rotMatrix=globeGetRotationMatrix(spherePos);normalForLighting=rotMatrix*normalForLighting;directional=mix(directional,clamp(dot(normalForLighting,u_lightpos_globe),0.0,1.0),u_projection_transition);
|
||||||
|
#endif
|
||||||
|
directional=mix((1.0-u_lightintensity),max((1.0-colorvalue+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_color.r+=clamp(color.r*directional*u_lightcolor.r,mix(0.0,0.3,1.0-u_lightcolor.r),1.0);v_color.g+=clamp(color.g*directional*u_lightcolor.g,mix(0.0,0.3,1.0-u_lightcolor.g),1.0);v_color.b+=clamp(color.b*directional*u_lightcolor.b,mix(0.0,0.3,1.0-u_lightcolor.b),1.0);v_color*=u_opacity;}`),fillExtrusionPattern:J(`uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;in vec2 v_pos_a;in vec2 v_pos_b;in vec4 v_lighting;
|
||||||
|
#pragma maplibre: define lowp float base
|
||||||
|
#pragma maplibre: define lowp float height
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float base
|
||||||
|
#pragma maplibre: initialize lowp float height
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_to
|
||||||
|
vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture(u_image,pos2);vec4 mixedColor=mix(color1,color2,u_fade);fragColor=mixedColor*v_lighting;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform float u_height_factor;uniform vec3 u_scale;uniform float u_vertical_gradient;uniform lowp float u_opacity;uniform vec2 u_fill_translate;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp vec3 u_lightpos_globe;uniform lowp float u_lightintensity;layout(location=0) in vec2 a_pos;layout(location=1) in vec4 a_normal_ed;
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
layout(location=2) in vec2 a_centroid;
|
||||||
|
#endif
|
||||||
|
#ifdef GLOBE
|
||||||
|
out vec3 v_sphere_pos;
|
||||||
|
#endif
|
||||||
|
out vec2 v_pos_a;out vec2 v_pos_b;out vec4 v_lighting;
|
||||||
|
#pragma maplibre: define lowp float base
|
||||||
|
#pragma maplibre: define lowp float height
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float base
|
||||||
|
#pragma maplibre: initialize lowp float height
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_to
|
||||||
|
vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec3 normal=a_normal_ed.xyz;float edgedistance=a_normal_ed.w;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
float height_terrain3d_offset=get_elevation(a_centroid);float base_terrain3d_offset=height_terrain3d_offset-(base > 0.0 ? 0.0 : 10.0);
|
||||||
|
#else
|
||||||
|
float height_terrain3d_offset=0.0;float base_terrain3d_offset=0.0;
|
||||||
|
#endif
|
||||||
|
base=max(0.0,base)+base_terrain3d_offset;height=max(0.0,height)+height_terrain3d_offset;float t=mod(normal.x,2.0);float elevation=t > 0.0 ? height : base;vec2 posInTile=a_pos+u_fill_translate;
|
||||||
|
#ifdef GLOBE
|
||||||
|
vec3 spherePos=projectToSphere(posInTile,a_pos);vec3 elevatedPos=spherePos*(1.0+elevation/GLOBE_RADIUS);v_sphere_pos=elevatedPos;gl_Position=interpolateProjectionFor3D(posInTile,spherePos,elevation);
|
||||||
|
#else
|
||||||
|
gl_Position=u_projection_matrix*vec4(posInTile,elevation,1.0);
|
||||||
|
#endif
|
||||||
|
vec2 pos=normal.x==1.0 && normal.y==0.0 && normal.z==16384.0
|
||||||
|
? a_pos
|
||||||
|
: vec2(edgedistance,elevation*u_height_factor);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,pos);v_lighting=vec4(0.0,0.0,0.0,1.0);float directional=clamp(dot(normal/16383.0,u_lightpos),0.0,1.0);directional=mix((1.0-u_lightintensity),max((0.5+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_lighting.rgb+=clamp(directional*u_lightcolor,mix(vec3(0.0),vec3(0.3),1.0-u_lightcolor),vec3(1.0));v_lighting*=u_opacity;}`),hillshadePrepare:J(`#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
uniform sampler2D u_image;in vec2 v_pos;uniform vec2 u_dimension;uniform float u_zoom;uniform vec4 u_unpack;float getElevation(vec2 coord,float bias) {vec4 data=texture(u_image,coord)*255.0;data.a=-1.0;return dot(data,u_unpack);}void main() {vec2 epsilon=1.0/u_dimension;float tileSize=u_dimension.x-2.0;float a=getElevation(v_pos+vec2(-epsilon.x,-epsilon.y),0.0);float b=getElevation(v_pos+vec2(0,-epsilon.y),0.0);float c=getElevation(v_pos+vec2(epsilon.x,-epsilon.y),0.0);float d=getElevation(v_pos+vec2(-epsilon.x,0),0.0);float e=getElevation(v_pos,0.0);float f=getElevation(v_pos+vec2(epsilon.x,0),0.0);float g=getElevation(v_pos+vec2(-epsilon.x,epsilon.y),0.0);float h=getElevation(v_pos+vec2(0,epsilon.y),0.0);float i=getElevation(v_pos+vec2(epsilon.x,epsilon.y),0.0);float exaggerationFactor=u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;float exaggeration=u_zoom < 15.0 ? (u_zoom-15.0)*exaggerationFactor : 0.0;vec2 deriv=vec2((c+f+f+i)-(a+d+d+g),(g+h+h+i)-(a+b+b+c))*tileSize/pow(2.0,exaggeration+(28.2562-u_zoom));fragColor=clamp(vec4(deriv.x/8.0+0.5,deriv.y/8.0+0.5,1.0,1.0),0.0,1.0);
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform mat4 u_matrix;uniform vec2 u_dimension;layout(location=0) in vec2 a_pos;layout(location=1) in vec2 a_texture_pos;out vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);highp vec2 epsilon=1.0/u_dimension;float scale=(u_dimension.x-2.0)/u_dimension.x;v_pos=(a_texture_pos/8192.0)*scale+epsilon;}`),hillshade:J(`uniform sampler2D u_image;in vec2 v_pos;uniform vec2 u_latrange;uniform float u_exaggeration;uniform vec4 u_accent;uniform int u_method;uniform float u_altitudes[NUM_ILLUMINATION_SOURCES];uniform float u_azimuths[NUM_ILLUMINATION_SOURCES];uniform vec4 u_shadows[NUM_ILLUMINATION_SOURCES];uniform vec4 u_highlights[NUM_ILLUMINATION_SOURCES];
|
||||||
|
#define PI 3.141592653589793
|
||||||
|
#define STANDARD 0
|
||||||
|
#define COMBINED 1
|
||||||
|
#define IGOR 2
|
||||||
|
#define MULTIDIRECTIONAL 3
|
||||||
|
#define BASIC 4
|
||||||
|
float get_aspect(vec2 deriv){return deriv.x !=0.0 ? atan(deriv.y,-deriv.x) : PI/2.0*(deriv.y > 0.0 ? 1.0 :-1.0);}void igor_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;float aspect=get_aspect(deriv);float azimuth=u_azimuths[0]+PI;float slope_stength=atan(length(deriv))*2.0/PI;float aspect_strength=1.0-abs(mod((aspect+azimuth)/PI+0.5,2.0)-1.0);float shadow_strength=slope_stength*aspect_strength;float highlight_strength=slope_stength*(1.0-aspect_strength);fragColor=u_shadows[0]*shadow_strength+u_highlights[0]*highlight_strength;}void standard_hillshade(vec2 deriv){float azimuth=u_azimuths[0]+PI;float slope=atan(0.625*length(deriv));float aspect=get_aspect(deriv);float intensity=u_exaggeration;float base=1.875-intensity*1.75;float maxValue=0.5*PI;float scaledSlope=intensity !=0.5 ? ((pow(base,slope)-1.0)/(pow(base,maxValue)-1.0))*maxValue : slope;float accent=cos(scaledSlope);vec4 accent_color=(1.0-accent)*u_accent*clamp(intensity*2.0,0.0,1.0);float shade=abs(mod((aspect+azimuth)/PI+0.5,2.0)-1.0);vec4 shade_color=mix(u_shadows[0],u_highlights[0],shade)*sin(scaledSlope)*clamp(intensity*2.0,0.0,1.0);fragColor=accent_color*(1.0-shade_color.a)+shade_color;}void basic_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;float azimuth=u_azimuths[0]+PI;float cos_az=cos(azimuth);float sin_az=sin(azimuth);float cos_alt=cos(u_altitudes[0]);float sin_alt=sin(u_altitudes[0]);float cang=(sin_alt-(deriv.y*cos_az*cos_alt-deriv.x*sin_az*cos_alt))/sqrt(1.0+dot(deriv,deriv));float shade=clamp(cang,0.0,1.0);if(shade > 0.5){fragColor=u_highlights[0]*(2.0*shade-1.0);}else
|
||||||
|
{fragColor=u_shadows[0]*(1.0-2.0*shade);}}void multidirectional_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;fragColor=vec4(0,0,0,0);for(int i=0; i < NUM_ILLUMINATION_SOURCES; i++){float cos_alt=cos(u_altitudes[i]);float sin_alt=sin(u_altitudes[i]);float cos_az=-cos(u_azimuths[i]);float sin_az=-sin(u_azimuths[i]);float cang=(sin_alt-(deriv.y*cos_az*cos_alt-deriv.x*sin_az*cos_alt))/sqrt(1.0+dot(deriv,deriv));float shade=clamp(cang,0.0,1.0);if(shade > 0.5){fragColor+=u_highlights[i]*(2.0*shade-1.0)/float(NUM_ILLUMINATION_SOURCES);}else
|
||||||
|
{fragColor+=u_shadows[i]*(1.0-2.0*shade)/float(NUM_ILLUMINATION_SOURCES);}}}void combined_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;float azimuth=u_azimuths[0]+PI;float cos_az=cos(azimuth);float sin_az=sin(azimuth);float cos_alt=cos(u_altitudes[0]);float sin_alt=sin(u_altitudes[0]);float cang=acos((sin_alt-(deriv.y*cos_az*cos_alt-deriv.x*sin_az*cos_alt))/sqrt(1.0+dot(deriv,deriv)));cang=clamp(cang,0.0,PI/2.0);float shade=cang*atan(length(deriv))*4.0/PI/PI;float highlight=(PI/2.0-cang)*atan(length(deriv))*4.0/PI/PI;fragColor=u_shadows[0]*shade+u_highlights[0]*highlight;}void main() {vec4 pixel=texture(u_image,v_pos);float scaleFactor=cos(radians((u_latrange[0]-u_latrange[1])*(1.0-v_pos.y)+u_latrange[1]));vec2 deriv=((pixel.rg*8.0)-4.0)/scaleFactor;if (u_method==BASIC) {basic_hillshade(deriv);} else if (u_method==COMBINED) {combined_hillshade(deriv);} else if (u_method==IGOR) {igor_hillshade(deriv);} else if (u_method==MULTIDIRECTIONAL) {multidirectional_hillshade(deriv);} else if (u_method==STANDARD) {standard_hillshade(deriv);} else {standard_hillshade(deriv);}
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform mat4 u_matrix;layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=projectTile(a_pos,a_pos);v_pos=a_pos/8192.0;if (a_pos.y <-32767.5) {v_pos.y=0.0;}if (a_pos.y > 32766.5) {v_pos.y=1.0;}}`),line:J(`uniform lowp float u_device_pixel_ratio;flat in vec2 v_width2;in vec2 v_normal;in float v_gamma_scale;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);fragColor=color*(alpha*opacity);
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`
|
||||||
|
#define scale 0.015873016
|
||||||
|
layout(location=0) in vec2 a_pos_normal;layout(location=1) in vec4 a_data;uniform vec2 u_translation;uniform mediump float u_ratio;uniform vec2 u_units_to_pixels;uniform lowp float u_device_pixel_ratio;out vec2 v_normal;flat out vec2 v_width2;out float v_gamma_scale;out highp float v_linesofar;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define mediump float gapwidth
|
||||||
|
#pragma maplibre: define lowp float offset
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump float gapwidth
|
||||||
|
#pragma maplibre: initialize lowp float offset
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;v_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*2.0;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
v_gamma_scale=1.0;
|
||||||
|
#else
|
||||||
|
float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;
|
||||||
|
#endif
|
||||||
|
v_width2=vec2(outset,inset);}`),lineGradient:J(`uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;flat in vec2 v_width2;in vec2 v_normal;in float v_gamma_scale;in highp vec2 v_uv;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);vec4 color=texture(u_image,v_uv);fragColor=color*(alpha*opacity);
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`
|
||||||
|
#define scale 0.015873016
|
||||||
|
layout(location=0) in vec2 a_pos_normal;layout(location=1) in vec4 a_data;layout(location=2) in float a_uv_x;layout(location=3) in float a_split_index;uniform vec2 u_translation;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_units_to_pixels;uniform float u_image_height;out vec2 v_normal;flat out vec2 v_width2;out float v_gamma_scale;out highp vec2 v_uv;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define mediump float gapwidth
|
||||||
|
#pragma maplibre: define lowp float offset
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump float gapwidth
|
||||||
|
#pragma maplibre: initialize lowp float offset
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;highp float texel_height=1.0/u_image_height;highp float half_texel_height=0.5*texel_height;v_uv=vec2(a_uv_x,a_split_index*texel_height-half_texel_height);vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
v_gamma_scale=1.0;
|
||||||
|
#else
|
||||||
|
float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;
|
||||||
|
#endif
|
||||||
|
v_width2=vec2(outset,inset);}`),linePattern:J(`#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
uniform lowp float u_device_pixel_ratio;uniform vec2 u_texsize;uniform float u_fade;uniform mediump vec3 u_scale;uniform sampler2D u_image;in vec2 v_normal;flat in vec2 v_width2;in float v_linesofar;in float v_gamma_scale;flat in float v_width;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_to
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_to
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileZoomRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;vec2 pattern_size_a=vec2(display_size_a.x*fromScale/tileZoomRatio,display_size_a.y);vec2 pattern_size_b=vec2(display_size_b.x*toScale/tileZoomRatio,display_size_b.y);float aspect_a=display_size_a.y/v_width;float aspect_b=display_size_b.y/v_width;float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);float x_a=mod(v_linesofar/pattern_size_a.x*aspect_a,1.0);float x_b=mod(v_linesofar/pattern_size_b.x*aspect_b,1.0);float y=0.5*v_normal.y+0.5;vec2 texel_size=1.0/u_texsize;vec2 pos_a=mix(pattern_tl_a*texel_size-texel_size,pattern_br_a*texel_size+texel_size,vec2(x_a,y));vec2 pos_b=mix(pattern_tl_b*texel_size-texel_size,pattern_br_b*texel_size+texel_size,vec2(x_b,y));vec4 color=mix(texture(u_image,pos_a),texture(u_image,pos_b),u_fade);fragColor=color*alpha*opacity;
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`
|
||||||
|
#define scale 0.015873016
|
||||||
|
#define LINE_DISTANCE_SCALE 2.0
|
||||||
|
layout(location=0) in vec2 a_pos_normal;layout(location=1) in vec4 a_data;uniform vec2 u_translation;uniform vec2 u_units_to_pixels;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;out vec2 v_normal;flat out vec2 v_width2;out float v_linesofar;out float v_gamma_scale;flat out float v_width;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp float offset
|
||||||
|
#pragma maplibre: define mediump float gapwidth
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
#pragma maplibre: define lowp float floorwidth
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_from
|
||||||
|
#pragma maplibre: define lowp vec4 pattern_to
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: define lowp float pixel_ratio_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize lowp float offset
|
||||||
|
#pragma maplibre: initialize mediump float gapwidth
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
#pragma maplibre: initialize lowp float floorwidth
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 pattern_to
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_from
|
||||||
|
#pragma maplibre: initialize lowp float pixel_ratio_to
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
v_gamma_scale=1.0;
|
||||||
|
#else
|
||||||
|
float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;
|
||||||
|
#endif
|
||||||
|
v_linesofar=a_linesofar;v_width2=vec2(outset,inset);v_width=floorwidth;}`),lineSDF:J(`uniform lowp float u_device_pixel_ratio;uniform lowp float u_lineatlas_width;uniform sampler2D u_image;uniform float u_mix;in vec2 v_normal;flat in vec2 v_width2;in vec2 v_tex_a;in vec2 v_tex_b;in float v_gamma_scale;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
#pragma maplibre: define lowp float floorwidth
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
#pragma maplibre: initialize lowp float floorwidth
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_to
|
||||||
|
float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);float sdfdist_a=texture(u_image,v_tex_a).a;float sdfdist_b=texture(u_image,v_tex_b).a;float sdfdist=mix(sdfdist_a,sdfdist_b,u_mix);float sdfgamma=(u_lineatlas_width/256.0/u_device_pixel_ratio)/min(dasharray_from.w,dasharray_to.w);alpha*=smoothstep(0.5-sdfgamma/floorwidth,0.5+sdfgamma/floorwidth,sdfdist);fragColor=color*(alpha*opacity);
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`
|
||||||
|
#define scale 0.015873016
|
||||||
|
#define LINE_DISTANCE_SCALE 2.0
|
||||||
|
layout(location=0) in vec2 a_pos_normal;layout(location=1) in vec4 a_data;uniform vec2 u_translation;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_units_to_pixels;uniform float u_tileratio;uniform float u_crossfade_from;uniform float u_crossfade_to;uniform float u_lineatlas_height;out vec2 v_normal;flat out vec2 v_width2;out vec2 v_tex_a;out vec2 v_tex_b;out float v_gamma_scale;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define highp vec4 color
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define mediump float gapwidth
|
||||||
|
#pragma maplibre: define lowp float offset
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
#pragma maplibre: define lowp float floorwidth
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 color
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump float gapwidth
|
||||||
|
#pragma maplibre: initialize lowp float offset
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
#pragma maplibre: initialize lowp float floorwidth
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_to
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
v_gamma_scale=1.0;
|
||||||
|
#else
|
||||||
|
float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;
|
||||||
|
#endif
|
||||||
|
float u_patternscale_a_x=u_tileratio/dasharray_from.w/u_crossfade_from;float u_patternscale_a_y=-dasharray_from.z/2.0/u_lineatlas_height;float u_patternscale_b_x=u_tileratio/dasharray_to.w/u_crossfade_to;float u_patternscale_b_y=-dasharray_to.z/2.0/u_lineatlas_height;v_tex_a=vec2(a_linesofar*u_patternscale_a_x/floorwidth,normal.y*u_patternscale_a_y+(float(dasharray_from.y)+0.5)/u_lineatlas_height);v_tex_b=vec2(a_linesofar*u_patternscale_b_x/floorwidth,normal.y*u_patternscale_b_y+(float(dasharray_to.y)+0.5)/u_lineatlas_height);v_width2=vec2(outset,inset);}`),lineGradientSDF:J(`uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;uniform sampler2D u_image_dash;uniform float u_mix;uniform lowp float u_lineatlas_width;in vec2 v_normal;flat in vec2 v_width2;in vec2 v_tex_a;in vec2 v_tex_b;in float v_gamma_scale;in highp vec2 v_uv;
|
||||||
|
#ifdef GLOBE
|
||||||
|
in float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
#pragma maplibre: define lowp float floorwidth
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
#pragma maplibre: initialize lowp float floorwidth
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_to
|
||||||
|
float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);vec4 color=texture(u_image,v_uv);float sdfdist_a=texture(u_image_dash,v_tex_a).a;float sdfdist_b=texture(u_image_dash,v_tex_b).a;float sdfdist=mix(sdfdist_a,sdfdist_b,u_mix);float sdfgamma=(u_lineatlas_width/256.0)/min(dasharray_from.w,dasharray_to.w);float dash_alpha=smoothstep(0.5-sdfgamma/floorwidth,0.5+sdfgamma/floorwidth,sdfdist);fragColor=color*(alpha*dash_alpha*opacity);
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (v_depth > 1.0) {discard;}
|
||||||
|
#endif
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`
|
||||||
|
#define scale 0.015873016
|
||||||
|
#define LINE_DISTANCE_SCALE 2.0
|
||||||
|
layout(location=0) in vec2 a_pos_normal;layout(location=1) in vec4 a_data;layout(location=2) in float a_uv_x;layout(location=3) in float a_split_index;uniform vec2 u_translation;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_units_to_pixels;uniform float u_image_height;uniform float u_tileratio;uniform float u_crossfade_from;uniform float u_crossfade_to;uniform float u_lineatlas_height;out vec2 v_normal;flat out vec2 v_width2;out float v_gamma_scale;out highp vec2 v_uv;out vec2 v_tex_a;out vec2 v_tex_b;
|
||||||
|
#ifdef GLOBE
|
||||||
|
out float v_depth;
|
||||||
|
#endif
|
||||||
|
#pragma maplibre: define lowp float blur
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define mediump float gapwidth
|
||||||
|
#pragma maplibre: define lowp float offset
|
||||||
|
#pragma maplibre: define mediump float width
|
||||||
|
#pragma maplibre: define lowp float floorwidth
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: define mediump vec4 dasharray_to
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float blur
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize mediump float gapwidth
|
||||||
|
#pragma maplibre: initialize lowp float offset
|
||||||
|
#pragma maplibre: initialize mediump float width
|
||||||
|
#pragma maplibre: initialize lowp float floorwidth
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_from
|
||||||
|
#pragma maplibre: initialize mediump vec4 dasharray_to
|
||||||
|
if (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;float texel_height=1.0/u_image_height;float half_texel_height=0.5*texel_height;v_uv=vec2(a_uv_x,a_split_index*texel_height-half_texel_height);vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;
|
||||||
|
#ifdef GLOBE
|
||||||
|
v_depth=gl_Position.z/gl_Position.w;
|
||||||
|
#endif
|
||||||
|
#ifdef TERRAIN3D
|
||||||
|
v_gamma_scale=1.0;
|
||||||
|
#else
|
||||||
|
float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;
|
||||||
|
#endif
|
||||||
|
float u_patternscale_a_x=u_tileratio/dasharray_from.w/u_crossfade_from;float u_patternscale_a_y=-dasharray_from.z/2.0/u_lineatlas_height;float u_patternscale_b_x=u_tileratio/dasharray_to.w/u_crossfade_to;float u_patternscale_b_y=-dasharray_to.z/2.0/u_lineatlas_height;v_tex_a=vec2(a_linesofar*u_patternscale_a_x/floorwidth,normal.y*u_patternscale_a_y+(float(dasharray_from.y)+0.5)/u_lineatlas_height);v_tex_b=vec2(a_linesofar*u_patternscale_b_x/floorwidth,normal.y*u_patternscale_b_y+(float(dasharray_to.y)+0.5)/u_lineatlas_height);v_width2=vec2(outset,inset);}`),layerOpacity:J(`uniform sampler2D u_image;uniform float u_opacity;in vec2 v_pos;void main() {fragColor=texture(u_image,v_pos)*u_opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(0.0);
|
||||||
|
#endif
|
||||||
|
}`,`layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=vec4(a_pos.x*2.0-1.0,1.0-a_pos.y*2.0,0.0,1.0);v_pos.x=a_pos.x;v_pos.y=1.0-a_pos.y;}`),raster:J(`uniform float u_fade_t;uniform float u_opacity;uniform sampler2D u_image0;uniform sampler2D u_image1;in vec2 v_pos0;in vec2 v_pos1;uniform float u_brightness_low;uniform float u_brightness_high;uniform float u_saturation_factor;uniform float u_contrast_factor;uniform vec3 u_spin_weights;void main() {vec4 color0=texture(u_image0,v_pos0);vec4 color1=texture(u_image1,v_pos1);if (color0.a > 0.0) {color0.rgb=color0.rgb/color0.a;}if (color1.a > 0.0) {color1.rgb=color1.rgb/color1.a;}vec4 color=mix(color0,color1,u_fade_t);color.a*=u_opacity;vec3 rgb=color.rgb;rgb=vec3(dot(rgb,u_spin_weights.xyz),dot(rgb,u_spin_weights.zxy),dot(rgb,u_spin_weights.yzx));float average=(color.r+color.g+color.b)/3.0;rgb+=(average-rgb)*u_saturation_factor;rgb=(rgb-0.5)*u_contrast_factor+0.5;vec3 u_high_vec=vec3(u_brightness_low,u_brightness_low,u_brightness_low);vec3 u_low_vec=vec3(u_brightness_high,u_brightness_high,u_brightness_high);fragColor=vec4(mix(u_high_vec,u_low_vec,rgb)*color.a,color.a);
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`uniform vec2 u_tl_parent;uniform float u_scale_parent;uniform float u_buffer_scale;uniform vec4 u_coords_top;uniform vec4 u_coords_bottom;layout(location=0) in vec2 a_pos;out vec2 v_pos0;out vec2 v_pos1;void main() {vec2 fractionalPos=a_pos/8192.0;vec2 position=mix(mix(u_coords_top.xy,u_coords_top.zw,fractionalPos.x),mix(u_coords_bottom.xy,u_coords_bottom.zw,fractionalPos.x),fractionalPos.y);gl_Position=projectTile(position,position);v_pos0=((fractionalPos-0.5)/u_buffer_scale)+0.5;
|
||||||
|
#ifdef GLOBE
|
||||||
|
if (a_pos.y <-32767.5) {v_pos0.y=0.0;}if (a_pos.y > 32766.5) {v_pos0.y=1.0;}
|
||||||
|
#endif
|
||||||
|
v_pos1=(v_pos0*u_scale_parent)+u_tl_parent;}`),symbolIcon:J(`uniform sampler2D u_texture;in vec2 v_tex;flat in float v_total_opacity;void main() {fragColor=texture(u_texture,v_tex)*v_total_opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`layout(location=0) in vec4 a_pos_offset;layout(location=1) in vec4 a_data;layout(location=2) in vec4 a_pixeloffset;layout(location=3) in vec3 a_projected_pos;layout(location=4) in float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform highp float u_camera_to_center_distance;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform float u_fade_change;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform vec2 u_texsize;uniform bool u_is_along_line;uniform bool u_is_variable_anchor;uniform vec2 u_translation;uniform float u_pitched_scale;uniform bool u_is_offset;out vec2 v_tex;flat out float v_total_opacity;
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
vec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;float a_size_min=floor(a_size[0]*0.5);vec2 a_pxoffset=a_pixeloffset.xy;vec2 a_minFontScale=a_pixeloffset.zw/256.0;float ele=get_elevation(a_pos);highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size_min,a_size[1],u_size_t)/128.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size_min/128.0;} else {size=u_size;}vec2 translated_a_pos=a_pos+u_translation;vec4 projectedPoint=projectTileWithElevation(translated_a_pos,ele);vec2 fade_opacity=unpack_opacity(a_fade_opacity);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;float visibility=calculate_visibility(projectedPoint);v_total_opacity=opacity*max(0.0,min(visibility,fade_opacity[0]+fade_change));if (v_total_opacity < 0.1){gl_Position=vec4(-2.,-2.,-2.,1.);return;}highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?
|
||||||
|
camera_to_anchor_distance/u_camera_to_center_distance :
|
||||||
|
u_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);if (!u_is_offset) {size*=perspective_ratio;}float fontScale=u_is_text ? size/24.0 : size;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=projectTileWithElevation(translated_a_pos+vec2(1,0),ele);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos;if (u_is_along_line || u_is_variable_anchor) {projected_pos=vec4(a_projected_pos.xy,ele,1.0);} else if (u_pitch_with_map) {projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy+u_translation,ele,1.0);} else {projected_pos=u_label_plane_matrix*projectTileWithElevation(a_projected_pos.xy+u_translation,ele);}float z=float(u_pitch_with_map)*projected_pos.z/projected_pos.w;float projectionScaling=1.0;
|
||||||
|
#ifdef GLOBE
|
||||||
|
if(u_pitch_with_map) {float anchor_pos_tile_y=(u_coord_matrix*vec4(projected_pos.xy/projected_pos.w,z,1.0)).y;projectionScaling=mix(projectionScaling,1.0/circumferenceRatioAtTileY(anchor_pos_tile_y)*u_pitched_scale,u_projection_transition);}
|
||||||
|
#endif
|
||||||
|
vec4 finalPos=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*max(a_minFontScale,fontScale)+a_pxoffset/16.0)*projectionScaling,z,1.0);if(u_pitch_with_map) {finalPos=projectTileWithElevation(finalPos.xy,finalPos.z);}gl_Position=finalPos;v_tex=a_tex/u_texsize;}`),symbolSDF:J(`#define SDF_PX 8.0
|
||||||
|
uniform bool u_is_halo;uniform bool u_is_plain;uniform sampler2D u_texture;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;uniform bool u_is_text;in vec2 v_data0;in vec3 v_data1;
|
||||||
|
#pragma maplibre: define highp vec4 fill_color
|
||||||
|
#pragma maplibre: define highp vec4 halo_color
|
||||||
|
#pragma maplibre: define lowp float halo_width
|
||||||
|
#pragma maplibre: define lowp float halo_blur
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 fill_color
|
||||||
|
#pragma maplibre: initialize highp vec4 halo_color
|
||||||
|
#pragma maplibre: initialize lowp float halo_width
|
||||||
|
#pragma maplibre: initialize lowp float halo_blur
|
||||||
|
float EDGE_GAMMA=0.105/u_device_pixel_ratio;vec2 tex=v_data0.xy;float gamma_scale=v_data1.x;float size=v_data1.y;float total_opacity=v_data1[2];float fontScale=u_is_text ? size/24.0 : size;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float inner_edge=(256.0-64.0)/256.0;lowp float dist=texture(u_texture,tex).a;lowp vec4 color_alpha_out_text,color_alpha_out_halo;if (u_is_plain){highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(inner_edge-gamma_scaled,inner_edge+gamma_scaled,dist);color_alpha_out_text=total_opacity*alpha*fill_color;}if (u_is_halo) {float gamma_halo=(halo_blur*1.19/SDF_PX+EDGE_GAMMA)/(fontScale*u_gamma_scale);float inner_edge_halo=inner_edge+gamma_halo*gamma_scale;highp float gamma_scaled_halo=gamma_halo*gamma_scale;highp float alpha_halo=smoothstep(inner_edge_halo-gamma_scaled_halo,inner_edge_halo+gamma_scaled_halo,dist);highp float halo_edge=(6.0-halo_width/fontScale)/SDF_PX;alpha_halo= min(smoothstep(halo_edge-gamma_scaled_halo,halo_edge+gamma_scaled_halo,dist),1.0-alpha_halo);color_alpha_out_halo=total_opacity*alpha_halo*halo_color;}if (u_is_plain && u_is_halo) {fragColor=color_alpha_out_text+(1.-color_alpha_out_text.a)*color_alpha_out_halo;} else if (u_is_halo){fragColor=color_alpha_out_halo;} else {fragColor=color_alpha_out_text;}
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`layout(location=0) in vec4 a_pos_offset;layout(location=1) in vec4 a_data;layout(location=2) in vec4 a_pixeloffset;layout(location=3) in vec3 a_projected_pos;layout(location=4) in float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform bool u_is_along_line;uniform bool u_is_variable_anchor;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform highp float u_camera_to_center_distance;uniform float u_fade_change;uniform vec2 u_texsize;uniform vec2 u_translation;uniform float u_pitched_scale;uniform bool u_is_offset;out vec2 v_data0;out vec3 v_data1;
|
||||||
|
#pragma maplibre: define highp vec4 fill_color
|
||||||
|
#pragma maplibre: define highp vec4 halo_color
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp float halo_width
|
||||||
|
#pragma maplibre: define lowp float halo_blur
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 fill_color
|
||||||
|
#pragma maplibre: initialize highp vec4 halo_color
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize lowp float halo_width
|
||||||
|
#pragma maplibre: initialize lowp float halo_blur
|
||||||
|
vec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;float a_size_min=floor(a_size[0]*0.5);vec2 a_pxoffset=a_pixeloffset.xy/16.0;vec2 a_minFontScale=a_pixeloffset.zw/256.0;float ele=get_elevation(a_pos);highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size_min,a_size[1],u_size_t)/128.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size_min/128.0;} else {size=u_size;}vec2 translated_a_pos=a_pos+u_translation;vec4 projectedPoint=projectTileWithElevation(translated_a_pos,ele);vec2 fade_opacity=unpack_opacity(a_fade_opacity);float visibility=calculate_visibility(projectedPoint);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;float interpolated_fade_opacity=max(0.0,min(visibility,fade_opacity[0]+fade_change));float total_opacity=opacity*interpolated_fade_opacity;if (total_opacity < 0.1){gl_Position=vec4(-2.,-2.,-2.,1.);return;}highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?
|
||||||
|
camera_to_anchor_distance/u_camera_to_center_distance :
|
||||||
|
u_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);if (!u_is_offset) {size*=perspective_ratio;}float fontScale=u_is_text ? size/24.0 : size;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=projectTileWithElevation(translated_a_pos+vec2(1,0),ele);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos;if (u_is_along_line || u_is_variable_anchor) {projected_pos=vec4(a_projected_pos.xy,ele,1.0);} else if (u_pitch_with_map) {projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy+u_translation,ele,1.0);} else {projected_pos=u_label_plane_matrix*projectTileWithElevation(a_projected_pos.xy+u_translation,ele);}float z=float(u_pitch_with_map)*projected_pos.z/projected_pos.w;float projectionScaling=1.0;
|
||||||
|
#ifdef GLOBE
|
||||||
|
if(u_pitch_with_map) {float anchor_pos_tile_y=(u_coord_matrix*vec4(projected_pos.xy/projected_pos.w,z,1.0)).y;projectionScaling=mix(projectionScaling,1.0/circumferenceRatioAtTileY(anchor_pos_tile_y)*u_pitched_scale,u_projection_transition);}
|
||||||
|
#endif
|
||||||
|
vec4 finalPos=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*max(a_minFontScale,fontScale)+a_pxoffset)*projectionScaling,z,1.0);if(u_pitch_with_map) {finalPos=projectTileWithElevation(finalPos.xy,finalPos.z);}float gamma_scale=finalPos.w;gl_Position=finalPos;v_data0=a_tex/u_texsize;v_data1=vec3(gamma_scale,size,total_opacity);}`),symbolTextAndIcon:J(`#define SDF_PX 8.0
|
||||||
|
#define SDF 1.0
|
||||||
|
#define ICON 0.0
|
||||||
|
uniform bool u_is_halo;uniform bool u_is_text;uniform sampler2D u_texture;uniform sampler2D u_texture_icon;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;in vec4 v_data0;in vec3 v_data1;flat in float v_is_sdf;
|
||||||
|
#pragma maplibre: define highp vec4 fill_color
|
||||||
|
#pragma maplibre: define highp vec4 halo_color
|
||||||
|
#pragma maplibre: define lowp float halo_width
|
||||||
|
#pragma maplibre: define lowp float halo_blur
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 fill_color
|
||||||
|
#pragma maplibre: initialize highp vec4 halo_color
|
||||||
|
#pragma maplibre: initialize lowp float halo_width
|
||||||
|
#pragma maplibre: initialize lowp float halo_blur
|
||||||
|
float total_opacity=v_data1[2];if (v_is_sdf==ICON) {vec2 tex_icon=v_data0.zw;fragColor=texture(u_texture_icon,tex_icon)*total_opacity;
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
return;}vec2 tex=v_data0.xy;float EDGE_GAMMA=0.105/u_device_pixel_ratio;float gamma_scale=v_data1.x;float size=v_data1.y;float fontScale=size/24.0;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float buff=(256.0-64.0)/256.0;lowp float dist=texture(u_texture,tex).a;lowp vec4 color_alpha_out,color_alpha_out_halo;if (u_is_text) {highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(buff-gamma_scaled,buff+gamma_scaled,dist);color_alpha_out=fill_color*(alpha*total_opacity);}if (u_is_halo) {highp float gamma_halo=(halo_blur*1.19/SDF_PX+EDGE_GAMMA)/(fontScale*u_gamma_scale);lowp float buff_halo=(6.0-halo_width/fontScale)/SDF_PX;highp float gamma_scaled_halo=gamma_halo*gamma_scale;highp float alpha_halo=smoothstep(buff_halo-gamma_scaled_halo,buff_halo+gamma_scaled_halo,dist);color_alpha_out_halo=halo_color*(alpha_halo*total_opacity);}if (u_is_text && u_is_halo) {fragColor=color_alpha_out+(1.-color_alpha_out.a)*color_alpha_out_halo;} else if (u_is_halo) {fragColor=color_alpha_out_halo;} else {fragColor=color_alpha_out;}
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor=vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}`,`layout(location=0) in vec4 a_pos_offset;layout(location=1) in vec4 a_data;layout(location=2) in vec3 a_projected_pos;layout(location=3) in float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform highp float u_camera_to_center_distance;uniform float u_fade_change;uniform vec2 u_texsize;uniform vec2 u_texsize_icon;uniform bool u_is_along_line;uniform bool u_is_variable_anchor;uniform vec2 u_translation;uniform float u_pitched_scale;uniform bool u_is_offset;out vec4 v_data0;out vec3 v_data1;flat out float v_is_sdf;
|
||||||
|
#pragma maplibre: define highp vec4 fill_color
|
||||||
|
#pragma maplibre: define highp vec4 halo_color
|
||||||
|
#pragma maplibre: define lowp float opacity
|
||||||
|
#pragma maplibre: define lowp float halo_width
|
||||||
|
#pragma maplibre: define lowp float halo_blur
|
||||||
|
void main() {
|
||||||
|
#pragma maplibre: initialize highp vec4 fill_color
|
||||||
|
#pragma maplibre: initialize highp vec4 halo_color
|
||||||
|
#pragma maplibre: initialize lowp float opacity
|
||||||
|
#pragma maplibre: initialize lowp float halo_width
|
||||||
|
#pragma maplibre: initialize lowp float halo_blur
|
||||||
|
vec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;float a_size_min=floor(a_size[0]*0.5);float is_sdf=a_size[0]-2.0*a_size_min;float ele=get_elevation(a_pos);highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size_min,a_size[1],u_size_t)/128.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size_min/128.0;} else {size=u_size;}vec2 translated_a_pos=a_pos+u_translation;vec4 projectedPoint=projectTileWithElevation(translated_a_pos,ele);vec2 fade_opacity=unpack_opacity(a_fade_opacity);float visibility=calculate_visibility(projectedPoint);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;float interpolated_fade_opacity=max(0.0,min(visibility,fade_opacity[0]+fade_change));float total_opacity=opacity*interpolated_fade_opacity;if (total_opacity < 0.1){gl_Position=vec4(-2.,-2.,-2.,1.);return;}highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?
|
||||||
|
camera_to_anchor_distance/u_camera_to_center_distance :
|
||||||
|
u_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);if (!u_is_offset) {size*=perspective_ratio;}float fontScale=size/24.0;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=projectTileWithElevation(translated_a_pos+vec2(1,0),ele);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos;if (u_is_along_line || u_is_variable_anchor) {projected_pos=vec4(a_projected_pos.xy,ele,1.0);} else if (u_pitch_with_map) {projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy+u_translation,ele,1.0);} else {projected_pos=u_label_plane_matrix*projectTileWithElevation(a_projected_pos.xy+u_translation,ele);}float z=float(u_pitch_with_map)*projected_pos.z/projected_pos.w;float projectionScaling=1.0;
|
||||||
|
#ifdef GLOBE
|
||||||
|
if(u_pitch_with_map && !u_is_along_line) {float anchor_pos_tile_y=(u_coord_matrix*vec4(projected_pos.xy/projected_pos.w,z,1.0)).y;projectionScaling=mix(projectionScaling,1.0/circumferenceRatioAtTileY(anchor_pos_tile_y)*u_pitched_scale,u_projection_transition);}
|
||||||
|
#endif
|
||||||
|
vec4 finalPos=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*fontScale)*projectionScaling,z,1.0);if(u_pitch_with_map) {finalPos=projectTileWithElevation(finalPos.xy,finalPos.z);}float gamma_scale=finalPos.w;gl_Position=finalPos;v_data0.xy=a_tex/u_texsize;v_data0.zw=a_tex/u_texsize_icon;v_data1=vec3(gamma_scale,size,total_opacity);v_is_sdf=is_sdf;}`),terrain:J(`uniform sampler2D u_texture;uniform vec4 u_fog_color;uniform vec4 u_horizon_color;uniform float u_fog_ground_blend;uniform float u_fog_ground_blend_opacity;uniform float u_horizon_fog_blend;uniform bool u_is_globe_mode;in vec2 v_texture_pos;in float v_fog_depth;const float gamma=2.2;vec4 gammaToLinear(vec4 color) {return pow(color,vec4(gamma));}vec4 linearToGamma(vec4 color) {return pow(color,vec4(1.0/gamma));}void main() {vec4 surface_color=texture(u_texture,vec2(v_texture_pos.x,1.0-v_texture_pos.y));if (!u_is_globe_mode && u_fog_ground_blend_opacity > 0.0 && v_fog_depth > u_fog_ground_blend) {vec4 surface_color_linear=gammaToLinear(surface_color);float blend_color=smoothstep(0.0,1.0,max((v_fog_depth-u_horizon_fog_blend)/(1.0-u_horizon_fog_blend),0.0));vec4 fog_horizon_color_linear=mix(gammaToLinear(u_fog_color),gammaToLinear(u_horizon_color),blend_color);float factor_fog=max(v_fog_depth-u_fog_ground_blend,0.0)/(1.0-u_fog_ground_blend);fragColor=linearToGamma(mix(surface_color_linear,fog_horizon_color_linear,pow(factor_fog,2.0)*u_fog_ground_blend_opacity));} else {fragColor=surface_color;}}`,`layout(location=0) in vec3 a_pos3d;uniform mat4 u_fog_matrix;uniform float u_ele_delta;out vec2 v_texture_pos;out float v_fog_depth;void main() {float ele=get_elevation(a_pos3d.xy);float ele_delta=a_pos3d.z==1.0 ? u_ele_delta : 0.0;v_texture_pos=a_pos3d.xy/8192.0;gl_Position=projectTileFor3D(a_pos3d.xy,ele-ele_delta);vec4 pos=u_fog_matrix*vec4(a_pos3d.xy,ele,1.0);v_fog_depth=pos.z/pos.w*0.5+0.5;}`),terrainDepth:J(`in float v_depth;const highp vec4 bitSh=vec4(256.*256.*256.,256.*256.,256.,1.);const highp vec4 bitMsk=vec4(0.,vec3(1./256.0));highp vec4 pack(highp float value) {highp vec4 comp=fract(value*bitSh);comp-=comp.xxyz*bitMsk;return comp;}void main() {fragColor=pack(v_depth);}`,`layout(location=0) in vec3 a_pos3d;uniform float u_ele_delta;out float v_depth;void main() {float ele=get_elevation(a_pos3d.xy);float ele_delta=a_pos3d.z==1.0 ? u_ele_delta : 0.0;gl_Position=projectTileFor3D(a_pos3d.xy,ele-ele_delta);v_depth=gl_Position.z/gl_Position.w;}`),terrainCoords:J(`precision mediump float;uniform sampler2D u_texture;uniform float u_terrain_coords_id;in vec2 v_texture_pos;void main() {vec4 rgba=texture(u_texture,v_texture_pos);fragColor=vec4(rgba.r,rgba.g,rgba.b,u_terrain_coords_id);}`,`layout(location=0) in vec3 a_pos3d;uniform float u_ele_delta;out vec2 v_texture_pos;void main() {float ele=get_elevation(a_pos3d.xy);float ele_delta=a_pos3d.z==1.0 ? u_ele_delta : 0.0;v_texture_pos=a_pos3d.xy/8192.0;gl_Position=projectTileFor3D(a_pos3d.xy,ele-ele_delta);}`),projectionErrorMeasurement:J(`flat in vec4 v_output_error_encoded;void main() {fragColor=v_output_error_encoded;}`,`layout(location=0) in vec2 a_pos;uniform highp float u_input;uniform highp float u_output_expected;flat out vec4 v_output_error_encoded;void main() {float real_output=2.0*atan(exp(PI-(u_input*PI*2.0)))-PI*0.5;float error=real_output-u_output_expected;float abs_error=abs(error)*128.0;v_output_error_encoded.x=min(floor(abs_error*256.0),255.0)/255.0;abs_error-=v_output_error_encoded.x;v_output_error_encoded.y=min(floor(abs_error*65536.0),255.0)/255.0;abs_error-=v_output_error_encoded.x/255.0;v_output_error_encoded.z=min(floor(abs_error*16777216.0),255.0)/255.0;v_output_error_encoded.w=error >=0.0 ? 1.0 : 0.0;gl_Position=vec4(a_pos,0.0,1.0);}`),atmosphere:J(`#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
in vec3 view_direction;uniform vec3 u_sun_pos;uniform vec3 u_globe_position;uniform float u_globe_radius;uniform float u_atmosphere_blend;/**Shader use from https:*Made some change to adapt to MapLibre Globe geometry*/const float PI=3.141592653589793;const int iSteps=5;const int jSteps=3;/*radius of the planet*/const float EARTH_RADIUS=6371e3;/*radius of the atmosphere*/const float ATMOS_RADIUS=6471e3;vec2 rsi(vec3 r0,vec3 rd,float sr) {float a=dot(rd,rd);float b=2.0*dot(rd,r0);float c=dot(r0,r0)-(sr*sr);float d=(b*b)-4.0*a*c;if (d < 0.0) return vec2(1e5,-1e5);return vec2((-b-sqrt(d))/(2.0*a),(-b+sqrt(d))/(2.0*a));}vec4 atmosphere(vec3 r,vec3 r0,vec3 pSun,float iSun,float rPlanet,float rAtmos,vec3 kRlh,float kMie,float shRlh,float shMie,float g) {pSun=normalize(pSun);r=normalize(r);vec2 p=rsi(r0,r,rAtmos);if (p.x > p.y) {return vec4(0.0,0.0,0.0,1.0);}if (p.x < 0.0) {p.x=0.0;}vec3 pos=r0+r*p.x;vec2 p2=rsi(r0,r,rPlanet);if (p2.x <=p2.y && p2.x > 0.0) {p.y=min(p.y,p2.x);}float iStepSize=(p.y-p.x)/float(iSteps);float iTime=p.x+iStepSize*0.5;vec3 totalRlh=vec3(0,0,0);vec3 totalMie=vec3(0,0,0);float iOdRlh=0.0;float iOdMie=0.0;float mu=dot(r,pSun);float mumu=mu*mu;float gg=g*g;float pRlh=3.0/(16.0*PI)*(1.0+mumu);float pMie=3.0/(8.0*PI)*((1.0-gg)*(mumu+1.0))/(pow(1.0+gg-2.0*mu*g,1.5)*(2.0+gg));for (int i=0; i < iSteps; i++) {vec3 iPos=r0+r*iTime;float iHeight=length(iPos)-rPlanet;float odStepRlh=exp(-iHeight/shRlh)*iStepSize;float odStepMie=exp(-iHeight/shMie)*iStepSize;iOdRlh+=odStepRlh;iOdMie+=odStepMie;float jStepSize=rsi(iPos,pSun,rAtmos).y/float(jSteps);float jTime=jStepSize*0.5;float jOdRlh=0.0;float jOdMie=0.0;for (int j=0; j < jSteps; j++) {vec3 jPos=iPos+pSun*jTime;float jHeight=length(jPos)-rPlanet;jOdRlh+=exp(-jHeight/shRlh)*jStepSize;jOdMie+=exp(-jHeight/shMie)*jStepSize;jTime+=jStepSize;}vec3 attn=exp(-(kMie*(iOdMie+jOdMie)+kRlh*(iOdRlh+jOdRlh)));totalRlh+=odStepRlh*attn;totalMie+=odStepMie*attn;iTime+=iStepSize;}float opacity=exp(-(length(kRlh)*length(totalRlh)+kMie*length(totalMie)));vec3 color=iSun*(pRlh*kRlh*totalRlh+pMie*kMie*totalMie);return vec4(color,opacity);}void main() {vec3 scale_camera_pos=-u_globe_position*EARTH_RADIUS/u_globe_radius;vec4 color=atmosphere(normalize(view_direction),scale_camera_pos,u_sun_pos,22.0,EARTH_RADIUS,ATMOS_RADIUS,vec3(5.5e-6,13.0e-6,22.4e-6),21e-6,8e3,1.2e3,0.758
|
||||||
|
);color.rgb=1.0-exp(-1.0*color.rgb);color=pow(color,vec4(1.0/2.2));fragColor=vec4(color.rgb,1.0-color.a)*u_atmosphere_blend;}`,`layout(location=0) in vec2 a_pos;uniform mat4 u_inv_proj_matrix;out vec3 view_direction;void main() {view_direction=(u_inv_proj_matrix*vec4(a_pos,0.0,1.0)).xyz;gl_Position=vec4(a_pos,0.0,1.0);}`),sky:J(`uniform vec4 u_sky_color;uniform vec4 u_horizon_color;uniform vec2 u_horizon;uniform vec2 u_horizon_normal;uniform float u_sky_horizon_blend;uniform float u_sky_blend;void main() {float x=gl_FragCoord.x;float y=gl_FragCoord.y;float blend=(y-u_horizon.y)*u_horizon_normal.y+(x-u_horizon.x)*u_horizon_normal.x;if (blend > 0.0) {if (blend < u_sky_horizon_blend) {fragColor=mix(u_sky_color,u_horizon_color,pow(1.0-blend/u_sky_horizon_blend,2.0));} else {fragColor=u_sky_color;}}fragColor=mix(fragColor,vec4(vec3(0.0),0.0),u_sky_blend);}`,`layout(location=0) in vec2 a_pos;void main() {gl_Position=vec4(a_pos,1.0,1.0);}`)};function J(e,t){let n=/#pragma maplibre: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g,r=t.match(/in ([\w]+) ([\w]+)/g),i=e.match(/uniform ([\w]+) ([\w]+)([\s]*)([\w]*)/g),a=t.match(/uniform ([\w]+) ([\w]+)([\s]*)([\w]*)/g),o=a?a.concat(i):i,s=r?r.length:0,c={};return e=e.replace(n,(e,t,n,r,i)=>(c[i]=!0,t===`define`?`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
in ${n} ${r} ${i};
|
||||||
|
#else
|
||||||
|
uniform ${n} ${r} u_${i};
|
||||||
|
#endif
|
||||||
|
`:`
|
||||||
|
#ifdef HAS_UNIFORM_u_${i}
|
||||||
|
${n} ${r} ${i} = u_${i};
|
||||||
|
#endif
|
||||||
|
`)),t=t.replace(n,(e,t,n,r,i)=>{let a=r===`float`?`vec2`:`vec4`,o=i.match(/color/)?`color`:a;return c[i]?t===`define`?`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
uniform lowp float u_${i}_t;
|
||||||
|
layout(location = ${s++}) in ${n} ${a} a_${i};
|
||||||
|
out ${n} ${r} ${i};
|
||||||
|
#else
|
||||||
|
uniform ${n} ${r} u_${i};
|
||||||
|
#endif
|
||||||
|
`:o===`vec4`?`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
${i} = a_${i};
|
||||||
|
#else
|
||||||
|
${n} ${r} ${i} = u_${i};
|
||||||
|
#endif
|
||||||
|
`:`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
${i} = unpack_mix_${o}(a_${i}, u_${i}_t);
|
||||||
|
#else
|
||||||
|
${n} ${r} ${i} = u_${i};
|
||||||
|
#endif
|
||||||
|
`:t===`define`?`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
uniform lowp float u_${i}_t;
|
||||||
|
layout(location = ${s++}) in ${n} ${a} a_${i};
|
||||||
|
#else
|
||||||
|
uniform ${n} ${r} u_${i};
|
||||||
|
#endif
|
||||||
|
`:o===`vec4`?`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
${n} ${r} ${i} = a_${i};
|
||||||
|
#else
|
||||||
|
${n} ${r} ${i} = u_${i};
|
||||||
|
#endif
|
||||||
|
`:`
|
||||||
|
#ifndef HAS_UNIFORM_u_${i}
|
||||||
|
${n} ${r} ${i} = unpack_mix_${o}(a_${i}, u_${i}_t);
|
||||||
|
#else
|
||||||
|
${n} ${r} ${i} = u_${i};
|
||||||
|
#endif
|
||||||
|
`}),{fragmentSource:e,vertexSource:t,staticAttributes:r,staticUniforms:o}}var us=class{constructor(e,t,n){this.vertexBuffer=e,this.indexBuffer=t,this.segments=n}destroy(){this.vertexBuffer.destroy(),this.indexBuffer.destroy(),this.segments.destroy(),this.vertexBuffer=null,this.indexBuffer=null,this.segments=null}};const ds=yr([{name:`a_pos`,type:`Int16`,components:2}]),fs=`#define PROJECTION_MERCATOR`,ps=`mercator`;var ms=class{constructor(){this._cachedMesh=null}get name(){return`mercator`}get useSubdivision(){return!1}get shaderVariantName(){return ps}get shaderDefine(){return fs}get shaderPreludeCode(){return ls.projectionMercator}get vertexShaderPreludeCode(){return ls.projectionMercator.vertexSource}get subdivisionGranularity(){return Nt.noSubdivision}get useGlobeControls(){return!1}get transitionState(){return 0}get latitudeErrorCorrectionRadians(){return 0}destroy(){}updateGPUdependent(e){}getMeshFromTileID(e,t,n,r,i){if(this._cachedMesh)return this._cachedMesh;let a=new O;a.emplaceBack(0,0),a.emplaceBack(M,0),a.emplaceBack(0,M),a.emplaceBack(M,M);let s=e.createVertexBuffer(a,ds.members),c=o.simpleSegment(0,0,4,2),l=new He;l.emplaceBack(1,0,2),l.emplaceBack(1,2,3);let u=e.createIndexBuffer(l);return this._cachedMesh=new us(s,u,c),this._cachedMesh}recalculate(){}hasTransition(){return!1}setErrorQueryLatitudeDegrees(e){}},hs=class e{constructor(e=0,t=0,n=0,r=0){if(isNaN(e)||e<0||isNaN(t)||t<0||isNaN(n)||n<0||isNaN(r)||r<0)throw Error(`Invalid value for edge-insets, top, bottom, left and right must all be numbers`);this.top=e,this.bottom=t,this.left=n,this.right=r}interpolate(e,t,n){return t.top!=null&&e.top!=null&&(this.top=Yn.number(e.top,t.top,n)),t.bottom!=null&&e.bottom!=null&&(this.bottom=Yn.number(e.bottom,t.bottom,n)),t.left!=null&&e.left!=null&&(this.left=Yn.number(e.left,t.left,n)),t.right!=null&&e.right!=null&&(this.right=Yn.number(e.right,t.right,n)),this}getCenter(e,t){return new z(j((this.left+e-this.right)/2,0,e),j((this.top+t-this.bottom)/2,0,t))}equals(e){return this.top===e.top&&this.bottom===e.bottom&&this.left===e.left&&this.right===e.right}clone(){return new e(this.top,this.bottom,this.left,this.right)}toJSON(){return{top:this.top,bottom:this.bottom,left:this.left,right:this.right}}};function gs(e,t){if(!e.renderWorldCopies||e.lngRange)return;let n=t.lng-e.center.lng;t.lng+=n>180?-360:n<-180?360:0}function _s(e){return Math.max(0,Math.floor(e))}var vs=class{constructor(e,t){this.applyConstrain=(e,t)=>this._constrainOverride===null?this._callbacks.defaultConstrain(e,t):this._constrainOverride(e,t),this._callbacks=e,this._tileSize=512,this._renderWorldCopies=t?.renderWorldCopies===void 0||!!t?.renderWorldCopies,this._minZoom=t?.minZoom||0,this._maxZoom=t?.maxZoom||22,this._minPitch=t?.minPitch===void 0||t?.minPitch===null?0:t?.minPitch,this._maxPitch=t?.maxPitch===void 0||t?.maxPitch===null?60:t?.maxPitch,this._constrainOverride=t?.constrainOverride??null,this.setMaxBounds(),this._width=0,this._height=0,this._center=new B(0,0),this._elevation=0,this._zoom=0,this._tileZoom=_s(this._zoom),this._scale=Se(this._zoom),this._bearingInRadians=0,this._fovInRadians=.6435011087932844,this._pitchInRadians=0,this._rollInRadians=0,this._unmodified=!0,this._edgeInsets=new hs,this._minElevationForCurrentTile=0,this._autoCalculateNearFarZ=!0}apply(e,t,n){this._constrainOverride=e.constrainOverride,this._latRange=e.latRange,this._lngRange=e.lngRange,this._width=e.width,this._height=e.height,this._center=e.center,this._elevation=e.elevation,this._minElevationForCurrentTile=e.minElevationForCurrentTile,this._zoom=e.zoom,this._tileZoom=_s(this._zoom),this._scale=Se(this._zoom),this._bearingInRadians=e.bearingInRadians,this._fovInRadians=e.fovInRadians,this._pitchInRadians=e.pitchInRadians,this._rollInRadians=e.rollInRadians,this._unmodified=e.unmodified,this._edgeInsets=new hs(e.padding.top,e.padding.bottom,e.padding.left,e.padding.right),this._minZoom=e.minZoom,this._maxZoom=e.maxZoom,this._minPitch=e.minPitch,this._maxPitch=e.maxPitch,this._renderWorldCopies=e.renderWorldCopies,this._cameraToCenterDistance=e.cameraToCenterDistance,this._nearZ=e.nearZ,this._farZ=e.farZ,this._autoCalculateNearFarZ=!n&&e.autoCalculateNearFarZ,t&&this.constrainInternal(),this._calcMatrices()}get pixelsToClipSpaceMatrix(){return this._pixelsToClipSpaceMatrix}get clipSpaceToPixelsMatrix(){return this._clipSpaceToPixelsMatrix}get minElevationForCurrentTile(){return this._minElevationForCurrentTile}setMinElevationForCurrentTile(e){this._minElevationForCurrentTile=e}get tileSize(){return this._tileSize}get tileZoom(){return this._tileZoom}get scale(){return this._scale}get width(){return this._width}get height(){return this._height}get bearingInRadians(){return this._bearingInRadians}get lngRange(){return this._lngRange}get latRange(){return this._latRange}get pixelsToGLUnits(){return this._pixelsToGLUnits}get minZoom(){return this._minZoom}setMinZoom(e){this._minZoom!==e&&(this._minZoom=e,this.setZoom(this.applyConstrain(this
Line truncated
|
||||||
|
`),x=y.concat(ls.prelude.vertexSource,o.vertexSource,t.vertexSource).join(`
|
||||||
|
`),S=l.createShader(l.FRAGMENT_SHADER);if(l.isContextLost()){this.failedToCreate=!0;return}if(l.shaderSource(S,b),l.compileShader(S),!l.getShaderParameter(S,l.COMPILE_STATUS))throw Error(`Could not compile fragment shader: ${l.getShaderInfoLog(S)}`);l.attachShader(this.program,S);let C=l.createShader(l.VERTEX_SHADER);if(l.isContextLost()){this.failedToCreate=!0;return}if(l.shaderSource(C,x),l.compileShader(C),!l.getShaderParameter(C,l.COMPILE_STATUS))throw Error(`Could not compile vertex shader: ${l.getShaderInfoLog(C)}`);l.attachShader(this.program,C),this.attributes={};let w={};this.numAttributes=f.length;for(let e=0;e<this.numAttributes;e++)f[e]&&(this.attributes[f[e]]=e);l.linkProgram(this.program);for(let e in this.attributes){let t=l.getAttribLocation(this.program,e);t>=0&&(this.attributes[e]=t)}if(!l.getProgramParameter(this.program,l.LINK_STATUS))throw Error(`Program failed to link: ${l.getProgramInfoLog(this.program)}`);l.deleteShader(C),l.deleteShader(S);for(let e of v)if(e&&!w[e]){let t=l.getUniformLocation(this.program,e);t&&(w[e]=t)}this.fixedUniforms=r(e,w),this.terrainUniforms=Cc(e,w),this.projectionUniforms=Ac(e,w),this.binderUniforms=n?n.getUniforms(e,w):[]}draw(e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h,g,_,v){let y=e.gl;if(this.failedToCreate)return;if(e.program.set(this.program),e.setDepthMode(n),e.setStencilMode(r),e.setColorMode(i),e.setCullFace(a),s){e.activeTexture.set(y.TEXTURE2),y.bindTexture(y.TEXTURE_2D,s.depthTexture),e.activeTexture.set(y.TEXTURE3),y.bindTexture(y.TEXTURE_2D,s.texture);for(let e in this.terrainUniforms)this.terrainUniforms[e].set(s[e])}if(c)for(let e in c){let t=jc[e];this.projectionUniforms[t].set(c[e])}if(o)for(let e in this.fixedUniforms)this.fixedUniforms[e].set(o[e]);h&&h.setUniforms(e,this.binderUniforms,p,{zoom:m});let b=0;switch(t){case y.LINES:b=2;break;case y.TRIANGLES:b=3;break;case y.LINE_STRIP:b=1;break}for(let n of f.get())n.vaos||={},n.vaos[l]||=new Sc,n.vaos[l].bind(e,this,u,h?h.getPaintVertexBuffers():[],d,n.vertexOffset,g,_,v),y.drawElements(t,n.primitiveLength*b,y.UNSIGNED_SHORT,n.primitiveOffset*b*2)}};function Pc(e,t,n){let r=1/Ee(n,1,t.transform.tileZoom),i=2**n.tileID.overscaledZ,a=n.tileSize*2**t.transform.tileZoom/i,o=a*(n.tileID.canonical.x+n.tileID.wrap*i),s=a*n.tileID.canonical.y;return{u_image:0,u_texsize:n.imageAtlasTexture.size,u_scale:[r,e.fromScale,e.toScale],u_fade:e.t,u_pixel_coord_upper:[o>>16,s>>16],u_pixel_coord_lower:[o&65535,s&65535]}}function Fc(e,t,n,r){let i=n.imageManager.getPattern(e.from.toString()),a=n.imageManager.getPattern(e.to.toString()),{width:o,height:s}=n.imageManager.getPixelSize(),c=2**r.tileID.overscaledZ,l=r.tileSize*2**n.transform.tileZoom/c,u=l*(r.tileID.canonical.x+r.tileID.wrap*c),d=l*r.tileID.canonical.y;return{u_image:0,u_pattern_tl_a:i.tl,u_pattern_br_a:i.br,u_pattern_tl_b:a.tl,u_pattern_br_b:a.br,u_texsize:[o,s],u_mix:t.t,u_pattern_size_a:i.displaySize,u_pattern_size_b:a.displaySize,u_scale_a:t.fromScale,u_scale_b:t.toScale,u_tile_units_to_pixels:1/Ee(r,1,n.transform.tileZoom),u_pixel_coord_upper:[u>>16,d>>16],u_pixel_coord_lower:[u&65535,d&65535]}}const Ic=(e,t)=>({u_lightpos:new or(e,t.u_lightpos),u_lightpos_globe:new or(e,t.u_lightpos_globe),u_lightintensity:new H(e,t.u_lightintensity),u_lightcolor:new or(e,t.u_lightcolor),u_vertical_gradient:new H(e,t.u_vertical_gradient),u_opacity:new H(e,t.u_opacity),u_fill_translate:new h(e,t.u_fill_translate)}),Lc=(e,t)=>({u_lightpos:new or(e,t.u_lightpos),u_lightpos_globe:new or(e,t.u_lightpos_globe),u_lightintensity:new H(e,t.u_lightintensity),u_lightcolor:new or(e,t.u_lightcolor),u_vertical_gradient:new H(e,t.u_vertical_gradient),u_height_factor:new H(e,t.u_height_factor),u_opacity:new H(e,t.u_opacity),u_fill_translate:new h(e,t.u_fill_translate),u_image:new P(e,t.u_image),u_texsize:new h(e,t.u_texsize),u_pixel_coord_upper:new h(e,t.u_pixel_coord_upper),u_pixel_coord_lower:new h(e,t.u_pixel_coord_lower),u_scale:new or(e,t.u_scale),u_fade:new H(e,t.u_fade)}),Rc=(e,t,n,r)=>{let i=e.style.light,a=i.getCartesianPosition(),o=S();i.properties.get(`anchor`)===`viewport`&&_(o,e.transform.bearingInRadians),Cn(a,a,o);let s=e.transform.transformLightDirection(a),c=i.properties.get(`color`);return{u_lightpos:a,u_lightpos_globe:s,u_lightintensity:i.properties.get(`intensity`),u_lightcolor:[c.r,c.g,c.b],u_vertical_gradient:+t,u_opacity:n,u_fill_translate:r}},zc=(e,t,n,r,i,a,o)=>L(Rc(e,t,n,r),Pc(a,e,o),{u_height_factor:-(2**i.overscaledZ)/o.tileSize/8}),Bc=(e,t)=>({u_fill_translate:new h(e,t.u_fill_translate)}),Vc=(e,t)=>({u_image:new P(e,t.u_image),u_texsize:new h(e,t.u_texsize),u_pixel_coord_upper:new h(e,t.u_pixel_coord_upper),u_pixel_coord_lower:new h(e,t.u_pixel_coord_lower),u_scale:new or(e,t.u_scale),u_fade:new H(e,t.u_fade),u_fill_translate:new h(e,t.u_fill_translate)}),Hc=(e,t)=>({u_world:new h(e,t.u_world),u_fill_translate:new h(e,t.u_fill_translate)}),Uc=(e,t)=>({u_world:new h(e,t.u_world),u_image:new P(e,t.u_image),u_texsize:new h(e,t.u_texsize),u_pixel_coord_uppe
Line truncated
|
||||||
|
//# sourceMappingURL=maplibre-gl.mjs.map
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
"use strict";var pmtiles=(()=>{var k=Object.defineProperty;var Je=Object.getOwnPropertyDescriptor;var Ye=Object.getOwnPropertyNames;var Qe=Object.prototype.hasOwnProperty;var Ce=Math.pow;var f=(r,e)=>k(r,"name",{value:e,configurable:!0});var Xe=(r,e)=>{for(var t in e)k(r,t,{get:e[t],enumerable:!0})},_e=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ye(e))!Qe.call(r,i)&&i!==t&&k(r,i,{get:()=>e[i],enumerable:!(n=Je(e,i))||n.enumerable});return r};var et=r=>_e(k({},"__esModule",{value:!0}),r);var m=(r,e,t)=>new Promise((n,i)=>{var a=l=>{try{s(t.next(l))}catch(c){i(c)}},o=l=>{try{s(t.throw(l))}catch(c){i(c)}},s=l=>l.done?n(l.value):Promise.resolve(l.value).then(a,o);s((t=t.apply(r,e)).next())});var Dt={};Xe(Dt,{Compression:()=>Oe,EtagMismatch:()=>B,FetchSource:()=>V,FileSource:()=>se,PMTiles:()=>S,Protocol:()=>ne,ResolvedValueCache:()=>oe,SharedPromiseCache:()=>K,TileType:()=>ae,bytesToHeader:()=>$e,findTile:()=>Fe,getUint64:()=>b,leafletRasterLayer:()=>wt,readVarint:()=>R,tileIdToZxy:()=>At,tileTypeExt:()=>Ze,zxyToTileId:()=>Ie});var w=Uint8Array,E=Uint16Array,tt=Int32Array,Me=new w([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),Ue=new w([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),rt=new w([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ee=f(function(r,e){for(var t=new E(31),n=0;n<31;++n)t[n]=e+=1<<r[n-1];for(var i=new tt(t[30]),n=1;n<30;++n)for(var a=t[n];a<t[n+1];++a)i[a]=a-t[n]<<5|n;return{b:t,r:i}},"freb"),Le=Ee(Me,2),Se=Le.b,nt=Le.r;Se[28]=258,nt[258]=28;var Pe=Ee(Ue,0),it=Pe.b,Mt=Pe.r,te=new E(32768);for(g=0;g<32768;++g)T=(g&43690)>>1|(g&21845)<<1,T=(T&52428)>>2|(T&13107)<<2,T=(T&61680)>>4|(T&3855)<<4,te[g]=((T&65280)>>8|(T&255)<<8)>>1;var T,g,Z=f(function(r,e,t){for(var n=r.length,i=0,a=new E(e);i<n;++i)r[i]&&++a[r[i]-1];var o=new E(e);for(i=1;i<e;++i)o[i]=o[i-1]+a[i-1]<<1;var s;if(t){s=new E(1<<e);var l=15-e;for(i=0;i<n;++i)if(r[i])for(var c=i<<4|r[i],h=e-r[i],u=o[r[i]-1]++<<h,v=u|(1<<h)-1;u<=v;++u)s[te[u]>>l]=c}else for(s=new E(n),i=0;i<n;++i)r[i]&&(s[i]=te[o[r[i]-1]++]>>15-r[i]);return s},"hMap"),F=new w(288);for(g=0;g<144;++g)F[g]=8;var g;for(g=144;g<256;++g)F[g]=9;var g;for(g=256;g<280;++g)F[g]=7;var g;for(g=280;g<288;++g)F[g]=8;var g,Re=new w(32);for(g=0;g<32;++g)Re[g]=5;var g;var at=Z(F,9,1);var st=Z(Re,5,1),_=f(function(r){for(var e=r[0],t=1;t<r.length;++t)r[t]>e&&(e=r[t]);return e},"max"),z=f(function(r,e,t){var n=e/8|0;return(r[n]|r[n+1]<<8)>>(e&7)&t},"bits"),ee=f(function(r,e){var t=e/8|0;return(r[t]|r[t+1]<<8|r[t+2]<<16)>>(e&7)},"bits16"),ot=f(function(r){return(r+7)/8|0},"shft"),ut=f(function(r,e,t){return(e==null||e<0)&&(e=0),(t==null||t>r.length)&&(t=r.length),new w(r.subarray(e,t))},"slc");var ft=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],y=f(function(r,e,t){var n=new Error(e||ft[r]);if(n.code=r,Error.captureStackTrace&&Error.captureStackTrace(n,y),!t)throw n;return n},"err"),re=f(function(r,e,t,n){var i=r.length,a=n?n.length:0;if(!i||e.f&&!e.l)return t||new w(0);var o=!t,s=o||e.i!=2,l=e.i;o&&(t=new w(i*3));var c=f(function(Ae){var Te=t.length;if(Ae>Te){var De=new w(Math.max(Te*2,Ae));De.set(t),t=De}},"cbuf"),h=e.f||0,u=e.p||0,v=e.b||0,d=e.l,p=e.d,C=e.m,H=e.n,G=i*8;do{if(!d){h=z(r,u,1);var q=z(r,u+1,3);if(u+=3,q)if(q==1)d=at,p=st,C=9,H=5;else if(q==2){var N=z(r,u,31)+257,pe=z(r,u+10,15)+4,me=N+z(r,u+5,31)+1;u+=14;for(var I=new w(me),J=new w(19),x=0;x<pe;++x)J[rt[x]]=z(r,u+x*3,7);u+=pe*3;for(var de=_(J),Ge=(1<<de)-1,qe=Z(J,de,1),x=0;x<me;){var ye=qe[z(r,u,Ge)];u+=ye&15;var A=ye>>4;if(A<16)I[x++]=A;else{var M=0,$=0;for(A==16?($=3+z(r,u,3),u+=2,M=I[x-1]):A==17?($=3+z(r,u,7),u+=3):A==18&&($=11+z(r,u,127),u+=7);$--;)I[x++]=M}}var we=I.subarray(0,N),D=I.subarray(N);C=_(we),H=_(D),d=Z(we,C,1),p=Z(D,H,1)}else y(1);else{var A=ot(u)+4,j=r[A-4]|r[A-3]<<8,W=A+j;if(W>i){l&&y(0);break}s&&c(v+j),t.set(r.subarray(A,W),v),e.b=v+=j,e.p=u=W*8,e.f=h;continue}if(u>G){l&&y(0);break}}s&&c(v+131072);for(var je=(1<<C)-1,We=(1<<H)-1,Y=u;;Y=u){var M=d[ee(r,u)&je],U=M>>4;if(u+=M&15,u>G){l&&y(0);break}if(M||y(2),U<256)t[v++]=U;else if(U==256){Y=u,d=null;break}else{var xe=U-254;if(U>264){var x=U-257,O=Me[x];xe=z(r,u,(1<<O)-1)+Se[x],u+=O}var Q=p[ee(r,u)&We],X=Q>>4;Q||y(3),u+=Q&15;var D=it[X];if(X>3){var O=Ue[X];D+=ee(r,u)&(1<<O)-1,u+=O}if(u>G){l&&y(0);break}s&&c(v+131072);var be=v+xe;if(v<D){var ze=a-D,Ne=Math.min(D,be);for(ze+v<0&&y(3);v<Ne;++v)t[v]=n[ze+v]}for(;v<be;++v)t[v]=t[v-D]}}e.l=d,e.p=Y,e.b=v,e.f=h,d&&(h=1,e.m=C,e.d=p,e.n=H)}while(!h);return v!=t.length&&o?ut(t,0,v):t.subarray(0,v)},"inflt");var lt=new w(0);var ht=f(function(r){(r[0]!=31||r[1]!=139||r[2]!=8)&&y(6,"invalid gzip data");var e=r[3],t=10;e&4&&(t+=(r[10]|r[11]<<8)+2);for(var n=(e>>3&1)+(e>>4&1);n>0;n-=!r[t++]);return t+(e&2)},"gzs"),ct=f(function(rLine truncated
|
||||||
|
//# sourceMappingURL=pmtiles.js.map
|
||||||