UNPKG

@itwin/geonames-extension

Version:

Geolocation Extension

191 lines 10.1 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.GeoNameExtension = exports.GeoNameMarkerManager = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); const core_frontend_1 = require("@itwin/core-frontend"); const core_geometry_1 = require("@itwin/core-geometry"); /** Marker positioned where there is a geographic entity. */ class GeoNameMarker extends core_frontend_1.Marker { constructor(location, props, icon) { super(location, GeoNameMarker._size); this.props = props; this.setImage(icon); // save icon this.imageSize = GeoNameMarker._imageSize; // 40x40 // set the tooltip when promise resolves. We won't need it for a while anyway. this.setScaleFactor({ low: 1, high: 1 }); // no size dependence for now. this.labelOffset = { x: 0, y: -24 }; this.title = props.name; if (props.population) this.title = `${this.title} (${core_frontend_1.IModelApp.localization.getLocalizedString("geoNames:misc.Population")}: ${props.population})`; // it would be better to use "this.label" here for a pure text string. We'll do it this way just to show that you can use HTML too // this.htmlElement = document.createElement("div"); // this.htmlElement.innerHTML = props.name; // put the name of the location. this.label = props.name; } onMouseButton(ev) { if (core_frontend_1.InputSource.Mouse === ev.inputSource && ev.isDown && ev.viewport !== undefined && ev.viewport.view instanceof core_frontend_1.ViewState3d) { if (core_frontend_1.BeButton.Data === ev.button) { const evViewport = ev.viewport; (async () => { await evViewport.animateFlyoverToGlobalLocation({ center: core_common_1.Cartographic.fromRadians({ longitude: this.props.lng * core_geometry_1.Angle.radiansPerDegree, latitude: this.props.lat * core_geometry_1.Angle.radiansPerDegree }) }); })().catch(() => { }); } else if (core_frontend_1.BeButton.Reset === ev.button && undefined !== this.props.wikipedia && 0 !== this.props.wikipedia.length) window.open(`https://${this.props.wikipedia}`); } return true; } } GeoNameMarker._size = core_geometry_1.Point2d.create(20, 20); GeoNameMarker._imageSize = core_geometry_1.Point2d.create(30, 30); class GeoNameMarkerSet extends core_frontend_1.MarkerSet { constructor() { super(...arguments); this.minimumClusterSize = 5; } getClusterMarker(cluster) { return new core_frontend_1.Marker(cluster.getClusterLocation(), cluster.markers[0].size); } } class GeoNameMarkerManager { constructor(vp, _cityMarkerImage, _cityCount = 50) { this._cityMarkerImage = _cityMarkerImage; this._cityCount = _cityCount; this._markerSet = new GeoNameMarkerSet(vp); } decorate(context) { if (this._markerSet !== undefined) this._markerSet.addDecoration(context); } synch(viewport) { const currentViewport = this._markerSet.viewport; if (currentViewport !== viewport) this._markerSet.changeViewport(viewport); const view = viewport.view; const worldFrust = viewport.getFrustum(); const longLatRange = core_geometry_1.Range2d.createNull(); for (const corner of worldFrust.points) { const carto = view.rootToCartographic(corner); if (undefined !== carto) longLatRange.extendXY(carto.longitude, carto.latitude); } this.doCitySearch(longLatRange, this._cityCount).then((cities) => { if (cities !== undefined) { for (const city of cities) { GeoNameMarkerManager._scratchCarto.longitude = city.lng * core_geometry_1.Angle.radiansPerDegree; GeoNameMarkerManager._scratchCarto.latitude = city.lat * core_geometry_1.Angle.radiansPerDegree; this._markerSet.markers.add(new GeoNameMarker(view.cartographicToRoot(GeoNameMarkerManager._scratchCarto, GeoNameMarkerManager._scratchPoint), city, this._cityMarkerImage)); } this._markerSet.markDirty(); core_frontend_1.IModelApp.viewManager.invalidateDecorationsAllViews(); core_frontend_1.IModelApp.requestNextAnimation(); } }).catch(() => { }); } // Load one image, logging if there was an error static async loadImage(src) { try { return await (0, core_frontend_1.imageElementFromUrl)(src); // note: "return await" is necessary inside try/catch } catch (err) { core_bentley_1.Logger.logError("SectionLocationSetDecoration", `Could not load image ${src}`); } return undefined; } outputInfoMessage(messageKey) { const message = core_frontend_1.IModelApp.localization.getLocalizedString(`geoNames:messages.${messageKey}`); const msgDetails = new core_frontend_1.NotifyMessageDetails(core_frontend_1.OutputMessagePriority.Info, message); core_frontend_1.IModelApp.notifications.outputMessage(msgDetails); } radiansToString(radians) { return (radians * core_geometry_1.Angle.degreesPerRadian).toFixed(5); } async doCitySearch(longLatRange, cityCount) { const urlTemplate = "http://api.geonames.org/citiesJSON?&north={north}&south={south}&east={east}&west={west}&lang=en&username=BentleySystems&maxRows={count}"; const url = urlTemplate.replace("{west}", this.radiansToString(longLatRange.low.x)).replace("{south}", this.radiansToString(longLatRange.low.y)).replace("{east}", this.radiansToString(longLatRange.high.x)).replace("{north}", this.radiansToString(longLatRange.high.y)).replace("{count}", cityCount.toString()); try { this.outputInfoMessage("LoadingLocations"); let json = await fetch(url, { method: "GET", headers: { "Content-Type": "application/json", // eslint-disable-line @typescript-eslint/naming-convention }, }); json = json.json(); const cities = new Array(); for (const geoName of json.geonames) { cities.push(geoName); } this.outputInfoMessage("LoadingComplete"); return cities; } catch (error) { return undefined; } } /** Start showing markers if not currently active (or optionally refresh when currently displayed). */ static async show(vp) { if (undefined === GeoNameMarkerManager.decorator) { const cityMarkerImage = await this.loadImage("./city.ico"); if (undefined === cityMarkerImage) return; // No point continuing if we don't have a marker image to show... GeoNameMarkerManager.decorator = new GeoNameMarkerManager(vp, cityMarkerImage); core_frontend_1.IModelApp.viewManager.addDecorator(GeoNameMarkerManager.decorator); } GeoNameMarkerManager.decorator.synch(vp); } static clear(_vp) { if (undefined !== GeoNameMarkerManager.decorator) { core_frontend_1.IModelApp.viewManager.dropDecorator(GeoNameMarkerManager.decorator); GeoNameMarkerManager.decorator = undefined; } } static update(vp) { if (undefined !== GeoNameMarkerManager.decorator) { GeoNameMarkerManager.decorator.synch(vp); } } } exports.GeoNameMarkerManager = GeoNameMarkerManager; GeoNameMarkerManager._scratchCarto = core_common_1.Cartographic.createZero(); GeoNameMarkerManager._scratchPoint = core_geometry_1.Point3d.createZero(); /** An Immediate Tool that attempts to use the geoLocation API to find the given feature */ class GeoNameTool extends core_frontend_1.Tool { static get maxArgs() { return 1; } static get minArgs() { return 0; } async run(viewport) { if (undefined === viewport) viewport = core_frontend_1.IModelApp.viewManager.selectedView; if (undefined !== viewport) this.doRunWithViewport(viewport); return true; } } class GeoNameOnTool extends GeoNameTool { doRunWithViewport(vp) { GeoNameMarkerManager.show(vp).then(() => { }).catch(() => { }); } } GeoNameOnTool.toolId = "GeoNamesOnTool"; class GeoNameOffTool extends GeoNameTool { doRunWithViewport(vp) { GeoNameMarkerManager.clear(vp); } } GeoNameOffTool.toolId = "GeoNamesOffTool"; class GeoNameUpdateTool extends GeoNameTool { doRunWithViewport(vp) { GeoNameMarkerManager.update(vp); } } GeoNameUpdateTool.toolId = "GeoNamesUpdateTool"; class GeoNameExtension { static async initialize() { await core_frontend_1.IModelApp.localization.registerNamespace(this._defaultNs); core_frontend_1.IModelApp.tools.register(GeoNameOnTool, this._defaultNs); core_frontend_1.IModelApp.tools.register(GeoNameOffTool, this._defaultNs); core_frontend_1.IModelApp.tools.register(GeoNameUpdateTool, this._defaultNs); if (undefined !== core_frontend_1.IModelApp.viewManager.selectedView) await GeoNameMarkerManager.show(core_frontend_1.IModelApp.viewManager.selectedView); } } exports.GeoNameExtension = GeoNameExtension; GeoNameExtension._defaultNs = "geoNames"; //# sourceMappingURL=geoNames.js.map