reszta poprawek
This commit is contained in:
@@ -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">© 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]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user