mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04: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 * as Cesium from 'cesium';
|
||||||
import { FOLLOW_EYE_HEIGHT_M } from './policy.js';
|
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
|
* Drive the globe camera from the street-level pose: either continuously
|
||||||
* ("camera follows view") or once, framing the image from behind.
|
* ("camera follows view") or once, framing the image from behind.
|
||||||
*/
|
*/
|
||||||
export function createCameraFollow({ state }) {
|
export function createCameraFollow({ state, parts }) {
|
||||||
const { render } = state.services;
|
const { render } = state.services;
|
||||||
|
|
||||||
function requestRender() {
|
function requestRender() {
|
||||||
render?.governorRequestRender?.('street-level-follow');
|
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) {
|
function groundHeightAt(lon, lat, fallback) {
|
||||||
const scene = state.viewer?.scene;
|
const scene = state.viewer?.scene;
|
||||||
const carto = Cesium.Cartographic.fromDegrees(lon, lat);
|
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;
|
let height = null;
|
||||||
try {
|
try {
|
||||||
if (scene?.sampleHeightSupported) height = scene.sampleHeight(carto);
|
if (scene?.sampleHeightSupported) height = scene.sampleHeight(carto);
|
||||||
} catch {
|
} catch {
|
||||||
/* not sampleable yet */
|
/* not sampleable yet */
|
||||||
}
|
}
|
||||||
if (!Number.isFinite(height)) height = scene?.globe?.getHeight?.(carto);
|
if (!plausible(height)) height = dem;
|
||||||
if (!Number.isFinite(height)) height = fallback;
|
if (!plausible(height)) height = scene?.globe?.getHeight?.(carto);
|
||||||
return Number.isFinite(height) ? height : 0;
|
if (!plausible(height)) height = fallback;
|
||||||
|
return plausible(height) ? height : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Put the Cesium camera where the street-level camera is. */
|
/** Put the Cesium camera where the street-level camera is. */
|
||||||
|
|||||||
Reference in new issue
Block a user