import { action, makeObservable, observable, reaction } from "mobx"; import { observer } from "mobx-react"; import { Component } from "react"; import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3"; import Ellipsoid from "terriajs-cesium/Source/Core/Ellipsoid"; import CesiumMath from "terriajs-cesium/Source/Core/Math"; import markerIcon from "../../../../wwwroot/images/difference-pin.png"; import LatLonHeight from "../../../Core/LatLonHeight"; import PickedFeatures from "../../../Map/PickedFeatures/PickedFeatures"; import { addMarker, removeMarker } from "../../../Models/LocationMarkerUtils"; import MapInteractionMode, { UIMode } from "../../../Models/MapInteractionMode"; import Terria from "../../../Models/Terria"; import Loader from "../../Loader"; interface PropsType { terria: Terria; location?: LatLonHeight; onPicking: (pickingLocation: LatLonHeight) => void; onPicked: ( pickedFeatures: PickedFeatures, pickedLocation: LatLonHeight ) => void; } @observer export default class LocationPicker extends Component { @observable private pickMode?: MapInteractionMode; @observable private currentPick?: PickedFeatures; @observable private pickDisposer?: () => void; constructor(props: PropsType) { super(props); makeObservable(this); } @action setupPicker() { const { terria, location, onPicking, onPicked } = this.props; this.pickMode = new MapInteractionMode({ message: "", messageAsNode:
, uiMode: UIMode.Difference }); addInteractionModeToMap(terria, this.pickMode); if (location) showMarker(terria, location); this.pickDisposer = reaction( () => this.pickMode!.pickedFeatures, action((newPick: PickedFeatures | undefined) => { if (newPick === undefined || newPick.pickPosition === undefined) { return; } this.pickMode!.customUi = () => ( ); const position = cartesianToDegrees(newPick.pickPosition); showMarker(this.props.terria, position); this.currentPick = newPick; onPicking(position); newPick.allFeaturesAvailablePromise?.then(() => { if (newPick === this.currentPick) { onPicked(newPick, position); } }); }) ); } @action destroyPicker() { const { terria } = this.props; if (this.pickMode) { removeInteractionModeFromMap(terria, this.pickMode); } removeMarker(terria); this.pickMode = undefined; this.currentPick = undefined; this.pickDisposer?.(); this.pickDisposer = undefined; } componentDidMount() { this.setupPicker(); } componentDidUpdate() { this.destroyPicker(); this.setupPicker(); } componentWillUnmount() { this.destroyPicker(); } render() { return null; } } function addInteractionModeToMap(terria: Terria, mode: MapInteractionMode) { terria.mapInteractionModeStack.push(mode); } function removeInteractionModeFromMap( terria: Terria, mode: MapInteractionMode ) { const [currentMode] = terria.mapInteractionModeStack.slice(-1); if (currentMode === mode) { terria.mapInteractionModeStack.pop(); } } function showMarker(terria: Terria, location: LatLonHeight) { addMarker(terria, { name: "User selection", location, customMarkerIcon: markerIcon }); } function cartesianToDegrees(cartesian: Cartesian3) { const carto = Ellipsoid.WGS84.cartesianToCartographic(cartesian); return { longitude: CesiumMath.toDegrees(carto.longitude), latitude: CesiumMath.toDegrees(carto.latitude) }; }