reszta poprawek

This commit is contained in:
2026-08-09 09:47:34 +02:00
parent 966dd3f209
commit a0c9d7947b
439 changed files with 112891 additions and 0 deletions
@@ -0,0 +1,284 @@
import React, {useEffect, useMemo, useRef, useState} from 'react';
import {
AbsoluteFill,
cancelRender,
continueRender,
delayRender,
useCurrentFrame,
useVideoConfig,
} from 'remotion';
import terrainPath from './cesium-path.json';
import {smoothFlightPath, type LngLat} from './flight-path';
export type FlyoverMode = 'landscape' | 'city';
export type {LngLat} from './flight-path';
export type CesiumFlythroughProps = {
mode?: FlyoverMode;
path?: LngLat[];
pathSmoothingPasses?: number;
altitudeStart?: number;
altitudeEnd?: number;
lookAheadKm?: number;
travelKm?: number;
pitchFromNadir?: number;
verticalExaggeration?: number;
maximumScreenSpaceError?: number;
};
const MAPTILER_KEY = process.env.REMOTION_MAPTILER_KEY;
const GOOGLE_MAPS_API_KEY = process.env.REMOTION_GOOGLE_MAPS_API_KEY;
const CESIUM_VER = '1.143';
const CDN = `https://cesium.com/downloads/cesiumjs/releases/${CESIUM_VER}/Build/Cesium/`;
const R = 6371;
const MAX_BANK = 0.13;
const BANK_GAIN = 0.6;
const havKm = (a: number[], b: number[]) => {
const r = Math.PI / 180;
const dLat = (b[1] - a[1]) * r;
const dLng = (b[0] - a[0]) * r;
const h =
Math.sin(dLat / 2) ** 2 +
Math.cos(a[1] * r) * Math.cos(b[1] * r) * Math.sin(dLng / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(h));
};
const makePathWalker = (path: LngLat[]) => {
if (path.length < 2)
throw new Error('Flyover path needs at least two points');
const cumulative = [0];
for (let i = 1; i < path.length; i++) {
cumulative.push(cumulative[i - 1] + havKm(path[i - 1], path[i]));
}
const lengthKm = cumulative[cumulative.length - 1];
const along = (km: number): LngLat => {
const d = Math.max(0, Math.min(lengthKm, km));
let i = 1;
while (i < cumulative.length && cumulative[i] < d) i++;
if (i >= cumulative.length) return path[path.length - 1];
const segmentLength = cumulative[i] - cumulative[i - 1] || 1;
const t = (d - cumulative[i - 1]) / segmentLength;
return [
path[i - 1][0] + (path[i][0] - path[i - 1][0]) * t,
path[i - 1][1] + (path[i][1] - path[i - 1][1]) * t,
];
};
return {along, lengthKm};
};
const bearing = (a: number[], b: number[]) => {
const r = Math.PI / 180;
const y = Math.sin((b[0] - a[0]) * r) * Math.cos(b[1] * r);
const x =
Math.cos(a[1] * r) * Math.sin(b[1] * r) -
Math.sin(a[1] * r) * Math.cos(b[1] * r) * Math.cos((b[0] - a[0]) * r);
return Math.atan2(y, x);
};
const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
const clamp = (v: number, lo: number, hi: number) =>
Math.max(lo, Math.min(hi, v));
const loadCesium = () =>
new Promise<any>((resolve, reject) => {
if ((window as any).Cesium) return resolve((window as any).Cesium);
(window as any).CESIUM_BASE_URL = CDN;
const css = document.createElement('link');
css.rel = 'stylesheet';
css.href = `${CDN}Widgets/widgets.css`;
document.head.appendChild(css);
const script = document.createElement('script');
script.src = `${CDN}Cesium.js`;
script.onload = () => resolve((window as any).Cesium);
script.onerror = () =>
reject(new Error(`Failed to load CesiumJS ${CESIUM_VER}`));
document.head.appendChild(script);
});
export const CesiumFlythrough: React.FC<CesiumFlythroughProps> = ({
mode = 'landscape',
path = terrainPath as LngLat[],
pathSmoothingPasses = 3,
altitudeStart = 4600,
altitudeEnd = 4300,
lookAheadKm = 1.5,
travelKm = 13,
pitchFromNadir = 76,
verticalExaggeration = 1.1,
maximumScreenSpaceError = 8,
}) => {
const containerRef = useRef<HTMLDivElement>(null);
const started = useRef(false);
const viewerRef = useRef<any>(null);
const tilesetRef = useRef<any>(null);
const frame = useCurrentFrame();
const {durationInFrames, fps, width, height} = useVideoConfig();
const [ready, setReady] = useState(false);
const [handle] = useState(() =>
delayRender(`cesium init: ${mode}`, {timeoutInMilliseconds: 120000}),
);
const walker = useMemo(
() => makePathWalker(smoothFlightPath(path, pathSmoothingPasses)),
[path, pathSmoothingPasses],
);
const setCamera = (C: any, viewer: any, progress: number) => {
const maxTravel = Math.max(0, walker.lengthKm - lookAheadKm * 2);
const cameraDistance = Math.min(travelKm, maxTravel) * progress;
const camera = walker.along(cameraDistance);
const aim = walker.along(cameraDistance + lookAheadKm);
const aim2 = walker.along(cameraDistance + lookAheadKm * 2);
const heading = bearing(camera, aim);
let headingDelta = bearing(aim, aim2) - heading;
while (headingDelta > Math.PI) headingDelta -= 2 * Math.PI;
while (headingDelta < -Math.PI) headingDelta += 2 * Math.PI;
viewer.camera.setView({
destination: C.Cartesian3.fromDegrees(
camera[0],
camera[1],
lerp(altitudeStart, altitudeEnd, progress),
),
orientation: {
heading,
pitch: C.Math.toRadians(-(90 - pitchFromNadir)),
roll: clamp(headingDelta * BANK_GAIN, -MAX_BANK, MAX_BANK),
},
});
};
const tilesAreLoaded = (viewer: any) => {
if (mode === 'landscape') return viewer.scene.globe.tilesLoaded;
return Boolean(tilesetRef.current?.tilesLoaded);
};
const settle = (viewer: any) =>
new Promise<void>((resolve) => {
let stable = 0;
let ticks = 0;
const tick = () => {
viewer.render();
ticks++;
stable = tilesAreLoaded(viewer) ? stable + 1 : 0;
if (stable > 8 || ticks > 600) {
viewer.render();
resolve();
} else {
setTimeout(tick, 8);
}
};
tick();
});
useEffect(() => {
if (started.current) return;
started.current = true;
(async () => {
if (mode === 'landscape' && !MAPTILER_KEY) {
throw new Error(
'Set REMOTION_MAPTILER_KEY. Create a key at https://cloud.maptiler.com/account/keys/',
);
}
if (mode === 'city' && !GOOGLE_MAPS_API_KEY) {
throw new Error(
'Set REMOTION_GOOGLE_MAPS_API_KEY. Create a Map Tiles API key at https://developers.google.com/maps/documentation/tile/get-api-key',
);
}
if (mode === 'city' && durationInFrames / fps > 30) {
throw new Error(
'Google Photorealistic 3D Tiles compositions must not exceed 30 seconds',
);
}
const C = await loadCesium();
const viewer = new C.Viewer(containerRef.current, {
baseLayer: false,
baseLayerPicker: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
navigationHelpButton: false,
animation: false,
timeline: false,
fullscreenButton: false,
infoBox: false,
selectionIndicator: false,
contextOptions: {webgl: {preserveDrawingBuffer: true}},
});
if (mode === 'landscape') {
viewer.imageryLayers.addImageryProvider(
new C.UrlTemplateImageryProvider({
url: `https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=${MAPTILER_KEY}`,
maximumLevel: 20,
}),
);
viewer.terrainProvider = await C.CesiumTerrainProvider.fromUrl(
`https://api.maptiler.com/tiles/terrain-quantized-mesh-v2/?key=${MAPTILER_KEY}`,
{requestVertexNormals: true},
);
viewer.creditDisplay.addStaticCredit(
new C.Credit(
'<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a>',
true,
),
);
}
if (mode === 'city') {
viewer.scene.globe.show = false;
const tileset = await C.Cesium3DTileset.fromUrl(
`https://tile.googleapis.com/v1/3dtiles/root.json?key=${GOOGLE_MAPS_API_KEY}`,
{
showCreditsOnScreen: true,
maximumScreenSpaceError,
},
);
viewer.scene.primitives.add(tileset);
tilesetRef.current = tileset;
}
viewer.useDefaultRenderLoop = false;
viewer.scene.skyAtmosphere.show = true;
viewer.scene.fog.enabled = true;
viewer.scene.globe.enableLighting = false;
viewer.scene.verticalExaggeration = verticalExaggeration;
(window as any).__CESIUM_FLYOVER__ = {C, mode};
viewerRef.current = viewer;
setCamera(C, viewer, 0);
await settle(viewer);
setReady(true);
continueRender(handle);
})().catch((error) => cancelRender(error));
}, [durationInFrames, fps, handle, mode]);
useEffect(() => {
if (!ready) return;
const frameHandle = delayRender(`cesium ${mode} frame ${frame}`, {
timeoutInMilliseconds: 60000,
});
const C = (window as any).__CESIUM_FLYOVER__.C;
const viewer = viewerRef.current;
const progress = durationInFrames <= 1 ? 0 : frame / (durationInFrames - 1);
setCamera(C, viewer, progress);
settle(viewer).then(() => continueRender(frameHandle));
}, [ready, frame, durationInFrames, mode]);
return (
<AbsoluteFill style={{backgroundColor: '#000'}}>
<div ref={containerRef} style={{width, height, position: 'absolute'}} />
{mode === 'city' ? (
<div
style={{
position: 'absolute',
top: 20,
right: 24,
color: 'white',
font: '500 18px/1.2 sans-serif',
textShadow: '0 1px 4px black',
}}
>
For promotional purposes only
</div>
) : null}
</AbsoluteFill>
);
};
@@ -0,0 +1,299 @@
[
[94.986139893537, 29.76417312959953],
[94.98637054463002, 29.764163024004816],
[94.98661427422437, 29.764153025681516],
[94.9868698103708, 29.764142908388347],
[94.98713600736019, 29.764132461562934],
[94.98741179569139, 29.76412145291623],
[94.9876962466277, 29.764109663422126],
[94.98798853462426, 29.764096898390772],
[94.98828790834106, 29.764082995679242],
[94.98859364523021, 29.764067827511347],
[94.98890509685035, 29.764051279216236],
[94.98922167960325, 29.76403324759024],
[94.98954294512464, 29.76401367774424],
[94.9898685550894, 29.76399255290906],
[94.99019820264337, 29.76396985787546],
[94.9905316178847, 29.763945606334815],
[94.9908685732739, 29.763919866576575],
[94.99120886105722, 29.763892700951896],
[94.99155229116181, 29.7638641665054],
[94.99189872300363, 29.76383429811986],
[94.99224811692223, 29.763803085651237],
[94.99260053337049, 29.763770509641105],
[94.99295601118384, 29.76373658086857],
[94.99331456742908, 29.763701322339223],
[94.99367598745215, 29.763664830647013],
[94.99404000156176, 29.763627219082974],
[94.99440635968021, 29.763588592698778],
[94.99477481502787, 29.76354905236459],
[94.9951451006731, 29.763508748648892],
[94.99578766204738, 29.763462125646818],
[94.99643710580968, 29.763412119743368],
[94.99709296623192, 29.763358988682928],
[94.99775479298779, 29.763302979031952],
[94.99842214521965, 29.763244327404465],
[94.99909470569231, 29.763183258547627],
[94.9997722961385, 29.76312010454948],
[95.00045474013422, 29.763055184243758],
[95.00114189582168, 29.762988795623112],
[95.00183368970049, 29.762921207778405],
[95.0025300799095, 29.76285270023514],
[95.00323103443773, 29.762783549665084],
[95.00393658318124, 29.76271400155497],
[95.00464681949704, 29.76264432424487],
[95.00536183331896, 29.76257477740286],
[95.00608171146906, 29.762505612813378],
[95.00680653793428, 29.762437075077955],
[95.00753639864557, 29.762369398844733],
[95.00827137837749, 29.762302811854063],
[95.00901153006761, 29.762237519590354],
[95.00975680776318, 29.76217368790719],
[95.01050716875933, 29.762111478518566],
[95.0112626067996, 29.76205102042169],
[95.01202312290016, 29.761992432502932],
[95.01278871942189, 29.76193583156792],
[95.01355940108247, 29.761881333165324],
[95.01433525277555, 29.761829093407865],
[95.01511636205572, 29.761779224166457],
[95.01590278872715, 29.76173180995877],
[95.0166868810408, 29.76168612055982],
[95.01746871725406, 29.761642332250204],
[95.0182483756254, 29.76160062131038],
[95.01902596675926, 29.761561177619345],
[95.019801682618, 29.761524238306453],
[95.02057570378254, 29.76149004865798],
[95.02134818878243, 29.761458838563573],
[95.02211921065114, 29.761430763930672],
[95.02288888930805, 29.761405973069504],
[95.02365734467304, 29.761384614290225],
[95.02442469666667, 29.761366835902948],
[95.02519095257038, 29.761352731197437],
[95.02595602043016, 29.761342344990513],
[95.02671980829304, 29.761335722099044],
[95.02748221022355, 29.76133286485609],
[95.02824308111781, 29.761333684556867],
[95.02900227020879, 29.761338090875398],
[95.02975960629327, 29.76134599002589],
[95.03051480114966, 29.76135728786741],
[95.03126749207338, 29.761371921751238],
[95.03201723576402, 29.761389829130785],
[95.03276363398774, 29.761410893146387],
[95.03350632277824, 29.761434973117545],
[95.03424521675927, 29.76146183394706],
[95.03498037607913, 29.761491215377145],
[95.035711917426, 29.761522866578012],
[95.03643998610582, 29.761556530192124],
[95.03716475930274, 29.761591886465347],
[95.03788653744915, 29.761628566185358],
[95.03860571883365, 29.76166618469001],
[95.03932258585421, 29.76170436456548],
[95.04003738892985, 29.76174273062808],
[95.04075025083816, 29.76178094997509],
[95.0414610559133, 29.76181870813213],
[95.04216961904287, 29.761855638407084],
[95.04287591713418, 29.761891331889718],
[95.04357986124926, 29.761925397709096],
[95.04428137757625, 29.761957488479126],
[95.04498041854592, 29.76198725048925],
[95.04567682817188, 29.762014317811357],
[95.04637032968634, 29.762038376323694],
[95.04706059416637, 29.762059099770216],
[95.04774726432963, 29.762076162373777],
[95.0484300050609, 29.762089241174117],
[95.04910871445378, 29.762098042845082],
[95.04978328153793, 29.762102280852183],
[95.05045359964508, 29.76210167552205],
[95.05111966253706, 29.76209602004179],
[95.05178153406797, 29.762085106891018],
[95.05243927503516, 29.762068731547185],
[95.05309287649075, 29.762046750046103],
[95.0537422946664, 29.762019099359485],
[95.05438748396233, 29.761985721609257],
[95.05502839823626, 29.76194655859307],
[95.05566488201883, 29.761901557942874],
[95.05629656919591, 29.761850805510885],
[95.05692313234233, 29.761794428680094],
[95.0575442743842, 29.761732580860688],
[95.0581596433054, 29.761665348138973],
[95.05876888708963, 29.761592816601354],
[95.05937164047754, 29.761515065256333],
[95.05996759228947, 29.761432144038746],
[95.06055643134583, 29.761344102883623],
[95.06113793491645, 29.761251010034922],
[95.06171214230999, 29.761153046649387],
[95.06227907948092, 29.761050389948267],
[95.06283877238438, 29.760943217152814],
[95.06339127381165, 29.760831691663462],
[95.06393669678933, 29.760716002374487],
[95.06447520396281, 29.76059636241658],
[95.06500695797821, 29.760472984920362],
[95.06553212847378, 29.760346104258282],
[95.0660508986937, 29.760216015040477],
[95.06656344194985, 29.760083025494016],
[95.06707002648291, 29.75994741412334],
[95.06757112978441, 29.759809440866206],
[95.06806722979658, 29.759669344181514],
[95.06855878142073, 29.759527354008487],
[95.06904617625263, 29.759383697903765],
[95.06952978875404, 29.75923861533451],
[95.07000993080214, 29.759092371156385],
[95.07048679175114, 29.758945227682446],
[95.07096044787545, 29.75879742836973],
[95.07143096114058, 29.758649219939148],
[95.0718984144853, 29.758500858117706],
[95.07236278188816, 29.7583525823887],
[95.07282412506945, 29.758204644682806],
[95.07328275575983, 29.75805728963777],
[95.07373905641253, 29.757910760813612],
[95.07419366476313, 29.757765217208473],
[95.07464735762416, 29.757620800921966],
[95.07510085345471, 29.757477677507868],
[95.07555467766437, 29.757336168750566],
[95.07600940811365, 29.757196598118206],
[95.07646537399586, 29.75705931280275],
[95.0769228207089, 29.756924677394206],
[95.07738220221682, 29.756793075496777],
[95.07784401968648, 29.75666487927172],
[95.07830874492939, 29.756540496044202],
[95.07877690647402, 29.756420332181715],
[95.07924898851259, 29.75630478841808],
[95.07972503722137, 29.756194196891926],
[95.08020511490892, 29.756088882533362],
[95.0806891403115, 29.75598918720403],
[95.08117690920173, 29.75589531641115],
[95.08166835685006, 29.755807414283098],
[95.08216335868525, 29.75572566824862],
[95.08266177736347, 29.755650250535062],
[95.08316349491537, 29.75558120546187],
[95.08366839703267, 29.755518567048284],
[95.08417639041532, 29.75546236367944],
[95.08468755179344, 29.755412571989652],
[95.08520236790308, 29.755369015997044],
[95.08572134650697, 29.75533148313236],
[95.0862450098908, 29.755299740305322],
[95.08677390781156, 29.75527358808779],
[95.08730861289804, 29.755252808551163],
[95.08784970300886, 29.755237175354623],
[95.08839755885471, 29.755226476280296],
[95.08895256438073, 29.755220494902016],
[95.089514993805, 29.755219019351184],
[95.09008489086116, 29.7552217729881],
[95.09066229928165, 29.75522847917293],
[95.09124726342738, 29.755238870403907],
[95.09183976966378, 29.755252726598844],
[95.09243978867215, 29.75526985018834],
[95.09304723439128, 29.755290065097345],
[95.09366184648091, 29.75531326126932],
[95.09428337414857, 29.755339326723966],
[95.09491171647382, 29.755368102171502],
[95.09554680939114, 29.75539940595205],
[95.09618846028675, 29.755433126230766],
[95.09683632409143, 29.75546923335011],
[95.09749004228215, 29.75550775219342],
[95.09814924669702, 29.755548754655436],
[95.0988136358514, 29.755592374644042],
[95.09948290826172, 29.755638746066982],
[95.1001568080277, 29.75568798494813],
[95.10083517891061, 29.75574017449467],
[95.10151797539464, 29.75579531974171],
[95.1022051519645, 29.755853425724286],
[95.10289664375364, 29.755914488290983],
[95.10359258928374, 29.755978570204803],
[95.10429306658138, 29.756045742645284],
[95.10499798654989, 29.756116067070348],
[95.10570717321444, 29.75618958016383],
[95.10642032295875, 29.75626636089044],
[95.10713711848761, 29.756346492746122],
[95.10785729025027, 29.75643004436662],
[95.10858043622838, 29.75651688160893],
[95.10930611534633, 29.75660684892344],
[95.11003407093642, 29.756699686157475],
[95.11076414467685, 29.756795123665622],
[95.1114960914754, 29.756892893838618],
[95.11222971288655, 29.756992700238396],
[95.1129649452222, 29.75709420093414],
[95.11370170201873, 29.75719709582746],
[95.11443986012442, 29.757301125099488],
[95.11517935555177, 29.7574061249826],
[95.11592009761476, 29.757511940391662],
[95.11666232015585, 29.75761835330566],
[95.11740624233691, 29.757725222810585],
[95.11815181076378, 29.75783253698326],
[95.11889913308254, 29.757940178669305],
[95.11964841222917, 29.758048000558695],
[95.12039993276164, 29.758155854652614],
[95.12115399312397, 29.75826357999786],
[95.1219108497459, 29.75837102690515],
[95.1226706293697, 29.758478081829693],
[95.12343325561484, 29.758584686897258],
[95.12419857627997, 29.758690818430438],
[95.12496638982559, 29.75879646083105],
[95.12573649209446, 29.7589015818837],
[95.12650863318528, 29.75900618637391],
[95.12728253192327, 29.759110282431784],
[95.12805798566751, 29.75921386162033],
[95.12883477913662, 29.759316919371038],
[95.12961273528985, 29.759419445656786],
[95.13039166301432, 29.759521458216526],
[95.13117134363408, 29.759622963323043],
[95.13195155721434, 29.759723948972997],
[95.13273211930314, 29.759824349786275],
[95.13351286507051, 29.759924061406032],
[95.13428648274362, 29.76002351015658],
[95.1350533298064, 29.760122544307915],
[95.1358137532818, 29.760221010686855],
[95.13656784419986, 29.760318809952974],
[95.13731567503761, 29.76041584848236],
[95.1380573752464, 29.760511990985425],
[95.13879310931623, 29.76060704815151],
[95.13952306473344, 29.760700794123938],
[95.14024751710419, 29.7607929520901],
[95.14096671686433, 29.760883206230545],
[95.14168092332761, 29.76097123202995],
[95.14239029599311, 29.761056732470486],
[95.14309486625548, 29.761139484506582],
[95.14379454089128, 29.761219462160696],
[95.14448922306659, 29.76129664046317],
[95.14517882147311, 29.76137100941381],
[95.14586312132259, 29.761442532574584],
[95.14654188135431, 29.761511168945386],
[95.14721489938523, 29.761576901934955],
[95.14788204807155, 29.761639772673718],
[95.14854319868547, 29.76169982923195],
[95.14919822095698, 29.761757127412878],
[95.14984699116548, 29.76181173598209],
[95.15048960377052, 29.761863851723042],
[95.15112617637942, 29.761913696049017],
[95.15175681293137, 29.761961561816054],
[95.15238148064795, 29.762007691856205],
[95.15300009096235, 29.762052309028526],
[95.1533539374323, 29.762086082676035],
[95.15370650809008, 29.762118928860186],
[95.15405759583123, 29.762150875711065],
[95.15440704121897, 29.76218191319173],
[95.1547548321985, 29.762211967913583],
[95.15510097264206, 29.762240955288657],
[95.15544525415498, 29.762268829619945],
[95.15578751039571, 29.76229553455492],
[95.15612769998111, 29.762320941845203],
[95.15646565712565, 29.762344985615734],
[95.156801142589, 29.76236761294652],
[95.1571338046714, 29.76238883654028],
[95.15746323934037, 29.76240869370805],
[95.15778903282519, 29.762427217766984],
[95.15811077257146, 29.762444433666733],
[95.15842800577592, 29.762460368791256],
[95.15874028837707, 29.76247502889767],
[95.15904716834646, 29.76248842410003],
[95.1593481499996, 29.762500590502704],
[95.15964271930007, 29.76251153961251],
[95.1599303416933, 29.76252129267978],
[95.16021045104225, 29.762529892932115],
[95.16048243037355, 29.762537389252305],
[95.16074559672008, 29.762543832974302],
[95.1609993202866, 29.762549265122786],
[95.16124294069552, 29.762553753099137],
[95.16147571071544, 29.762557390653928],
[95.16169677155058, 29.762560323342807]
]
@@ -0,0 +1,12 @@
[
[-74.0135, 40.7047],
[-74.0102, 40.7104],
[-74.0074, 40.7167],
[-74.0047, 40.7232],
[-74.0017, 40.7297],
[-73.9988, 40.7362],
[-73.9954, 40.7429],
[-73.9917, 40.7496],
[-73.9882, 40.7563],
[-73.9848, 40.7631]
]
@@ -0,0 +1,39 @@
import React from 'react';
import {Composition} from 'remotion';
import {CesiumFlythrough, type CesiumFlythroughProps} from './CesiumFlythrough';
import cityPath from './city-path.json';
export const RemotionRoot: React.FC = () => (
<>
<Composition
id="LandscapeFlyover"
component={CesiumFlythrough}
defaultProps={{mode: 'landscape'} satisfies CesiumFlythroughProps}
durationInFrames={24 * 30}
fps={30}
width={1920}
height={1080}
/>
<Composition
id="CityFlyover"
component={CesiumFlythrough}
defaultProps={
{
mode: 'city',
path: cityPath as [number, number][],
altitudeStart: 700,
altitudeEnd: 500,
lookAheadKm: 0.7,
travelKm: 4.5,
pitchFromNadir: 72,
verticalExaggeration: 1,
maximumScreenSpaceError: 6,
} satisfies CesiumFlythroughProps
}
durationInFrames={18 * 30}
fps={30}
width={1920}
height={1080}
/>
</>
);
@@ -0,0 +1,35 @@
export type LngLat = [number, number];
// Chaikin corner cutting turns a sparse route into a continuous curve. Repeated passes round
// direction changes into deliberate swerves instead of left-right heading bumps.
export const smoothFlightPath = (source: LngLat[], passes = 3): LngLat[] => {
if (source.length < 2)
throw new Error('Flyover path needs at least two points');
// Keep adjacent longitudes continuous for routes that cross the antimeridian.
const unwrapped: LngLat[] = [source[0]];
for (let index = 1; index < source.length; index++) {
const [lng, lat] = source[index];
const previous = unwrapped[index - 1][0];
let adjusted = lng;
while (adjusted - previous > 180) adjusted -= 360;
while (adjusted - previous < -180) adjusted += 360;
unwrapped.push([adjusted, lat]);
}
let curve = unwrapped;
for (let pass = 0; pass < Math.max(0, passes); pass++) {
const next: LngLat[] = [curve[0]];
for (let i = 0; i < curve.length - 1; i++) {
const a = curve[i];
const b = curve[i + 1];
next.push(
[a[0] * 0.75 + b[0] * 0.25, a[1] * 0.75 + b[1] * 0.25],
[a[0] * 0.25 + b[0] * 0.75, a[1] * 0.25 + b[1] * 0.75],
);
}
next.push(curve[curve.length - 1]);
curve = next;
}
return curve;
};
@@ -0,0 +1,215 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"name": "Yarlung Tsangpo (OSM, gorge way)"},
"geometry": {
"type": "LineString",
"coordinates": [
[94.8794306, 29.5453548],
[94.880058, 29.5500259],
[94.8804545, 29.5529773],
[94.8872806, 29.559007],
[94.8902386, 29.5645817],
[94.8945618, 29.5651505],
[94.8985437, 29.5703839],
[94.8978611, 29.5758448],
[94.9077237, 29.5843086],
[94.9107706, 29.5872382],
[94.9136749, 29.5879042],
[94.9208424, 29.5864253],
[94.9243692, 29.5890419],
[94.9243692, 29.5945028],
[94.9268508, 29.597544],
[94.9331942, 29.6000111],
[94.9350913, 29.6024165],
[94.9359736, 29.6042869],
[94.9354367, 29.6064452],
[94.9350634, 29.608155],
[94.9343462, 29.6094434],
[94.9295695, 29.6113703],
[94.9288061, 29.6124782],
[94.9268721, 29.6194181],
[94.9273809, 29.6276608],
[94.9274409, 29.6286334],
[94.9263783, 29.6303683],
[94.9250518, 29.6304537],
[94.922744, 29.6299103],
[94.9170292, 29.6256472],
[94.9144757, 29.6243553],
[94.9115439, 29.6243318],
[94.9008302, 29.6273853],
[94.8972905, 29.6276085],
[94.8897112, 29.6252949],
[94.8827398, 29.6253184],
[94.8806998, 29.6268686],
[94.8777241, 29.6317051],
[94.8768493, 29.6342436],
[94.8768641, 29.6346894],
[94.8769277, 29.6365972],
[94.8775677, 29.6391137],
[94.8804943, 29.6418187],
[94.8821969, 29.6438716],
[94.8877263, 29.6456718],
[94.8903366, 29.6468971],
[94.8959561, 29.6481151],
[94.9032857, 29.6528729],
[94.9113869, 29.6568592],
[94.9162734, 29.6587881],
[94.9182022, 29.6625172],
[94.9203882, 29.670104],
[94.9197453, 29.6744761],
[94.9192644, 29.6754058],
[94.9178164, 29.6782052],
[94.915116, 29.6816771],
[94.9094581, 29.6810342],
[94.9043145, 29.6796197],
[94.9018712, 29.6806484],
[94.8976278, 29.6812914],
[94.8909411, 29.6856634],
[94.8896552, 29.6890068],
[94.892227, 29.6990368],
[94.8978849, 29.704952],
[94.9017426, 29.7100956],
[94.9061206, 29.7112788],
[94.9065005, 29.7113815],
[94.9225743, 29.7192255],
[94.9264023, 29.7212652],
[94.9267629, 29.7213678],
[94.9341474, 29.723469],
[94.9360823, 29.7245705],
[94.9357152, 29.7273333],
[94.9344915, 29.7289804],
[94.9323502, 29.7303263],
[94.9298621, 29.73339],
[94.9294542, 29.734665],
[94.9298213, 29.7382244],
[94.9306755, 29.739157],
[94.9340021, 29.7439794],
[94.9355331, 29.7464083],
[94.9364901, 29.7488664],
[94.9372115, 29.749423],
[94.937775, 29.7498579],
[94.939019, 29.7500527],
[94.9407117, 29.7501944],
[94.9429346, 29.7513629],
[94.947778, 29.7543307],
[94.9541921, 29.755984],
[94.9574551, 29.7555414],
[94.9603715, 29.7553644],
[94.9629516, 29.755488],
[94.9676317, 29.757489],
[94.9709355, 29.7587814],
[94.9737019, 29.7603278],
[94.9738572, 29.7603796],
[94.9844009, 29.7638941],
[94.9852725, 29.7649069],
[94.9861359, 29.7675568],
[94.9898232, 29.7694497],
[94.9917263, 29.7691954],
[94.9966421, 29.7688099],
[95.0005707, 29.7670075],
[95.0007566, 29.7668999],
[95.0028203, 29.7657056],
[95.0080406, 29.7614995],
[95.0092963, 29.7609572],
[95.0138378, 29.7589957],
[95.0160159, 29.7574362],
[95.0194618, 29.7553902],
[95.0222306, 29.7524106],
[95.024336, 29.7498815],
[95.0273932, 29.7487547],
[95.0324981, 29.7493557],
[95.0339552, 29.7496724],
[95.0346257, 29.7499916],
[95.035882, 29.7507411],
[95.0375964, 29.7530966],
[95.0386203, 29.754818],
[95.0383895, 29.7567272],
[95.038166, 29.7590432],
[95.0395792, 29.7618349],
[95.0411334, 29.7631575],
[95.0420532, 29.7639402],
[95.0467825, 29.7661735],
[95.0495101, 29.7673453],
[95.0510063, 29.7681933],
[95.0516577, 29.7683919],
[95.0560621, 29.7692331],
[95.0577259, 29.7690047],
[95.0588453, 29.7684695],
[95.0650773, 29.767807],
[95.0705737, 29.761782],
[95.0720258, 29.7599696],
[95.0736121, 29.7540856],
[95.0754147, 29.751782],
[95.0758224, 29.751042],
[95.0760619, 29.750314],
[95.0759483, 29.7495284],
[95.0751984, 29.7480135],
[95.0728911, 29.7466988],
[95.0724585, 29.7445327],
[95.0732804, 29.7429802],
[95.0734102, 29.740789],
[95.0731362, 29.7386729],
[95.0744382, 29.7374902],
[95.075294, 29.7367129],
[95.079535, 29.7361346],
[95.081745, 29.736994],
[95.083005, 29.737484],
[95.0833905, 29.7430745],
[95.0844421, 29.7452715],
[95.0871532, 29.7473749],
[95.0918361, 29.7499864],
[95.0931923, 29.7511573],
[95.0943202, 29.7514189],
[95.0965266, 29.7510558],
[95.0991656, 29.7494408],
[95.1029871, 29.7472998],
[95.1038668, 29.7453591],
[95.1063039, 29.7417406],
[95.1084814, 29.741365],
[95.111726, 29.7426671],
[95.1138489, 29.7452914],
[95.1152135, 29.7465013],
[95.1154175, 29.7473556],
[95.1158661, 29.7480506],
[95.1167533, 29.7482586],
[95.1179004, 29.7491572],
[95.119434, 29.7515181],
[95.1195997, 29.7517319],
[95.1214023, 29.7535598],
[95.1239692, 29.754987],
[95.1260602, 29.7556005],
[95.1284973, 29.7561388],
[95.1311663, 29.7559002],
[95.1323477, 29.7559385],
[95.1344757, 29.7564723],
[95.1350155, 29.7583672],
[95.1382746, 29.7617848],
[95.1400377, 29.7646815],
[95.1410982, 29.7654339],
[95.1437689, 29.7649144],
[95.1469991, 29.7640131],
[95.1503617, 29.7622343],
[95.1506908, 29.7620602],
[95.1532721, 29.7600322],
[95.1565312, 29.7590432],
[95.1584059, 29.7594063],
[95.1589059, 29.7599317],
[95.1595043, 29.7612399],
[95.1611602, 29.7632119],
[95.1635565, 29.7646136],
[95.1700434, 29.7649144],
[95.1730828, 29.7644136],
[95.1748094, 29.7636814],
[95.1765005, 29.7628339],
[95.1794885, 29.7589784],
[95.1830673, 29.7576787],
[95.1848212, 29.7580682],
[95.1869103, 29.7594603]
]
}
}
]
}