terriajs
Version:
Geospatial data visualization platform.
682 lines • 29.9 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import i18next from "i18next";
import { computed, makeObservable, override, runInAction } from "mobx";
import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3";
import Cartographic from "terriajs-cesium/Source/Core/Cartographic";
import GeographicProjection from "terriajs-cesium/Source/Core/GeographicProjection";
import GeographicTilingScheme from "terriajs-cesium/Source/Core/GeographicTilingScheme";
import WebMercatorTilingScheme from "terriajs-cesium/Source/Core/WebMercatorTilingScheme";
import combine from "terriajs-cesium/Source/Core/combine";
import GetFeatureInfoFormat from "terriajs-cesium/Source/Scene/GetFeatureInfoFormat";
import ImageryLayerFeatureInfo from "terriajs-cesium/Source/Scene/ImageryLayerFeatureInfo";
import WebMapServiceImageryProvider from "terriajs-cesium/Source/Scene/WebMapServiceImageryProvider";
import URI from "urijs";
import TerriaError from "../../../Core/TerriaError";
import createTransformerAllowUndefined from "../../../Core/createTransformerAllowUndefined";
import filterOutUndefined from "../../../Core/filterOutUndefined";
import isDefined from "../../../Core/isDefined";
import CatalogMemberMixin, { getName } from "../../../ModelMixins/CatalogMemberMixin";
import DiffableMixin, { DiffStratum } from "../../../ModelMixins/DiffableMixin";
import ExportWebCoverageServiceMixin from "../../../ModelMixins/ExportWebCoverageServiceMixin";
import GetCapabilitiesMixin from "../../../ModelMixins/GetCapabilitiesMixin";
import MappableMixin from "../../../ModelMixins/MappableMixin";
import MinMaxLevelMixin from "../../../ModelMixins/MinMaxLevelMixin";
import TileErrorHandlerMixin from "../../../ModelMixins/TileErrorHandlerMixin";
import UrlMixin from "../../../ModelMixins/UrlMixin";
import { csvFeatureInfoContext } from "../../../Table/tableFeatureInfoContext";
import WebMapServiceCatalogItemTraits, { SUPPORTED_CRS_3857, SUPPORTED_CRS_4326 } from "../../../Traits/TraitsClasses/WebMapServiceCatalogItemTraits";
import CommonStrata from "../../Definition/CommonStrata";
import CreateModel from "../../Definition/CreateModel";
import LoadableStratum from "../../Definition/LoadableStratum";
import StratumOrder from "../../Definition/StratumOrder";
import proxyCatalogItemUrl from "../proxyCatalogItemUrl";
import WebMapServiceCapabilitiesStratum from "./WebMapServiceCapabilitiesStratum";
// Remove problematic query parameters from URLs (GetCapabilities, GetMap, ...) - these are handled separately
const QUERY_PARAMETERS_TO_REMOVE = [
"request",
"service",
"x",
"y",
"width",
"height",
"bbox",
"layers",
"styles",
"version",
"format",
"srs",
"crs"
];
/** This LoadableStratum is responsible for setting WMS version based on CatalogItem.url */
export class WebMapServiceUrlStratum extends LoadableStratum(WebMapServiceCatalogItemTraits) {
catalogItem;
static stratumName = "wms-url-stratum";
constructor(catalogItem) {
super();
this.catalogItem = catalogItem;
makeObservable(this);
}
duplicateLoadableStratum(model) {
return new WebMapServiceUrlStratum(model);
}
get useWmsVersion130() {
if (this.catalogItem.url?.toLowerCase().includes("version=1.1.0") ||
this.catalogItem.url?.toLowerCase().includes("version=1.1.1")) {
return false;
}
}
}
__decorate([
computed
], WebMapServiceUrlStratum.prototype, "useWmsVersion130", null);
// Order is important so that the traits are overridden correctly
StratumOrder.addLoadStratum(WebMapServiceUrlStratum.stratumName);
StratumOrder.addLoadStratum(DiffStratum.stratumName);
class WebMapServiceCatalogItem extends TileErrorHandlerMixin(ExportWebCoverageServiceMixin(DiffableMixin(MinMaxLevelMixin(GetCapabilitiesMixin(UrlMixin(MappableMixin(CatalogMemberMixin(CreateModel(WebMapServiceCatalogItemTraits))))))))) {
/**
* The collection of strings that indicate an Abstract property should be ignored. If these strings occur anywhere
* in the Abstract, the Abstract will not be used. This makes it easy to filter out placeholder data like
* Geoserver's "A compliant implementation of WMS..." stock abstract.
*/
static abstractsToIgnore = ["A compliant implementation of WMS"];
// hide elements in the info section which might show information about the datasource
_sourceInfoItemNames = [
i18next.t("models.webMapServiceCatalogItem.getCapabilitiesUrl")
];
_webMapServiceCatalogGroup = undefined;
/** Default WMS parameters for version=1.3.0 */
static defaultParameters130 = {
transparent: true,
format: "image/png",
exceptions: "XML",
styles: "",
version: "1.3.0"
};
static defaultGetFeatureParameters130 = {
exceptions: "XML",
version: "1.3.0"
};
/** Default WMS parameters for version=1.1.1 */
static defaultParameters111 = {
transparent: true,
format: "image/png",
exceptions: "application/vnd.ogc.se_xml",
styles: "",
tiled: true,
version: "1.1.1"
};
static defaultGetFeatureParameters111 = {
exceptions: "application/vnd.ogc.se_xml",
version: "1.1.1"
};
static type = "wms";
constructor(id, terria, sourceReference) {
super(id, terria, sourceReference);
makeObservable(this);
this.strata.set(WebMapServiceUrlStratum.stratumName, new WebMapServiceUrlStratum(this));
}
get type() {
return WebMapServiceCatalogItem.type;
}
get shortReport() {
if (this.tilingScheme instanceof GeographicTilingScheme &&
this.terria.currentViewer.type === "Leaflet") {
return i18next.t("map.cesium.notWebMercatorTilingScheme", this);
}
return super.shortReport;
}
get colorScaleRange() {
if (this.supportsColorScaleRange) {
return `${this.colorScaleMinimum},${this.colorScaleMaximum}`;
}
return undefined;
}
async createGetCapabilitiesStratumFromParent(capabilities) {
const stratum = await WebMapServiceCapabilitiesStratum.load(this, capabilities);
runInAction(() => {
this.strata.set(GetCapabilitiesMixin.getCapabilitiesStratumName, stratum);
});
}
async forceLoadMapItems() {
if (this.invalidLayers.length > 0)
throw new TerriaError({
sender: this,
title: i18next.t("models.webMapServiceCatalogItem.noLayerFoundTitle"),
message: i18next.t("models.webMapServiceCatalogItem.noLayerFoundMessage", { name: getName(this), layers: this.invalidLayers.join(", ") })
});
}
async forceLoadMetadata() {
if (this.strata.get(GetCapabilitiesMixin.getCapabilitiesStratumName) !==
undefined)
return;
const stratum = await WebMapServiceCapabilitiesStratum.load(this);
runInAction(() => {
this.strata.set(GetCapabilitiesMixin.getCapabilitiesStratumName, stratum);
});
}
get cacheDuration() {
if (isDefined(super.cacheDuration)) {
return super.cacheDuration;
}
return "0d";
}
get layersArray() {
if (Array.isArray(this.layers)) {
return this.layers;
}
else if (this.layers) {
return this.layers.split(",");
}
else {
return [];
}
}
/** LAYERS which are valid (i.e. exist in GetCapabilities).
* These can be fetched from the server (eg GetMap request)
*/
get validLayers() {
const gcStratum = this.strata.get(GetCapabilitiesMixin.getCapabilitiesStratumName);
if (gcStratum)
return this.layersArray
.map((layer) => gcStratum.capabilities.findLayer(layer)?.Name)
.filter(isDefined);
return [];
}
/** LAYERS which are **INVALID** - they do **not** exist in GetCapabilities
* These layers can **not** be fetched the server (eg GetMap request)
*/
get invalidLayers() {
const gcStratum = this.strata.get(GetCapabilitiesMixin.getCapabilitiesStratumName);
if (gcStratum)
return this.layersArray.filter((layer) => !isDefined(gcStratum.capabilities.findLayer(layer)?.Name));
return [];
}
get stylesArray() {
return this.styles?.split(",") ?? [];
}
get discreteTimes() {
const getCapabilitiesStratum = this.strata.get(GetCapabilitiesMixin.getCapabilitiesStratumName);
return getCapabilitiesStratum?.discreteTimes;
}
get defaultGetCapabilitiesUrl() {
if (this.uri) {
const baseUrl = QUERY_PARAMETERS_TO_REMOVE.reduce((url, parameter) => url
.removeQuery(parameter)
.removeQuery(parameter.toUpperCase())
.removeQuery(parameter.toLowerCase()), this.uri.clone());
return baseUrl
.setSearch({
service: "WMS",
version: this.useWmsVersion130 ? "1.3.0" : "1.1.1",
request: "GetCapabilities"
})
.toString();
}
else {
return undefined;
}
}
get canDiffImages() {
const hasValidDiffStyles = this.availableDiffStyles.some((diffStyle) => this.styleSelectableDimensions?.[0]?.options?.find((style) => style.id === diffStyle));
return hasValidDiffStyles === true;
}
showDiffImage(firstDate, secondDate, diffStyleId) {
if (this.canDiffImages === false) {
return;
}
// A helper to get the diff tag given a date string
const firstDateStr = this.getTagForTime(firstDate);
const secondDateStr = this.getTagForTime(secondDate);
this.setTrait(CommonStrata.user, "firstDiffDate", firstDateStr);
this.setTrait(CommonStrata.user, "secondDiffDate", secondDateStr);
this.setTrait(CommonStrata.user, "diffStyleId", diffStyleId);
this.setTrait(CommonStrata.user, "isShowingDiff", true);
}
clearDiffImage() {
this.setTrait(CommonStrata.user, "firstDiffDate", undefined);
this.setTrait(CommonStrata.user, "secondDiffDate", undefined);
this.setTrait(CommonStrata.user, "diffStyleId", undefined);
this.setTrait(CommonStrata.user, "isShowingDiff", false);
}
getLegendBaseUrl() {
// Remove problematic query parameters from URL
const baseUrl = QUERY_PARAMETERS_TO_REMOVE.reduce((url, parameter) => url
.removeQuery(parameter)
.removeQuery(parameter.toUpperCase())
.removeQuery(parameter.toLowerCase()), new URI(this.url));
return baseUrl.toString();
}
getLegendUrlForStyle(styleId, firstDate, secondDate) {
const firstTag = firstDate && this.getTagForTime(firstDate);
const secondTag = secondDate && this.getTagForTime(secondDate);
const time = filterOutUndefined([firstTag, secondTag]).join(",");
const layerName = this.availableStyles.find((style) => style.styles.some((s) => s.name === styleId))?.layerName;
const uri = URI(`${this.url}?service=WMS&version=1.1.0&request=GetLegendGraphic&format=image/png&transparent=True`)
.addQuery("layer", encodeURIComponent(layerName || ""))
.addQuery("styles", encodeURIComponent(styleId));
if (time) {
uri.addQuery("time", time);
}
return uri.toString();
}
get mapItems() {
// Don't return anything if there are invalid layers
// See forceLoadMapItems for error message
if (this.invalidLayers.length > 0)
return [];
if (this.isShowingDiff === true) {
return this._diffImageryParts ? [this._diffImageryParts] : [];
}
const result = [];
const current = this._currentImageryParts;
if (current) {
result.push(current);
}
const next = this._nextImageryParts;
if (next) {
result.push(next);
}
return result;
}
get tilingScheme() {
if (this.crs) {
if (SUPPORTED_CRS_3857.includes(this.crs))
return new WebMercatorTilingScheme();
if (SUPPORTED_CRS_4326.includes(this.crs))
return new GeographicTilingScheme();
}
return new WebMercatorTilingScheme();
}
get _currentImageryParts() {
const imageryProvider = this._createImageryProvider(this.currentDiscreteTimeTag);
if (imageryProvider === undefined) {
return undefined;
}
// Reset feature picking for the current imagery layer.
// We disable feature picking for the next imagery layer.
imageryProvider.enablePickFeatures = this.allowFeaturePicking;
return {
imageryProvider,
alpha: this.opacity,
show: this.show,
clippingRectangle: this.clipToRectangle ? this.cesiumRectangle : undefined
};
}
get _nextImageryParts() {
if (this.terria.timelineStack.contains(this) &&
!this.isPaused &&
this.nextDiscreteTimeTag) {
const imageryProvider = this._createImageryProvider(this.nextDiscreteTimeTag);
if (imageryProvider === undefined) {
return undefined;
}
// Disable feature picking for the next imagery layer.
imageryProvider.enablePickFeatures = false;
return {
imageryProvider,
alpha: 0.0,
show: true,
clippingRectangle: this.clipToRectangle
? this.cesiumRectangle
: undefined
};
}
else {
return undefined;
}
}
get _diffImageryParts() {
const diffStyleId = this.diffStyleId;
if (this.firstDiffDate === undefined ||
this.secondDiffDate === undefined ||
diffStyleId === undefined) {
return;
}
const time = `${this.firstDiffDate},${this.secondDiffDate}`;
const imageryProvider = this._createImageryProvider(time);
if (imageryProvider) {
return {
imageryProvider,
alpha: this.opacity,
show: this.show,
clippingRectangle: this.clipToRectangle
? this.cesiumRectangle
: undefined
};
}
return undefined;
}
get diffModeParameters() {
return this.isShowingDiff ? { styles: this.diffStyleId } : {};
}
get diffModeGetFeatureInfoParameters() {
return this.isShowingDiff ? { styles: this.diffStyleId } : {};
}
getTagForTime(date) {
const index = this.getDiscreteTimeIndex(date);
return index !== undefined
? this.discreteTimesAsSortedJulianDates?.[index].tag
: undefined;
}
_createImageryProvider = createTransformerAllowUndefined((time) => {
// Don't show anything on the map until GetCapabilities finishes loading.
if (this.isLoadingMetadata) {
return undefined;
}
if (this.url === undefined) {
return undefined;
}
console.log(`Creating new ImageryProvider for time ${time}`);
// Set dimensionParameters
const dimensionParameters = formatDimensionsForOws(this.dimensions);
if (time !== undefined) {
dimensionParameters.time = time;
}
// Construct parameters objects
// We use slightly different parameters for GetMap and GetFeatureInfo requests
const parameters = {
...(this.useWmsVersion130
? WebMapServiceCatalogItem.defaultParameters130
: WebMapServiceCatalogItem.defaultParameters111),
...this.parameters,
...dimensionParameters
};
const getFeatureInfoParameters = {
...(this.useWmsVersion130
? WebMapServiceCatalogItem.defaultGetFeatureParameters130
: WebMapServiceCatalogItem.defaultGetFeatureParameters111),
feature_count: 1 +
(this.maximumShownFeatureInfos ??
this.terria.configParameters.defaultMaximumShownFeatureInfos),
...this.parameters,
// Note order is important here, as getFeatureInfoParameters may override `time` dimension value
...dimensionParameters,
...this.getFeatureInfoParameters
};
if (this.supportsColorScaleRange) {
parameters.COLORSCALERANGE = this.colorScaleRange;
}
// Styles parameter is mandatory (for GetMap and GetFeatureInfo requests), but can be empty string to use default style
parameters.styles = this.styles ?? "";
getFeatureInfoParameters.styles = this.styles ?? "";
Object.assign(parameters, this.diffModeParameters);
Object.assign(getFeatureInfoParameters, this.diffModeGetFeatureInfoParameters);
// Remove problematic query parameters from URL - these are handled by the parameters objects
const baseUrl = QUERY_PARAMETERS_TO_REMOVE.reduce((url, parameter) => url
.removeQuery(parameter)
.removeQuery(parameter.toUpperCase())
.removeQuery(parameter.toLowerCase()), new URI(this.url));
// Set CRS for WMS 1.3.0
// Set SRS for WMS 1.1.1
const crs = this.useWmsVersion130 ? this.crs : undefined;
const srs = this.useWmsVersion130 ? undefined : this.crs;
const imageryOptions = {
url: proxyCatalogItemUrl(this, baseUrl.toString()),
layers: this.validLayers.length > 0 ? this.validLayers.join(",") : "",
parameters,
crs,
srs,
getFeatureInfoParameters,
getFeatureInfoUrl: this.getFeatureInfoUrl,
tileWidth: this.tileWidth,
tileHeight: this.tileHeight,
tilingScheme: this.tilingScheme,
maximumLevel: this.getMaximumLevel(true) ?? this.maximumLevel,
minimumLevel: this.minimumLevel,
credit: this.attribution
// Note: we set enablePickFeatures in _currentImageryParts and _nextImageryParts
};
imageryOptions.getFeatureInfoFormats = this.getFeatureInfoFormats;
if (imageryOptions.maximumLevel !== undefined &&
this.hideLayerAfterMinScaleDenominator) {
// Make Cesium request one extra level so we can tell the user what's happening and return a blank image.
++imageryOptions.maximumLevel;
}
const imageryProvider = new WebMapServiceImageryProvider(imageryOptions);
return this.updateRequestImage(imageryProvider);
});
get styleSelectableDimensions() {
return this.availableStyles.map((layer, layerIndex) => {
let name = "Styles";
// If multiple layers -> prepend layer name to name
if (this.availableStyles.length > 1) {
// Attempt to get layer title from GetCapabilitiesStratum
const layerTitle = layer.layerName &&
this.strata.get(GetCapabilitiesMixin.getCapabilitiesStratumName).capabilitiesLayers.get(layer.layerName)?.Title;
name = `${layerTitle || layer.layerName || `Layer ${layerIndex + 1}`} styles`;
}
const options = filterOutUndefined(layer.styles.map(function (s) {
if (isDefined(s.name)) {
return {
name: s.title || s.name || "",
id: s.name
};
}
}));
// Try to set selectedId to value stored in `styles` trait for this `layerIndex`
// The `styles` parameter is CSV, a style for each layer
const selectedId = this.styles?.split(",")?.[layerIndex];
return {
name,
id: `${this.uniqueId}-${layer.layerName}-styles`,
options,
selectedId,
setDimensionValue: (stratumId, newStyle) => {
if (!newStyle)
return;
runInAction(() => {
const styles = this.styleSelectableDimensions.map((style) => style.selectedId || "");
styles[layerIndex] = newStyle;
this.setTrait(stratumId, "styles", styles.join(","));
});
},
// There is no way of finding out default style if no style has been selected :(
// To use the default style, we just send empty "styles" to WMS server
// But if the server doesn't support GetLegendGraphic, then we can't request the default legend
// Therefore - we only add the "Default style" / undefined option if supportsGetLegendGraphic is true
allowUndefined: this.supportsGetLegendGraphic && options.length > 1,
undefinedLabel: i18next.t("models.webMapServiceCatalogItem.defaultStyleLabel"),
disable: this.isShowingDiff
};
});
}
get wmsDimensionSelectableDimensions() {
const dimensions = [];
// For each layer -> For each dimension
this.availableDimensions.forEach((layer) => {
layer.dimensions.forEach((dim) => {
// Only add dimensions if hasn't already been added (multiple layers may have the same dimension)
if (!isDefined(dim.name) ||
dim.values.length < 2 ||
dimensions.findIndex((findDim) => findDim.name === dim.name) !== -1) {
return;
}
dimensions.push({
name: dim.name,
id: `${this.uniqueId}-${dim.name}`,
options: dim.values.map((value) => {
let name = value;
// Add units and unitSybol if defined
if (typeof dim.units === "string" && dim.units !== "") {
if (typeof dim.unitSymbol === "string" && dim.unitSymbol !== "") {
name = `${value} (${dim.units} ${dim.unitSymbol})`;
}
else {
name = `${value} (${dim.units})`;
}
}
return {
name,
id: value
};
}),
// Set selectedId to value stored in `dimensions` trait, the default value, or the first available value
selectedId: this.dimensions?.[dim.name]?.toString() ||
dim.default ||
dim.values[0],
setDimensionValue: (stratumId, newDimension) => {
let newDimensions = {};
newDimensions[dim.name] = newDimension;
if (isDefined(this.dimensions)) {
newDimensions = combine(newDimensions, this.dimensions);
}
runInAction(() => {
this.setTrait(stratumId, "dimensions", newDimensions);
});
}
});
});
});
return dimensions;
}
get selectableDimensions() {
if (this.disableDimensionSelectors) {
return super.selectableDimensions;
}
return filterOutUndefined([
...super.selectableDimensions,
...this.wmsDimensionSelectableDimensions,
...this.styleSelectableDimensions
]);
}
/** If GetFeatureInfo/GetTimeseries request is returning CSV, we need to parse it into TimeSeriesFeatureInfoContext.
*/
get featureInfoContext() {
if (this.getFeatureInfoFormat.format !== "text/csv")
return () => ({});
return csvFeatureInfoContext(this);
}
get getFeatureInfoFormats() {
const customFormat = this.getFeatureInfoFormat;
if (customFormat) {
if (customFormat.type === "json") {
return [
new GetFeatureInfoFormat("json", "application/json", (json) => geoJsonToFeatureInfoWithProject(json, this.tilingScheme.projection))
];
}
else {
return [
new GetFeatureInfoFormat(customFormat.type, customFormat.format)
];
}
}
return [
new GetFeatureInfoFormat("json", "application/json", (json) => geoJsonToFeatureInfoWithProject(json, this.tilingScheme.projection)),
new GetFeatureInfoFormat("xml", "text/xml"),
new GetFeatureInfoFormat("csv", "text/csv")
];
}
}
__decorate([
override
], WebMapServiceCatalogItem.prototype, "shortReport", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "colorScaleRange", null);
__decorate([
override
], WebMapServiceCatalogItem.prototype, "cacheDuration", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "layersArray", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "validLayers", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "invalidLayers", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "stylesArray", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "discreteTimes", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "canDiffImages", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "mapItems", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "tilingScheme", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "_currentImageryParts", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "_nextImageryParts", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "_diffImageryParts", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "diffModeParameters", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "diffModeGetFeatureInfoParameters", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "styleSelectableDimensions", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "wmsDimensionSelectableDimensions", null);
__decorate([
override
], WebMapServiceCatalogItem.prototype, "selectableDimensions", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "featureInfoContext", null);
__decorate([
computed
], WebMapServiceCatalogItem.prototype, "getFeatureInfoFormats", null);
/**
* Add `_dim` prefix to dimensions for OWS (WMS, WCS...) excluding time, styles and elevation
*/
export function formatDimensionsForOws(dimensions) {
if (!isDefined(dimensions)) {
return {};
}
return Object.entries(dimensions).reduce((formattedDimensions, [key, value]) => {
formattedDimensions[["time", "styles", "elevation"].includes(key?.toLowerCase())
? key
: `dim_${key}`] = value;
return formattedDimensions;
}, {});
}
// Take the GetFeatureInfo response and reproject the feature coordinates to geographic if necessary, so the position is correct when displayed on the map.
// Cesium [GetFeatureInfoFormat](https://github.com/CesiumGS/cesium/blob/5754031f65646bee5f9d0e9a56dec7d3677a8b08/packages/engine/Source/Scene/GetFeatureInfoFormat.js#L74) assumes picked features is returned in geographic projection, so we need to convert them when tile scheme is not geographic.
function geoJsonToFeatureInfoWithProject(json, projection) {
const result = [];
const features = json.features;
for (let i = 0; i < features.length; ++i) {
const feature = features[i];
const featureInfo = new ImageryLayerFeatureInfo();
featureInfo.data = feature;
featureInfo.properties = feature.properties;
featureInfo.configureNameFromProperties(feature.properties);
featureInfo.configureDescriptionFromProperties(feature.properties);
// If this is a point feature, use the coordinates of the point.
if (!!feature.geometry && feature.geometry.type === "Point") {
const x = feature.geometry.coordinates[0];
const y = feature.geometry.coordinates[1];
if (!projection || projection instanceof GeographicProjection) {
featureInfo.position = Cartographic.fromDegrees(x, y);
}
else {
const positionInMeters = new Cartesian3(x, y, 0);
const cartographic = projection.unproject(positionInMeters);
featureInfo.position = cartographic;
}
}
result.push(featureInfo);
}
return result;
}
export default WebMapServiceCatalogItem;
//# sourceMappingURL=WebMapServiceCatalogItem.js.map