Skip to content

Commit

Permalink
chore(web): extend camera and marker APIs for pedestrian (#859)
Browse files Browse the repository at this point in the history
  • Loading branch information
keiya01 committed Dec 14, 2023
1 parent d8d9f34 commit 1d35d9d
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 6 deletions.
9 changes: 9 additions & 0 deletions web/src/beta/lib/core/Crust/Plugins/api.ts
Expand Up @@ -428,6 +428,9 @@ export function commonReearth({
captureScreen,
getLocationFromScreen,
sampleTerrainHeight,
computeGlobeHeight,
toXYZ,
toLngLatHeight,
enableScreenSpaceCameraController,
lookHorizontal,
lookVertical,
Expand Down Expand Up @@ -475,6 +478,9 @@ export function commonReearth({
captureScreen: GlobalThis["reearth"]["scene"]["captureScreen"];
getLocationFromScreen: GlobalThis["reearth"]["scene"]["getLocationFromScreen"];
sampleTerrainHeight: GlobalThis["reearth"]["scene"]["sampleTerrainHeight"];
computeGlobeHeight: GlobalThis["reearth"]["scene"]["computeGlobeHeight"];
toXYZ: GlobalThis["reearth"]["scene"]["toXYZ"];
toLngLatHeight: GlobalThis["reearth"]["scene"]["toLngLatHeight"];
inEditor: () => GlobalThis["reearth"]["scene"]["inEditor"];
built: () => GlobalThis["reearth"]["scene"]["built"];
enableScreenSpaceCameraController: GlobalThis["reearth"]["camera"]["enableScreenSpaceController"];
Expand Down Expand Up @@ -548,6 +554,9 @@ export function commonReearth({
captureScreen,
getLocationFromScreen,
sampleTerrainHeight,
computeGlobeHeight,
toXYZ,
toLngLatHeight,
pickManyFromViewport,
},
get viewport() {
Expand Down
45 changes: 45 additions & 0 deletions web/src/beta/lib/core/Crust/Plugins/hooks.ts
Expand Up @@ -228,6 +228,45 @@ export default function ({
[engineRef],
);

const computeGlobeHeight = useCallback(
(lng: number, lat: number, height?: number) => {
return engineRef?.computeGlobeHeight(lng, lat, height);
},
[engineRef],
);

const toXYZ = useCallback(
(
lng: number,
lat: number,
height: number,
options?:
| {
useGlobeEllipsoid?: boolean | undefined;
}
| undefined,
) => {
return engineRef?.toXYZ(lng, lat, height, options);
},
[engineRef],
);

const toLngLatHeight = useCallback(
(
x: number,
y: number,
z: number,
options?:
| {
useGlobeEllipsoid?: boolean | undefined;
}
| undefined,
) => {
return engineRef?.toLngLatHeight(x, y, z, options);
},
[engineRef],
);

const enableScreenSpaceCameraController = useCallback(
(enabled: boolean) => engineRef?.enableScreenSpaceCameraController(enabled),
[engineRef],
Expand Down Expand Up @@ -404,6 +443,9 @@ export default function ({
zoomOut,
cameraViewport,
getCameraFovInfo,
computeGlobeHeight,
toXYZ,
toLngLatHeight,
rotateRight,
orbit,
captureScreen,
Expand Down Expand Up @@ -466,6 +508,9 @@ export default function ({
getLocationFromScreen,
sampleTerrainHeight,
enableScreenSpaceCameraController,
computeGlobeHeight,
toXYZ,
toLngLatHeight,
lookHorizontal,
lookVertical,
moveForward,
Expand Down
13 changes: 13 additions & 0 deletions web/src/beta/lib/core/Crust/Plugins/plugin_types.ts
Expand Up @@ -128,6 +128,19 @@ export type Scene = {
withTerrain?: boolean,
) => LatLngHeight | undefined;
readonly sampleTerrainHeight: (lng: number, lat: number) => Promise<number | undefined>;
readonly computeGlobeHeight: (lng: number, lat: number, height?: number) => number | undefined;
readonly toXYZ: (
lng: number,
lat: number,
height: number,
options?: { useGlobeEllipsoid?: boolean },
) => [x: number, y: number, z: number] | undefined;
readonly toLngLatHeight: (
x: number,
y: number,
z: number,
options?: { useGlobeEllipsoid?: boolean },
) => [lng: number, lat: number, height: number] | undefined;
readonly pickManyFromViewport: (
windowPosition: [x: number, y: number],
windowWidth: number,
Expand Down
4 changes: 4 additions & 0 deletions web/src/beta/lib/core/Crust/Plugins/storybook.tsx
Expand Up @@ -94,6 +94,9 @@ export const context: Context = {
captureScreen: act("captureScreen"),
getLocationFromScreen: act("getLocationFromScreen"),
sampleTerrainHeight: act("sampleTerrainHeight"),
computeGlobeHeight: act("computeGlobeHeight"),
toXYZ: act("toXYZ"),
toLngLatHeight: act("toLngLatHeight"),
pickManyFromViewport: act("pickManyFromViewport"),
},
layers: {
Expand Down Expand Up @@ -124,6 +127,7 @@ export const context: Context = {
pitch: 0,
roll: 0,
fov: Math.PI * (60 / 180),
aspectRatio: 1,
},
viewport: { west: 0, east: 0, north: 0, south: 0 },
getFovInfo: act("getFovInfo"),
Expand Down
3 changes: 3 additions & 0 deletions web/src/beta/lib/core/Map/ref.ts
Expand Up @@ -23,6 +23,9 @@ const engineRefKeys: FunctionKeys<EngineRef> = {
getClock: 1,
getLocationFromScreen: 1,
sampleTerrainHeight: 1,
computeGlobeHeight: 1,
toXYZ: 1,
toLngLatHeight: 1,
getViewport: 1,
lookAt: 1,
lookAtLayer: 1,
Expand Down
13 changes: 13 additions & 0 deletions web/src/beta/lib/core/Map/types/index.ts
Expand Up @@ -73,6 +73,19 @@ export type EngineRef = {
| undefined;
getLocationFromScreen: (x: number, y: number, withTerrain?: boolean) => LatLngHeight | undefined;
sampleTerrainHeight: (lng: number, lat: number) => Promise<number | undefined>;
computeGlobeHeight: (lng: number, lat: number, height?: number) => number | undefined;
toXYZ: (
lng: number,
lat: number,
height: number,
options?: { useGlobeEllipsoid?: boolean },
) => [x: number, y: number, z: number] | undefined;
toLngLatHeight: (
x: number,
y: number,
z: number,
options?: { useGlobeEllipsoid?: boolean },
) => [lng: number, lat: number, height: number] | undefined;
flyTo: FlyTo;
lookAt: (destination: LookAtDestination, options?: CameraOptions) => void;
lookAtLayer: (layerId: string) => void;
Expand Down
20 changes: 17 additions & 3 deletions web/src/beta/lib/core/engines/Cesium/Feature/Marker/index.tsx
Expand Up @@ -68,6 +68,8 @@ export default function Marker({ property, id, isVisible, geometry, layer, featu
imageShadowBlur: shadowBlur,
imageShadowPositionX: shadowOffsetX,
imageShadowPositionY: shadowOffsetY,
eyeOffset,
pixelOffset,
heightReference: hr,
} = property ?? {};

Expand Down Expand Up @@ -98,7 +100,17 @@ export default function Marker({ property, id, isVisible, geometry, layer, featu
shadowOffsetY,
});

const pixelOffset = useMemo(() => {
const cartPixelOffset = useMemo(
() => (pixelOffset ? new Cartesian2(...pixelOffset) : undefined),
[pixelOffset],
);
const cartEyeOffset = useMemo(
() => (eyeOffset ? new Cartesian3(...eyeOffset) : undefined),
[eyeOffset],
);

const labelPixelOffset = useMemo(() => {
if (cartPixelOffset) return cartPixelOffset;
const padding = 15;
const x = (isStyleImage ? imgw : pointSize) / 2 + padding;
const y = (isStyleImage ? imgh : pointSize) / 2 + padding;
Expand All @@ -110,7 +122,7 @@ export default function Marker({ property, id, isVisible, geometry, layer, featu
? y * (labelPos.includes("top") ? -1 : 1)
: 0,
);
}, [isStyleImage, imgw, pointSize, imgh, labelPos]);
}, [isStyleImage, imgw, pointSize, imgh, labelPos, cartPixelOffset]);

const extrudePointsLineColor = useMemo(() => {
return Color.WHITE.withAlpha(0.4);
Expand Down Expand Up @@ -186,6 +198,8 @@ export default function Marker({ property, id, isVisible, geometry, layer, featu
heightReference={heightReference(hr)}
distanceDisplayCondition={distanceDisplayCondition}
sizeInMeters={imageSizeInMeters}
pixelOffset={cartPixelOffset}
eyeOffset={cartEyeOffset}
/>
)}
{label && (
Expand All @@ -204,7 +218,7 @@ export default function Marker({ property, id, isVisible, geometry, layer, featu
? VerticalOrigin.BOTTOM
: VerticalOrigin.CENTER
}
pixelOffset={pixelOffset}
pixelOffset={labelPixelOffset}
fillColor={labelColorCesium}
font={toCSSFont(labelTypography, { fontSize: 30 })}
text={stringLabelText}
Expand Down
12 changes: 9 additions & 3 deletions web/src/beta/lib/core/engines/Cesium/common.ts
Expand Up @@ -313,6 +313,8 @@ export const lookAt = (
range?: number;
/** Field of view expressed in radians */
fov?: number;
/** Radius of bounding sphere */
radius?: number;
},
options?: {
/** Seconds */
Expand All @@ -337,8 +339,11 @@ export const lookAt = (
: undefined;

if (position) {
cesiumCamera.flyToBoundingSphere(new BoundingSphere(position), {
offset: new HeadingPitchRange(camera.heading, camera.pitch, camera.range),
cesiumCamera.flyToBoundingSphere(new BoundingSphere(position, camera.radius), {
offset:
camera.heading !== undefined || camera.pitch !== undefined || camera.range !== undefined
? new HeadingPitchRange(camera.heading, camera.pitch, camera.range)
: undefined,
duration: options?.duration,
easingFunction: options?.easing,
});
Expand Down Expand Up @@ -496,7 +501,8 @@ export const getCamera = (viewer: Viewer | CesiumWidget | undefined): Camera | u
const lng = CesiumMath.toDegrees(longitude);
const { heading, pitch, roll } = camera;
const fov = camera.frustum instanceof PerspectiveFrustum ? camera.frustum.fov : 1;
return { lng, lat, height, heading, pitch, roll, fov };
const aspectRatio = camera.frustum instanceof PerspectiveFrustum ? camera.frustum.aspectRatio : 1;
return { lng, lat, height, heading, pitch, roll, fov, aspectRatio };
};

export const getClock = (clock: CesiumClock | undefined): Clock | undefined => {
Expand Down
29 changes: 29 additions & 0 deletions web/src/beta/lib/core/engines/Cesium/useEngineRef.ts
Expand Up @@ -121,6 +121,35 @@ export default function useEngineRef(
if (!viewer || viewer.isDestroyed()) return;
return await sampleTerrainHeight(viewer.scene, lng, lat);
},
computeGlobeHeight: (lng, lat, height) => {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;
return viewer.scene.globe.getHeight(Cesium.Cartographic.fromDegrees(lng, lat, height));
},
toXYZ: (lng, lat, height, options) => {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;
const cartesian = Cesium.Cartesian3.fromDegrees(
lng,
lat,
height,
options?.useGlobeEllipsoid ? viewer.scene.globe.ellipsoid : undefined,
);
return [cartesian.x, cartesian.y, cartesian.z];
},
toLngLatHeight: (x, y, z, options) => {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;
const cart = Cesium.Cartographic.fromCartesian(
Cesium.Cartesian3.fromElements(x, y, z),
options?.useGlobeEllipsoid ? viewer.scene.globe.ellipsoid : undefined,
);
return [
CesiumMath.toDegrees(cart.longitude),
CesiumMath.toDegrees(cart.latitude),
cart.height,
];
},
flyTo: (target, options) => {
if (target && typeof target === "object") {
const viewer = cesium.current?.cesiumElement;
Expand Down
2 changes: 2 additions & 0 deletions web/src/beta/lib/core/mantle/compat/types.ts
Expand Up @@ -77,6 +77,8 @@ export type CameraPosition = {
roll: number;
/** Field of view expressed in radians */
fov: number;
/** Aspect ratio of frustum */
aspectRatio?: number;
};

export type Typography = {
Expand Down
2 changes: 2 additions & 0 deletions web/src/beta/lib/core/mantle/types/appearance.ts
Expand Up @@ -70,6 +70,8 @@ export type MarkerAppearance = {
extrude?: boolean;
near?: number;
far?: number;
pixelOffset?: [number, number];
eyeOffset?: [number, number, number];
};

export type PolylineAppearance = {
Expand Down
1 change: 1 addition & 0 deletions web/src/beta/lib/core/mantle/types/value.ts
Expand Up @@ -17,6 +17,7 @@ export type Camera = {
pitch: number;
roll: number;
fov: number;
aspectRatio?: number;
};

export type Typography = {
Expand Down
2 changes: 2 additions & 0 deletions web/src/beta/lib/core/types.ts
Expand Up @@ -39,4 +39,6 @@ export type LookAtDestination = {
range?: number;
/** Radian */
fov?: number;
/** Meters */
radius?: number;
};

0 comments on commit 1d35d9d

Please sign in to comment.