From 38bbc2adf716e97d0139854ac66d75409fa4855d Mon Sep 17 00:00:00 2001 From: Eliav Maimon Date: Thu, 12 Feb 2026 15:07:48 +0200 Subject: [PATCH] feat: add cesium poi --- .../Wizard/ModelSelection/ModelSelection.tsx | 11 ++- src/utils/Cesium/CesiumPOI/CesiumPOI.css | 11 +++ src/utils/Cesium/CesiumPOI/CesiumPOI.tsx | 63 +++++++++++++++ src/utils/Cesium/LocationMarker.tsx | 79 +++++++++++++++++++ 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 src/utils/Cesium/CesiumPOI/CesiumPOI.css create mode 100644 src/utils/Cesium/CesiumPOI/CesiumPOI.tsx create mode 100644 src/utils/Cesium/LocationMarker.tsx diff --git a/src/components/Wizard/ModelSelection/ModelSelection.tsx b/src/components/Wizard/ModelSelection/ModelSelection.tsx index aafba23..357434e 100644 --- a/src/components/Wizard/ModelSelection/ModelSelection.tsx +++ b/src/components/Wizard/ModelSelection/ModelSelection.tsx @@ -17,10 +17,14 @@ import { CatalogTreeNode, IDENTIFIER_FIELD, WizardSelectionProps } from '../Wiza import './ModelSelection.css'; import { CesiumGeojsonFootprint } from './CesiumGeojsonFootprint'; +import { LocationMarker } from '../../../utils/Cesium/LocationMarker'; +import { CesiumPOI } from '../../../utils/Cesium/CesiumPOI/CesiumPOI'; export const ModelSelection: React.FC = (props) => { const [isLoading, setIsLoading] = useState(true); const [finishedFlying, setFinishedFlying] = useState(false); + // const [poi, setPoi] = useState(undefined); + // const [poi, setPoi] = useState(undefined); const treeTheme = { "--rst-selected-background-color": '#f8fafc33', @@ -53,8 +57,8 @@ export const ModelSelection: React.FC = (props) => { } (async () => { - const treeData = await fetchCatalog((value: boolean)=>{ - setTimeout( () => setIsLoading(value), 2000); + const treeData = await fetchCatalog((value: boolean) => { + setTimeout(() => setIsLoading(value), 2000); }); props.setCatalogTreeData(treeData.data.children as CatalogTreeNode[]); @@ -88,7 +92,7 @@ export const ModelSelection: React.FC = (props) => { { - isLoading && + isLoading && } { props.catalogTreeData && @@ -128,6 +132,7 @@ export const ModelSelection: React.FC = (props) => { isZoomTo={true} /> } + diff --git a/src/utils/Cesium/CesiumPOI/CesiumPOI.css b/src/utils/Cesium/CesiumPOI/CesiumPOI.css new file mode 100644 index 0000000..9c2b3e2 --- /dev/null +++ b/src/utils/Cesium/CesiumPOI/CesiumPOI.css @@ -0,0 +1,11 @@ +#CesiumPOI { + position: absolute; + border: solid 1px red; + right: 20px; + background-color: black; +} + +#CesiumPOI .small { + height: 50px; + width: 50px; +} \ No newline at end of file diff --git a/src/utils/Cesium/CesiumPOI/CesiumPOI.tsx b/src/utils/Cesium/CesiumPOI/CesiumPOI.tsx new file mode 100644 index 0000000..e872d86 --- /dev/null +++ b/src/utils/Cesium/CesiumPOI/CesiumPOI.tsx @@ -0,0 +1,63 @@ +import { TextField } from "@map-colonies/react-core" +import { LocationMarker } from "../LocationMarker" +import { useEffect, useState } from "react" +import { Box } from "@map-colonies/react-components"; + +import './CesiumPOI.css'; + +// interface CesiumGeojsonFootprintProps { + +// } + +const LONGITUDE_INDEX = 0; +const LATITUDE_INDEX = 2; + +export const CesiumPOI: React.FC = () => { + const [longitude, setLongitude] = useState(); + const [latitude, setLatitude] = useState(); + const [inputValue, setInputValue] = useState(""); + + const regex = /^(-?(?:[0-8]?\d(?:\.\d+)?|90(?:\.0+)?)),\s*(-?(?:1[0-7]\d(?:\.\d+)?|[0-9]?\d(?:\.\d+)?|180(?:\.0+)?))/; + + const isValid = + typeof longitude === "number" && + typeof latitude === "number"; + + return ( + + ): void => { + const val = e.currentTarget.value; + setInputValue(val); + const matches = val.match(regex); + + if (matches) { + const lat = parseFloat(matches[LATITUDE_INDEX]); + const lon = parseFloat(matches[LONGITUDE_INDEX]); + + setLatitude(lat); + setLongitude(lon); + } else { + setLatitude(undefined); + setLongitude(undefined); + } + } + } + /> + {/* for height in the future */} + + { + isValid && + + } + + ) +} diff --git a/src/utils/Cesium/LocationMarker.tsx b/src/utils/Cesium/LocationMarker.tsx new file mode 100644 index 0000000..93d15ef --- /dev/null +++ b/src/utils/Cesium/LocationMarker.tsx @@ -0,0 +1,79 @@ +import React, { useEffect, useState } from 'react'; +import { useIntl } from 'react-intl'; +import { isEmpty } from 'lodash'; +import { + CesiumCartesian3, + CesiumCartographic, + CesiumColor, + CesiumEntity, + CesiumHeightReference, + cesiumSampleTerrainMostDetailed, + CesiumVerticalOrigin, + useCesiumMap +} from '@map-colonies/react-components'; +import { FlyTo } from './FlyTo'; + +interface PoiEntityProps { + longitude: number; + latitude: number; +} + +// export interface IPOI { +// lon: number; +// lat: number; +// } + +export const LocationMarker: React.FC = ({ longitude, latitude }) => { + // const longitude = 52.01053; + // const latitude = 36.50835; + // const intl = useIntl(); + const mapViewer = useCesiumMap(); + const [position, setPosition] = useState(); + // const [height, setHeight] = useState(DEFAULT_HEIGHT); + + useEffect(() => { + // setTimeout(() => { + if (!mapViewer) return; + + const cartographic = CesiumCartographic.fromDegrees(longitude, latitude); + const height = mapViewer.scene.sampleHeight(cartographic); + + console.log('height', height) + const finalHeight = height || 0; + + setPosition( + CesiumCartesian3.fromDegrees(longitude, latitude, finalHeight) + ); + // }, 20000); + }, [mapViewer, latitude, longitude]); + + return ( + <> + { + position !== undefined && + + // ${intl.formatMessage({ id: 'poi.dialog.description.latitude' }, { value: latitude })}
+ // ${intl.formatMessage({ id: 'poi.dialog.description.height' }, { value: height })} + // `} + /> + } + + ); +}; \ No newline at end of file