mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
fix(street-level): ignore implausible ground samples when framing a photo
Opening a photo frames it from 140 m behind using scene.sampleHeight for the ground. Before the Google 3D tiles under the photo have loaded, that sample can be kilometres wrong: an Austin 360 photo sampled -14,886 m and the camera flew to -14,811 m. A sample now counts only when it is a plausible surface height and, once the bare-earth height is known, lies within -15/+80 m of it; otherwise the bare-earth height is used. FOLLOW's eye height goes through the same check. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d3d3898dbb
commit
d77dccb350
1 file changed
+28
-4
@@ -1,29 +1,53 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { FOLLOW_EYE_HEIGHT_M } from './policy.js';
|
||||
|
||||
/** Ellipsoidal heights a land surface can have (Dead Sea shore to Everest, with geoid slack). */
|
||||
const SURFACE_MIN_M = -500;
|
||||
const SURFACE_MAX_M = 9000;
|
||||
/** Rendered mesh window around the bare earth: roofs and bridges, not whole towers. */
|
||||
const MESH_BELOW_DEM_M = 15;
|
||||
const MESH_ABOVE_DEM_M = 80;
|
||||
|
||||
/**
|
||||
* Drive the globe camera from the street-level pose: either continuously
|
||||
* ("camera follows view") or once, framing the image from behind.
|
||||
*/
|
||||
export function createCameraFollow({ state }) {
|
||||
export function createCameraFollow({ state, parts }) {
|
||||
const { render } = state.services;
|
||||
|
||||
function requestRender() {
|
||||
render?.governorRequestRender?.('street-level-follow');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ground under a photo for framing and following. The rendered surface is
|
||||
* sampled first, but `sampleHeight` can return nonsense before the tiles
|
||||
* under the point have loaded (kilometres below the ellipsoid), so a sample
|
||||
* counts only when it is a plausible surface height and, once the bare-earth
|
||||
* height is known, lies within the mesh window around it.
|
||||
*/
|
||||
function groundHeightAt(lon, lat, fallback) {
|
||||
const scene = state.viewer?.scene;
|
||||
const carto = Cesium.Cartographic.fromDegrees(lon, lat);
|
||||
const caster = parts?.groundCaster;
|
||||
const dem = caster?.groundAt(lon, lat) ?? null;
|
||||
if (dem === null) caster?.prepare([[lon, lat]]);
|
||||
const plausible = (height) =>
|
||||
Number.isFinite(height) &&
|
||||
height >= SURFACE_MIN_M &&
|
||||
height <= SURFACE_MAX_M &&
|
||||
(dem === null ||
|
||||
(height >= dem - MESH_BELOW_DEM_M && height <= dem + MESH_ABOVE_DEM_M));
|
||||
let height = null;
|
||||
try {
|
||||
if (scene?.sampleHeightSupported) height = scene.sampleHeight(carto);
|
||||
} catch {
|
||||
/* not sampleable yet */
|
||||
}
|
||||
if (!Number.isFinite(height)) height = scene?.globe?.getHeight?.(carto);
|
||||
if (!Number.isFinite(height)) height = fallback;
|
||||
return Number.isFinite(height) ? height : 0;
|
||||
if (!plausible(height)) height = dem;
|
||||
if (!plausible(height)) height = scene?.globe?.getHeight?.(carto);
|
||||
if (!plausible(height)) height = fallback;
|
||||
return plausible(height) ? height : 0;
|
||||
}
|
||||
|
||||
/** Put the Cesium camera where the street-level camera is. */
|
||||
|
||||
Reference in new issue
Block a user