Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1 #12

Merged
merged 3 commits into from
Dec 8, 2024
Merged

v1.1 #12

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 64 additions & 22 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from 'react';
import { useUamInstanceStore } from './uam/uamInstance';
import UCSViewer from './viewer/UCSViewer';
import styled from 'styled-components';
Expand All @@ -6,41 +7,82 @@ import UCSInfoPanel from './viewer/UCSInfopanel';
import PathInfoPanel from './viewer/PathInfoPanel';
import { pathCoordinates } from './path/pathCoordinates';

const AppContainer = styled.div`
display: flex;
flex-direction: column; /* 세로로 배치 */
height: 100vh;
`;

const ViewerSection = styled.div`
display: flex;
flex: 1; /* 화면의 나머지 공간 차지 */
overflow: hidden; /* 필요 시 넘치는 내용 숨김 */
`;

const PathInfoContainer = styled.div`
height: 20vh; /* 하단에 고정된 높이 */
width: 100%; /* 가로 전체 */
background-color: #1e1e1e;
const MenuSection = styled.div`
display: flex;
flex-direction: column;
`;

const InfoPanelSection = styled.div`
display: flex;
flex: 1;
`;

const ButtonSection = styled.div`
display: flex;
height: 3rem;
justify-content: space-evenly;
align-items: center;
width: 100%;
`;

interface StyledButtonProps
extends Omit<React.HTMLAttributes<HTMLLIElement>, '$active'> {
$active: boolean;
}

const StyledButton = styled.button<StyledButtonProps>`
display: flex;
flex: 1; /* 버튼이 섹션 전체를 고르게 차지 */
height: 3rem;
justify-content: center;
align-items: center;
border-radius: 1.25rem 1.25rem 0rem 0rem;
border-top: 2px solid rgba(255, 255, 255, 0.5);
background-color: ${(props) =>
props.$active ? '#1e1e1e' : 'black'}; /* 활성 상태에 따른 색상 변경 */
color: white; /* 텍스트 색상 변경 */
`;

export default function App() {
const { uamInstances } = useUamInstanceStore();
const [activePanel, setActivePanel] = useState('UCS'); // UCS 또는 Path

return (
<ViewerProvider>
<AppContainer>
{/* Viewer와 InfoPanel */}
<ViewerSection>
<UCSViewer />
<UCSInfoPanel uamInstances={uamInstances} />
</ViewerSection>

{/* PathInfoPanel */}
<PathInfoContainer>
<PathInfoPanel pathCount={pathCoordinates.length} />
</PathInfoContainer>
</AppContainer>
{/* Viewer와 InfoPanel */}
<ViewerSection>
<UCSViewer />
<MenuSection>
<ButtonSection>
<StyledButton
$active={activePanel === 'UCS'}
onClick={() => setActivePanel('UCS')}
>
UAM 정보
</StyledButton>
<StyledButton
$active={activePanel === 'Path'}
onClick={() => setActivePanel('Path')}
>
경로
</StyledButton>
</ButtonSection>
<InfoPanelSection>
{activePanel === 'UCS' && (
<UCSInfoPanel uamInstances={uamInstances} />
)}
{activePanel === 'Path' && (
<PathInfoPanel pathCount={pathCoordinates.length} />
)}
</InfoPanelSection>
</MenuSection>
</ViewerSection>
</ViewerProvider>
);
}
2 changes: 1 addition & 1 deletion src/path/PathController.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import { useMemo } from 'react';
import PathEntity from './PathEntity';
import { pathCoordinates } from './pathCoordinates';
import { Color } from 'cesium';
Expand Down
11 changes: 8 additions & 3 deletions src/uam/UamEntity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
JulianDate,
Resource,
SampledPositionProperty,
VelocityOrientationProperty,
} from 'cesium';
import { useEffect, useState } from 'react';
import { Entity, ModelGraphics } from 'resium';
Expand Down Expand Up @@ -59,15 +60,19 @@ const UamEntity: React.FC<UamProp> = ({ id }: UamProp) => {

useEffect(() => {
const loadModelUri = async () => {
const uri = await IonResource.fromAssetId(2852225);
const uri = await IonResource.fromAssetId(2808773);
setModelUri(uri);
};
loadModelUri();
}, []);

return (
<Entity id={`uam-${id}`} position={wayPoints}>
{modelUri && <ModelGraphics uri={modelUri} scale={10.0} />}
<Entity
id={`uam-${id}`}
position={wayPoints}
orientation={new VelocityOrientationProperty(wayPoints)}
>
{modelUri && <ModelGraphics uri={modelUri} scale={8.0} />}
</Entity>
);
};
Expand Down
21 changes: 14 additions & 7 deletions src/viewer/PathInfoPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from 'styled-components';
import { useState } from 'react';

const InfoPanel = styled.div`
width: 100%; /* 가로 전체 */
width: 21rem; /* 가로 전체 */
background-color: #1e1e1e;
font-family: Arial, sans-serif;
color: #fff;
Expand All @@ -15,13 +15,12 @@ const InfoPanel = styled.div`
const PathList = styled.ul`
list-style: none;
padding: 0;
margin: 1rem 0 0 0;
border-top: 1px solid #333;
`;

const PathItem = styled.li<{ $isSelected: boolean }>`
padding: 0.5rem 1rem;
cursor: pointer;
border: white;
background-color: ${({ $isSelected }) =>
$isSelected ? '#555' : 'transparent'};
color: ${({ $isSelected }) => ($isSelected ? '#fff' : '#ccc')};
Expand Down Expand Up @@ -80,17 +79,25 @@ const PathInfoPanel: React.FC<PathInfoPanelProps> = ({ pathCount }) => {
textAlign: 'center',
margin: '1rem 0',
}}
>
경로 목록
</div>
></div>
<PathList>
<PathItem
onClick={() => {
for (let index = 0; index < pathCount; index++) {
handlePathClick(index);
}
}}
$isSelected={false}
>
Route 전체 조회
</PathItem>
{Array.from({ length: pathCount }, (_, i) => (
<PathItem
key={`path-${i}`}
onClick={() => handlePathClick(i)}
$isSelected={visiblePaths.includes(i)}
>
{i} 번 노선
Route {i + 1}
</PathItem>
))}
</PathList>
Expand Down
7 changes: 4 additions & 3 deletions src/viewer/UCSInfopanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@ const UCSInfoPanel: React.FC<UamInfoPanelProps> = ({ uamInstances }) => {
textAlign: 'center',
margin: '1rem 0',
}}
>
현재 비행중인 UAM
</div>
></div>
<InstanceList>
{uamInstances.map((uamId) => {
const uam = uamData.find((data) => data.id === uamId);
Expand All @@ -139,6 +137,9 @@ const UCSInfoPanel: React.FC<UamInfoPanelProps> = ({ uamInstances }) => {
위치: {uam.buildingName || '위치 정보를 불러오는 중...'}
</div>
<div>고도: {uam.altitude.toFixed(1)} m</div>
<div>
속력 {CesiumMath.randomBetween(35, 39).toFixed(2)}km/h
</div>
</>
) : (
<div>위치 정보를 불러오는 중...</div>
Expand Down
1 change: 0 additions & 1 deletion src/viewer/UCSViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export default function UCSViewer() {
<Clock startTime={start.clone()} shouldAnimate={true} />
<CameraFlyTo destination={homePosition} duration={0} once />
<Cesium3DTileset url={IonResource.fromAssetId(2275207)} />
<Cesium3DTileset url={IonResource.fromAssetId(96188)} />
<UamController />
<PathController />
</CustomViewer>
Expand Down
72 changes: 72 additions & 0 deletions src/wasm/uam_control_system_wasm.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* tslint:disable */
/* eslint-disable */
export class UAM {
free(): void;
/**
* @param {number} lat
* @param {number} lon
* @param {number} alt
* @param {number} vx
* @param {number} vy
* @param {number} vz
* @returns {UAM}
*/
static new(lat: number, lon: number, alt: number, vx: number, vy: number, vz: number): UAM;
/**
* @param {UAM} other
* @returns {number | undefined}
*/
predict_collision(other: UAM): number | undefined;
}
export class UAMs {
free(): void;
/**
* @returns {UAMs}
*/
static new(): UAMs;
/**
* @param {UAM} uam
*/
add(uam: UAM): void;
/**
* @returns {any}
*/
predict_collisions(): any;
}

export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;

export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly __wbg_uam_free: (a: number, b: number) => void;
readonly __wbg_uams_free: (a: number, b: number) => void;
readonly uam_new: (a: number, b: number, c: number, d: number, e: number, f: number) => number;
readonly uam_predict_collision: (a: number, b: number, c: number) => void;
readonly uams_new: () => number;
readonly uams_add: (a: number, b: number) => void;
readonly uams_predict_collisions: (a: number) => number;
readonly __wbindgen_malloc: (a: number, b: number) => number;
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
}

export type SyncInitInput = BufferSource | WebAssembly.Module;
/**
* Instantiates the given `module`, which can either be bytes or
* a precompiled `WebAssembly.Module`.
*
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
*
* @returns {InitOutput}
*/
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;

/**
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
* for everything else, calls `WebAssembly.instantiate` directly.
*
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
*
* @returns {Promise<InitOutput>}
*/
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
Loading
Loading