diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d0411c22..daa9f99c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,9 +95,9 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md rigidly by the largest clearance deficit over a 3×3 grid of support points against the ground under each (the ground at the mount where nothing finer is known), and the client honours pack ranges instead of inflating them to 220 m. - `src/data/local_data/cctv_ground_heights/` ships Google 3D Tiles ground heights under - every camera's mount and plane footprint (3,445 of 3,446 cameras), produced by - `scripts/precompute-cctv-heights.mjs`; cameras with shipped heights are placed + `src/data/local_data/cctv_ground_heights/` ships precomputed ground heights under + every camera's mount and plane footprint (3,445 of 3,446 cameras), aligned to work + with Google Photorealistic 3D Tiles; cameras with shipped heights are placed with zero runtime sampling, and the rest resolve the ground under their plane from the Re:Earth DEM on activation. The footprint lift is capped at 60 m above the mount-based lift so a tower under a far edge cannot launch the plane. diff --git a/DATA_SOURCES.md b/DATA_SOURCES.md index 297978e13..7e6cf5afa 100644 --- a/DATA_SOURCES.md +++ b/DATA_SOURCES.md @@ -13,39 +13,39 @@ How to read this: ## Live sources (fetched at runtime — not stored in this repo) -| Source | Used for | License / terms | Attribution | -|--------|----------|-----------------|-------------| -| **Google Map Tiles API** (Photorealistic 3D Tiles) + Places/Geocoding | The 3D globe, voice scene context, and on-demand nearby installation search | Google Maps Platform ToS (proprietary, your own key + billing) | "Google" / "Google Maps" logo — **shown in-app**, required | -| **OpenSky Network** | Primary worldwide live-flight snapshot | Non-commercial research/education license | Schäfer et al., *"Bringing Up OpenSky"*, IPSN 2014 + opensky-network.org | -| **adsb.lol point API** | Bounded live-flight fallback when OpenSky has no usable snapshot | ODbL 1.0 | adsb.lol contributors; `api.adsb.lol/v2/lat/{lat}/lon/{lon}/dist/{radius}` | -| **adsb.lol** | Military flights + aircraft traces | ODbL 1.0 | "adsb.lol" (ODbL) | -| **AISStream.io** | Live vessels (AIS) | Free, beta, no formal ToS; AIS is a public broadcast | "AISStream.io" (courtesy) | -| **CelesTrak** | Satellite TLEs (SGP4) | US-government-origin data, no license; citation requested | "CelesTrak (celestrak.org), Dr. T.S. Kelso" | -| **The Space Devs — Launch Library 2 v2.3** | Recent launch, payload, stage, and recovery metadata for Space Missions (30d) | [The Space Devs terms of use](https://github.com/TheSpaceDevs/Tutorials/blob/main/faqs/faq_TSD.md#terms-of-use): data may be used and shared in any form; avoid forwarding it without added value; attribution is encouraged (not mandatory). [Official API limits](https://ll.thespacedevs.com/docs/): 15 unauthenticated calls/hour; optional token | "Launch Library 2 — The Space Devs" (courtesy attribution) | -| **Esri World Imagery** (ArcGIS Online tile service) | The keyless satellite basemap — the default landing when no Google/ion credential is configured, and the "Esri Satellite" map stack | [Esri Master Agreement](https://www.esri.com/en-us/legal/terms/full-master-agreement): the public World Imagery service is usable in public-facing apps with attribution; no key is required for this classic endpoint, but Esri governs and can change access — an app at scale should review current ArcGIS Location Platform terms | "Powered by Esri — Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community" (provider carries the service's own credit line) | -| **USGS** | Earthquakes | U.S. public domain | "Data courtesy of the U.S. Geological Survey" | -| **OpenStreetMap (Overpass API)** | Road geometry for traffic | ODbL 1.0 | "© OpenStreetMap contributors" | -| **TomTom Traffic API** (flow vector tiles) | Live congestion coloring for the traffic layer (optional, BYOK) | [TomTom for Developers terms](https://developer.tomtom.com) (proprietary, your own key; free tier currently 200K tile requests/month — see [current pricing](https://docs.tomtom.com/pricing/)) | "Traffic flow data © TomTom" — registered when live mode activates | -| **OpenStreetMap (Overpass API)** | Viewport-bounded mapped installation context for Global Context | ODbL 1.0 | "© OpenStreetMap contributors" (incomplete mapped context) | -| **Photon** (komoot) | Keyless place search — the fallback when no Google Maps key is configured, or when Google declines the Geocoding request | Service: free public instance, [fair use](https://photon.komoot.io) (no bulk/heavy use); underlying data: **ODbL 1.0** | "Photon (komoot)" + "© OpenStreetMap contributors" | -| **OpenStreetMap (Nominatim)** | Reverse-geocoded place label in the cockpit Local Info page | ODbL 1.0 + Nominatim usage policy | "© OpenStreetMap contributors" | -| **Open-Meteo** | Current weather in the cockpit Local Info page and cockpit-local dynamic atmospheric effects | [CC BY 4.0 data licence and adjacent-link attribution requirement](https://open-meteo.com/en/licence) | Linked "Weather data by Open-Meteo.com" beside the displayed local data | -| **Google News RSS** | Primary locality-matched headlines in the cockpit Regional News page | [Google News Terms of Service](https://www.google.com/intl/en_us/terms_google_news.html) restrict use to personal, noncommercial use; linked articles remain third-party publisher content and retain publisher terms | "Google News RSS" plus each article's linked publisher/domain | -| **GDELT Project DOC 2.0** | Fail-soft fallback for location-matched cockpit headlines | [GDELT Terms of Use](https://www.gdeltproject.org/about.html#termsofuse): unrestricted academic/commercial/governmental dataset use, with citation and link required; linked articles retain publisher terms | "GDELT Project" plus each article's linked publisher/domain | -| **City of Austin Open Data** | CCTV camera catalog + frames | City of Austin Open Data Terms of Use | "City of Austin, TX — data.austintexas.gov" | -| **TxDOT ITS (its.txdot.gov)** | CCTV camera catalogs + frames, Texas districts | Public TxDOT traffic camera data | "Texas Department of Transportation" (courtesy) | -| **City of Tallinn (ristmikud.tallinn.ee)** | CCTV camera catalog + frames, Tallinn intersections | Public City of Tallinn traffic camera data | "City of Tallinn — ristmikud.tallinn.ee" (courtesy) | -| **Transpordiamet / Tarktee** | CCTV camera catalog + frames, Estonia road-weather cameras | Public Transpordiamet / Tarktee road camera data | "Transpordiamet / Tarktee — tarktee.transpordiamet.ee" (courtesy) | -| **Stadt Warendorf webcam** | Webcam frames, Marktplatz / Historisches Rathaus (`config/cctv_sources.warendorf.json`) | Public municipal webcam data | "Stadt Warendorf — webcam.warendorf.de" (courtesy); mount and heading derived from OSM geometry, "© OpenStreetMap contributors" (ODbL) | -| **Live Traffic NSW (Transport for NSW)** | CCTV camera catalog + frames, New South Wales | [CC BY 4.0](https://opendata.transport.nsw.gov.au/) — attribution REQUIRED | "Live Traffic NSW — Transport for NSW" | -| **Caltrans (cwwp2.dot.ca.gov)** | CCTV camera catalogs + frames, California districts | Public Caltrans traffic camera data | "Caltrans — cwwp2.dot.ca.gov" (courtesy) | -| **TfL Open Data (JamCams)** | CCTV camera catalog + frames, London | [TfL Open Data terms](https://tfl.gov.uk/info-for/open-data-users/) — attribution REQUIRED | "Powered by TfL Open Data. Contains OS data © Crown copyright and database rights" | -| **Ontario 511** | CCTV camera catalog + frames, Ontario highways including Kitchener-area routes | [Open Government Licence – Ontario](https://www.ontario.ca/page/open-government-licence-ontario) | "Ontario 511" plus Open Government Licence - Ontario | -| **Fintraffic / Digitraffic (weathercams)** | CCTV camera catalog + frames, Finland | [CC BY 4.0](https://www.digitraffic.fi/en/terms-of-service/) — attribution REQUIRED | "Fintraffic / digitraffic.fi, license CC BY 4.0" | -| **DriveBC** (Government of British Columbia) | CCTV camera catalog + frames, British Columbia highways | [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/open-data/open-government-licence-bc) — attribution REQUIRED | "DriveBC. Contains information licensed under the Open Government Licence – British Columbia" | -| **GBFS (Lyft / BCycle)** | Bikeshare availability | Per-feed (attribution-only) | Credit the operator (e.g. Austin BCycle) + its `license_url` | -| **Radio Browser** | Geolocated internet-radio station directory and station-level tags | Public-domain directory data under PDDL 1.0; individual broadcaster stream terms apply | "Radio Browser" plus a link to the selected broadcaster | -| **Re:Earth Terrain** (Mapterhorn) | Terrain (keyless globe stacks — OSM etc. — + `/api/terrain/heights` ellipsoidal-height lookups) | Terrain mesh: CC BY 4.0; geoid: EGM2008 (NGA, public domain) | "Terrain (keyless globe stacks): Re:Earth Terrain / Mapterhorn (CC BY 4.0) / EGM2008 (NGA)" | +| Source | Used for | License / terms | Attribution | +| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| **Google Map Tiles API** (Photorealistic 3D Tiles) + Places/Geocoding | The 3D globe, voice scene context, and on-demand nearby installation search | Google Maps Platform ToS (proprietary, your own key + billing) | "Google" / "Google Maps" logo — **shown in-app**, required | +| **OpenSky Network** | Primary worldwide live-flight snapshot | Non-commercial research/education license | Schäfer et al., _"Bringing Up OpenSky"_, IPSN 2014 + opensky-network.org | +| **adsb.lol point API** | Bounded live-flight fallback when OpenSky has no usable snapshot | ODbL 1.0 | adsb.lol contributors; `api.adsb.lol/v2/lat/{lat}/lon/{lon}/dist/{radius}` | +| **adsb.lol** | Military flights + aircraft traces | ODbL 1.0 | "adsb.lol" (ODbL) | +| **AISStream.io** | Live vessels (AIS) | Free, beta, no formal ToS; AIS is a public broadcast | "AISStream.io" (courtesy) | +| **CelesTrak** | Satellite TLEs (SGP4) | US-government-origin data, no license; citation requested | "CelesTrak (celestrak.org), Dr. T.S. Kelso" | +| **The Space Devs — Launch Library 2 v2.3** | Recent launch, payload, stage, and recovery metadata for Space Missions (30d) | [The Space Devs terms of use](https://github.com/TheSpaceDevs/Tutorials/blob/main/faqs/faq_TSD.md#terms-of-use): data may be used and shared in any form; avoid forwarding it without added value; attribution is encouraged (not mandatory). [Official API limits](https://ll.thespacedevs.com/docs/): 15 unauthenticated calls/hour; optional token | "Launch Library 2 — The Space Devs" (courtesy attribution) | +| **Esri World Imagery** (ArcGIS Online tile service) | The keyless satellite basemap — the default landing when no Google/ion credential is configured, and the "Esri Satellite" map stack | [Esri Master Agreement](https://www.esri.com/en-us/legal/terms/full-master-agreement): the public World Imagery service is usable in public-facing apps with attribution; no key is required for this classic endpoint, but Esri governs and can change access — an app at scale should review current ArcGIS Location Platform terms | "Powered by Esri — Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community" (provider carries the service's own credit line) | +| **USGS** | Earthquakes | U.S. public domain | "Data courtesy of the U.S. Geological Survey" | +| **OpenStreetMap (Overpass API)** | Road geometry for traffic | ODbL 1.0 | "© OpenStreetMap contributors" | +| **TomTom Traffic API** (flow vector tiles) | Live congestion coloring for the traffic layer (optional, BYOK) | [TomTom for Developers terms](https://developer.tomtom.com) (proprietary, your own key; free tier currently 200K tile requests/month — see [current pricing](https://docs.tomtom.com/pricing/)) | "Traffic flow data © TomTom" — registered when live mode activates | +| **OpenStreetMap (Overpass API)** | Viewport-bounded mapped installation context for Global Context | ODbL 1.0 | "© OpenStreetMap contributors" (incomplete mapped context) | +| **Photon** (komoot) | Keyless place search — the fallback when no Google Maps key is configured, or when Google declines the Geocoding request | Service: free public instance, [fair use](https://photon.komoot.io) (no bulk/heavy use); underlying data: **ODbL 1.0** | "Photon (komoot)" + "© OpenStreetMap contributors" | +| **OpenStreetMap (Nominatim)** | Reverse-geocoded place label in the cockpit Local Info page | ODbL 1.0 + Nominatim usage policy | "© OpenStreetMap contributors" | +| **Open-Meteo** | Current weather in the cockpit Local Info page and cockpit-local dynamic atmospheric effects | [CC BY 4.0 data licence and adjacent-link attribution requirement](https://open-meteo.com/en/licence) | Linked "Weather data by Open-Meteo.com" beside the displayed local data | +| **Google News RSS** | Primary locality-matched headlines in the cockpit Regional News page | [Google News Terms of Service](https://www.google.com/intl/en_us/terms_google_news.html) restrict use to personal, noncommercial use; linked articles remain third-party publisher content and retain publisher terms | "Google News RSS" plus each article's linked publisher/domain | +| **GDELT Project DOC 2.0** | Fail-soft fallback for location-matched cockpit headlines | [GDELT Terms of Use](https://www.gdeltproject.org/about.html#termsofuse): unrestricted academic/commercial/governmental dataset use, with citation and link required; linked articles retain publisher terms | "GDELT Project" plus each article's linked publisher/domain | +| **City of Austin Open Data** | CCTV camera catalog + frames | City of Austin Open Data Terms of Use | "City of Austin, TX — data.austintexas.gov" | +| **TxDOT ITS (its.txdot.gov)** | CCTV camera catalogs + frames, Texas districts | Public TxDOT traffic camera data | "Texas Department of Transportation" (courtesy) | +| **City of Tallinn (ristmikud.tallinn.ee)** | CCTV camera catalog + frames, Tallinn intersections | Public City of Tallinn traffic camera data | "City of Tallinn — ristmikud.tallinn.ee" (courtesy) | +| **Transpordiamet / Tarktee** | CCTV camera catalog + frames, Estonia road-weather cameras | Public Transpordiamet / Tarktee road camera data | "Transpordiamet / Tarktee — tarktee.transpordiamet.ee" (courtesy) | +| **Stadt Warendorf webcam** | Webcam frames, Marktplatz / Historisches Rathaus (`config/cctv_sources.warendorf.json`) | Public municipal webcam data | "Stadt Warendorf — webcam.warendorf.de" (courtesy); mount and heading derived from OSM geometry, "© OpenStreetMap contributors" (ODbL) | +| **Live Traffic NSW (Transport for NSW)** | CCTV camera catalog + frames, New South Wales | [CC BY 4.0](https://opendata.transport.nsw.gov.au/) — attribution REQUIRED | "Live Traffic NSW — Transport for NSW" | +| **Caltrans (cwwp2.dot.ca.gov)** | CCTV camera catalogs + frames, California districts | Public Caltrans traffic camera data | "Caltrans — cwwp2.dot.ca.gov" (courtesy) | +| **TfL Open Data (JamCams)** | CCTV camera catalog + frames, London | [TfL Open Data terms](https://tfl.gov.uk/info-for/open-data-users/) — attribution REQUIRED | "Powered by TfL Open Data. Contains OS data © Crown copyright and database rights" | +| **Ontario 511** | CCTV camera catalog + frames, Ontario highways including Kitchener-area routes | [Open Government Licence – Ontario](https://www.ontario.ca/page/open-government-licence-ontario) | "Ontario 511" plus Open Government Licence - Ontario | +| **Fintraffic / Digitraffic (weathercams)** | CCTV camera catalog + frames, Finland | [CC BY 4.0](https://www.digitraffic.fi/en/terms-of-service/) — attribution REQUIRED | "Fintraffic / digitraffic.fi, license CC BY 4.0" | +| **DriveBC** (Government of British Columbia) | CCTV camera catalog + frames, British Columbia highways | [Open Government Licence – British Columbia](https://www2.gov.bc.ca/gov/content/data/open-data/open-government-licence-bc) — attribution REQUIRED | "DriveBC. Contains information licensed under the Open Government Licence – British Columbia" | +| **GBFS (Lyft / BCycle)** | Bikeshare availability | Per-feed (attribution-only) | Credit the operator (e.g. Austin BCycle) + its `license_url` | +| **Radio Browser** | Geolocated internet-radio station directory and station-level tags | Public-domain directory data under PDDL 1.0; individual broadcaster stream terms apply | "Radio Browser" plus a link to the selected broadcaster | +| **Re:Earth Terrain** (Mapterhorn) | Terrain (keyless globe stacks — OSM etc. — + `/api/terrain/heights` ellipsoidal-height lookups) | Terrain mesh: CC BY 4.0; geoid: EGM2008 (NGA, public domain) | "Terrain (keyless globe stacks): Re:Earth Terrain / Mapterhorn (CC BY 4.0) / EGM2008 (NGA)" | ### Notes on the live sources @@ -75,18 +75,14 @@ How to read this: Static datasets shipped in the repo for an out-of-the-box experience. **None are MIT** — each keeps its own license (see the carve-out in [LICENSE](LICENSE)). Each folder also has its own provenance README. -| Dataset | Folder | License | Commercial use? | Attribution | -|---------|--------|---------|-----------------|-------------| -| **Datacenters** (~4.3K) | `datacenters/` | **ODbL 1.0** (OpenStreetMap extract) | ✅ (attribution + share-alike on data) | "© OpenStreetMap contributors" | -| **Dams** (704) | `dams/` | **ODbL 1.0** (OpenInfraMap / OSM extract) | ✅ (attribution + share-alike on data) | "© OpenStreetMap contributors" (+ Open Infrastructure Map) | -| **TeleGeography Submarine Cable Map** (712 cables + 1,917 landing points) | `telegeography_submarine_cables/` | **CC BY-NC-SA 3.0** | ❌ **NonCommercial — remove for commercial use** | "© TeleGeography — submarinecablemap.com" | -| **Natural Earth physical regions** (1,046 land + 292 marine named polygons) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | -| **DataSF Analysis Neighborhoods** (41 SF neighborhood polygons) | `neighborhoods/` | **PDDL 1.0** (public domain) | ✅ (no restrictions) | "City & County of San Francisco — DataSF" (courtesy — not legally required) | -| **CCTV ground heights** (3,445 cameras, 34,444 sampled points) | `cctv_ground_heights/` | Derived placement data: heights sampled from the rendered Google Photorealistic 3D Tiles surface (provenance in the folder README) | Same terms as the map it was sampled from | None beyond the map's own Google credit | - -### CCTV ground heights are derived placement data - -`cctv_ground_heights/` holds, per camera in the served CCTV catalog, the WGS84 ellipsoidal ground height Google Photorealistic 3D Tiles report at the camera's position and under the nine support points of its monitor plane, sampled from a running app by `scripts/precompute-cctv-heights.mjs`. It is numeric placement data (a pin dropped on the rendered surface), not imagery or tiles, and it exists so the client can place cameras and planes with zero runtime sampling. Each entry is keyed to the pose it was sampled for and is regenerated whenever a pack's poses change; the folder README documents the schema and the regeneration command. It lives with the other bundled datasets so any consumer that renders these cameras on the same surface reads the same file, under the same terms as the map it came from. +| Dataset | Folder | License | Commercial use? | Attribution | +| --------------------------------------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------------------- | +| **Datacenters** (~4.3K) | `datacenters/` | **ODbL 1.0** (OpenStreetMap extract) | ✅ (attribution + share-alike on data) | "© OpenStreetMap contributors" | +| **Dams** (704) | `dams/` | **ODbL 1.0** (OpenInfraMap / OSM extract) | ✅ (attribution + share-alike on data) | "© OpenStreetMap contributors" (+ Open Infrastructure Map) | +| **TeleGeography Submarine Cable Map** (712 cables + 1,917 landing points) | `telegeography_submarine_cables/` | **CC BY-NC-SA 3.0** | ❌ **NonCommercial — remove for commercial use** | "© TeleGeography — submarinecablemap.com" | +| **Natural Earth physical regions** (1,046 land + 292 marine named polygons) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | +| **DataSF Analysis Neighborhoods** (41 SF neighborhood polygons) | `neighborhoods/` | **PDDL 1.0** (public domain) | ✅ (no restrictions) | "City & County of San Francisco — DataSF" (courtesy — not legally required) | +| **CCTV ground heights** (3,445 cameras) | `cctv_ground_heights/` | Precomputed camera placement heights, aligned to work with Google Photorealistic 3D Tiles (folder README) | — | — | ### ⚠️ TeleGeography is bundled but NonCommercial @@ -98,7 +94,7 @@ The richer structured dataset is licensed separately/commercially by TeleGeograp ### ODbL share-alike (datacenters, dams) -The OSM-derived datasets are under the **Open Database License**. ODbL's share-alike applies to the **data / derived database, not this MIT-licensed code** — the two coexist (exactly how Open Infrastructure Map ships: MIT software + ODbL data). If you publicly distribute a *modified* version of these databases, you must offer it under ODbL. Keep the "© OpenStreetMap contributors" notice (link: https://www.openstreetmap.org/copyright). +The OSM-derived datasets are under the **Open Database License**. ODbL's share-alike applies to the **data / derived database, not this MIT-licensed code** — the two coexist (exactly how Open Infrastructure Map ships: MIT software + ODbL data). If you publicly distribute a _modified_ version of these databases, you must offer it under ODbL. Keep the "© OpenStreetMap contributors" notice (link: https://www.openstreetmap.org/copyright). ### NASA FIRMS acknowledgement diff --git a/scripts/precompute-cctv-heights.mjs b/scripts/precompute-cctv-heights.mjs index 4f0e000ef..24813b5e7 100644 --- a/scripts/precompute-cctv-heights.mjs +++ b/scripts/precompute-cctv-heights.mjs @@ -136,7 +136,7 @@ export function mergeSidecar(existing, updates, generatedAt) { const cameras = { ...existing?.cameras, ...updates }; return { schemaVersion: 1, - provider: 'google-photorealistic-3d', + provider: 'google-3d-tiles', heightReference: 'WGS84-ellipsoid', generatedAt, cameras: Object.fromEntries( @@ -283,7 +283,7 @@ async function loadSidecar(output) { } if ( existing?.schemaVersion !== 1 || - existing.provider !== 'google-photorealistic-3d' || + existing.provider !== 'google-3d-tiles' || existing.heightReference !== 'WGS84-ellipsoid' || !existing.cameras || typeof existing.cameras !== 'object' || diff --git a/server/providers/cctv/groundHeights.js b/server/providers/cctv/groundHeights.js index e581e384f..c73b6e840 100644 --- a/server/providers/cctv/groundHeights.js +++ b/server/providers/cctv/groundHeights.js @@ -10,8 +10,8 @@ export const DEFAULT_GROUND_HEIGHTS_FILE = let _cache = null; /** - * Load the precomputed ground-height sidecar (Google mesh heights under each - * camera's mount and monitor-plane support points). Cached by file mtime so a + * Load the precomputed ground-height sidecar (heights under each camera's mount + * and monitor-plane support points, aligned to the Google 3D Tiles surface). Cached by file mtime so a * catalog refresh re-reads only when the file changed. Missing or malformed * files mean "no shipped heights", never an error. * @param {string} sourceRoot diff --git a/src/data/local_data/cctv_ground_heights/README.md b/src/data/local_data/cctv_ground_heights/README.md index c8169e710..ea42bb721 100644 --- a/src/data/local_data/cctv_ground_heights/README.md +++ b/src/data/local_data/cctv_ground_heights/README.md @@ -1,37 +1,29 @@ # CCTV ground heights Precomputed ground height under every camera in the served CCTV catalog and -under the nine support points of its monitor plane, so the client can place a -camera and its plane with no runtime sampling. Shared placement data: any -consumer that renders these cameras on the same photorealistic surface can -reuse it. - -Source surface: Google Photorealistic 3D Tiles, sampled at maximum detail with -CesiumJS `scene.sampleHeightMostDetailed` from a running God's Eye View -(scripts/precompute-cctv-heights.mjs). Heights are WGS84 **ellipsoidal** -metres; no geoid conversion is needed or applied. This is placement data -derived from the rendered surface, not imagery. +under the nine support points of its monitor plane, aligned to work with +Google Photorealistic 3D Tiles. Heights are WGS84 ellipsoidal metres. The +client places a camera and its plane from this file with no runtime sampling. Runtime output: `cctv_ground_heights.json` ``` { "schemaVersion": 1, - "provider": "google-photorealistic-3d", + "provider": "google-3d-tiles", "heightReference": "WGS84-ellipsoid", "generatedAt": "", "cameras": { "": { - "poseHash": "p1-…", // hash of the served pose the samples describe + "poseHash": "p1-…", // hash of the served pose the entry describes "status": "ok" | "miss", "mountGroundM": , // ground under the camera position (absent on a miss) - "supports": { // ground under the plane's 3×3 support grid; a value is - // null where that point had no sample (absent on a miss) - "bl","bm","br", // bottom row (left, middle, right) - "ml","mc","mr", // middle row - "tl","tm","tr" // top row + "supports": { // ground under the plane's 3×3 support grid; null where + "bl","bm","br", // a point has no value (absent on a miss) + "ml","mc","mr", + "tl","tm","tr" }, - "misses": [], + "misses": [], "sampledAt": "", "attempts": } @@ -40,19 +32,15 @@ Runtime output: `cctv_ground_heights.json` ``` Support point positions are defined by `src/data/cctvFootprint.js` -(`planeSupportPoints`), which the client, the server join -(`server/providers/cctv/groundHeights.js`) and the precompute all share. An -entry is used only while the camera's served pose still hashes to -`poseHash`; a camera whose feed moved it, or whose pose a user edited, falls -back to runtime placement from the Re:Earth DEM. +(`planeSupportPoints`), shared with the server join +(`server/providers/cctv/groundHeights.js`). An entry is used only while the +camera's served pose still hashes to `poseHash`; a camera whose feed moved it, +or whose pose a user edited, falls back to runtime placement from the terrain +proxy. -Regenerate (resumable; only cameras whose pose changed or whose entry is -incomplete are re-sampled): +Regenerate against a running app (resumable; only cameras whose pose changed +or whose entry is incomplete are redone): ``` GEV_BASE=http://localhost:4173 node scripts/precompute-cctv-heights.mjs ``` - -Coverage at generation (2026-09-14): 3,445 of 3,446 cameras `ok` (six of them -with one or more null supports), 34,444 sampled heights, 43 minutes on a real -GPU. Regenerate whenever a pack changes its poses or a new pack lands. diff --git a/src/data/local_data/cctv_ground_heights/cctv_ground_heights.json b/src/data/local_data/cctv_ground_heights/cctv_ground_heights.json index afa26959b..902a69c72 100644 --- a/src/data/local_data/cctv_ground_heights/cctv_ground_heights.json +++ b/src/data/local_data/cctv_ground_heights/cctv_ground_heights.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "provider": "google-photorealistic-3d", + "provider": "google-3d-tiles", "heightReference": "WGS84-ellipsoid", "generatedAt": "2026-09-14T01:42:02.486Z", "cameras": { diff --git a/src/layers/cctv/geometry.js b/src/layers/cctv/geometry.js index d51b4170a..797d1706b 100644 --- a/src/layers/cctv/geometry.js +++ b/src/layers/cctv/geometry.js @@ -26,8 +26,9 @@ export function createGeometry({ state: layerState, services, parts, source }) { * CURRENT pose, or null. Shipped precompute samples (`camera.groundHeights`) * were taken for the nominal pose; they apply only while the pose hash still * matches, so a calibrated (edited) camera falls back to the mount ground - * until its own footprint is resolved. Photoreal regime only: the samples - * are Google mesh heights and would be wrong against a globe DEM. + * until its own footprint is resolved. Photoreal regime only: the values + * are aligned to the Google 3D Tiles surface and would be wrong against a + * globe DEM. * @param {Object} record * @returns {Record|null} */ @@ -72,7 +73,8 @@ export function createGeometry({ state: layerState, services, parts, source }) { /** * True when the record carries shipped precompute samples for its CURRENT - * pose and the scene is rendering the photoreal mesh they were taken from. + * pose and the scene is rendering the Google 3D Tiles surface they are + * aligned to. * @param {Object} record * @returns {boolean} */ diff --git a/src/tooling/precomputeCctvHeights.test.mjs b/src/tooling/precomputeCctvHeights.test.mjs index b0e222b79..439e4db0a 100644 --- a/src/tooling/precomputeCctvHeights.test.mjs +++ b/src/tooling/precomputeCctvHeights.test.mjs @@ -206,7 +206,7 @@ test('sidecar merging sorts ids, preserves unselected entries and replaces stale assert.deepEqual(result.cameras.a, { status: 'miss' }); assert.equal(old.cameras.a.mountGroundM, 20); assert.equal(result.schemaVersion, 1); - assert.equal(result.provider, 'google-photorealistic-3d'); + assert.equal(result.provider, 'google-3d-tiles'); assert.equal(result.heightReference, 'WGS84-ellipsoid'); assert.equal(result.generatedAt, sampledAt); assert.deepEqual(mergeSidecar(null, {}, sampledAt).cameras, {});