Skip to content

Commit

Permalink
Swap clampPolygonToGround to clampToGround - and now let cesium KmlDa…
Browse files Browse the repository at this point in the history
…taSource handle clamping
  • Loading branch information
nf-s committed Nov 10, 2023
1 parent 3c22fe3 commit 9d6ebe4
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 139 deletions.
173 changes: 36 additions & 137 deletions lib/Models/Catalog/CatalogItems/KmlCatalogItem.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import i18next from "i18next";
import { computed, makeObservable, override } from "mobx";
import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3";
import Cartographic from "terriajs-cesium/Source/Core/Cartographic";
import Ellipsoid from "terriajs-cesium/Source/Core/Ellipsoid";
import JulianDate from "terriajs-cesium/Source/Core/JulianDate";
import PolygonHierarchy from "terriajs-cesium/Source/Core/PolygonHierarchy";
import Resource from "terriajs-cesium/Source/Core/Resource";
import sampleTerrain from "terriajs-cesium/Source/Core/sampleTerrain";
import ConstantProperty from "terriajs-cesium/Source/DataSources/ConstantProperty";
import KmlDataSource from "terriajs-cesium/Source/DataSources/KmlDataSource";
import Property from "terriajs-cesium/Source/DataSources/Property";
import TerriaError, { networkRequestError } from "../../../Core/TerriaError";
import isDefined from "../../../Core/isDefined";
import readXml from "../../../Core/readXml";
import TerriaError, { networkRequestError } from "../../../Core/TerriaError";
import CatalogMemberMixin from "../../../ModelMixins/CatalogMemberMixin";
import MappableMixin from "../../../ModelMixins/MappableMixin";
import UrlMixin from "../../../ModelMixins/UrlMixin";
import KmlCatalogItemTraits from "../../../Traits/TraitsClasses/KmlCatalogItemTraits";
import CreateModel from "../../Definition/CreateModel";
import HasLocalData from "../../HasLocalData";
import { ModelConstructorParameters } from "../../Definition/Model";
import HasLocalData from "../../HasLocalData";
import proxyCatalogItemUrl from "../proxyCatalogItemUrl";

const kmzRegex = /\.kmz$/i;
Expand Down Expand Up @@ -62,45 +54,44 @@ class KmlCatalogItem
return "1d";
}

protected forceLoadMapItems(): Promise<void> {
return new Promise<string | Resource | Document | Blob>((resolve) => {
if (isDefined(this.kmlString)) {
const parser = new DOMParser();
resolve(parser.parseFromString(this.kmlString, "text/xml"));
} else if (isDefined(this._kmlFile)) {
if (this._kmlFile.name && this._kmlFile.name.match(kmzRegex)) {
resolve(this._kmlFile);
protected async forceLoadMapItems(): Promise<void> {
try {
const kmlLoadInput = await new Promise<
string | Resource | Document | Blob
>((resolve) => {
if (isDefined(this.kmlString)) {
const parser = new DOMParser();
resolve(parser.parseFromString(this.kmlString, "text/xml"));
} else if (isDefined(this._kmlFile)) {
if (this._kmlFile.name && this._kmlFile.name.match(kmzRegex)) {
resolve(this._kmlFile);
} else {
resolve(readXml(this._kmlFile));
}
} else if (isDefined(this.url)) {
resolve(proxyCatalogItemUrl(this, this.url));
} else {
resolve(readXml(this._kmlFile));
throw networkRequestError({
sender: this,
title: i18next.t("models.kml.unableToLoadItemTitle"),
message: i18next.t("models.kml.unableToLoadItemMessage")
});
}
} else if (isDefined(this.url)) {
resolve(proxyCatalogItemUrl(this, this.url));
} else {
throw networkRequestError({
});
this._dataSource = await KmlDataSource.load(kmlLoadInput, {
clampToGround: this.clampToGround
} as any);
} catch (e) {
throw networkRequestError(
TerriaError.from(e, {
sender: this,
title: i18next.t("models.kml.unableToLoadItemTitle"),
message: i18next.t("models.kml.unableToLoadItemMessage")
});
}
})
.then((kmlLoadInput) => {
return KmlDataSource.load(kmlLoadInput);
})
.then((dataSource) => {
this._dataSource = dataSource;
this.doneLoading(dataSource); // Unsure if this is necessary
})
.catch((e) => {
throw networkRequestError(
TerriaError.from(e, {
sender: this,
title: i18next.t("models.kml.errorLoadingTitle"),
message: i18next.t("models.kml.errorLoadingMessage", {
appName: this.terria.appName
})
title: i18next.t("models.kml.errorLoadingTitle"),
message: i18next.t("models.kml.errorLoadingMessage", {
appName: this.terria.appName
})
);
});
})
);
}
}

@computed
Expand All @@ -115,98 +106,6 @@ class KmlCatalogItem
protected forceLoadMetadata(): Promise<void> {
return Promise.resolve();
}

private doneLoading(kmlDataSource: KmlDataSource) {
// Clamp features to terrain.
if (isDefined(this.terria.cesium) && this.clampPolygonsToGround) {
const positionsToSample: Cartographic[] = [];
const correspondingCartesians: Cartesian3[] = [];

const entities = kmlDataSource.entities.values;
for (let i = 0; i < entities.length; ++i) {
const entity = entities[i];

const polygon = entity.polygon;
if (isDefined(polygon)) {
polygon.perPositionHeight = true as unknown as Property;
const polygonHierarchy = getPropertyValue<PolygonHierarchy>(
polygon.hierarchy
);
if (polygonHierarchy) {
samplePolygonHierarchyPositions(
polygonHierarchy,
positionsToSample,
correspondingCartesians
);
}
}
}
const terrainProvider = this.terria.cesium.scene.globe.terrainProvider;
sampleTerrain(terrainProvider, 11, positionsToSample).then(function () {
for (let i = 0; i < positionsToSample.length; ++i) {
const position = positionsToSample[i];
if (!isDefined(position.height)) {
continue;
}

Ellipsoid.WGS84.cartographicToCartesian(
position,
correspondingCartesians[i]
);
}

// Force the polygons to be rebuilt.
for (let i = 0; i < entities.length; ++i) {
const polygon = entities[i].polygon;
if (!isDefined(polygon)) {
continue;
}

const existingHierarchy = getPropertyValue<PolygonHierarchy>(
polygon.hierarchy
);
if (existingHierarchy) {
polygon.hierarchy = new ConstantProperty(
new PolygonHierarchy(
existingHierarchy.positions,
existingHierarchy.holes
)
);
}
}
});
}
}
}

export default KmlCatalogItem;

function getPropertyValue<T>(property: Property | undefined): T | undefined {
if (property === undefined) {
return undefined;
}
return property.getValue(JulianDate.now());
}

function samplePolygonHierarchyPositions(
polygonHierarchy: PolygonHierarchy,
positionsToSample: Cartographic[],
correspondingCartesians: Cartesian3[]
) {
const positions = polygonHierarchy.positions;

for (let i = 0; i < positions.length; ++i) {
const position = positions[i];
correspondingCartesians.push(position);
positionsToSample.push(Ellipsoid.WGS84.cartesianToCartographic(position));
}

const holes = polygonHierarchy.holes;
for (let i = 0; i < holes.length; ++i) {
samplePolygonHierarchyPositions(
holes[i],
positionsToSample,
correspondingCartesians
);
}
}
4 changes: 2 additions & 2 deletions lib/Traits/TraitsClasses/KmlCatalogItemTraits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class KmlCatalogItemTraits extends mixTraits(
type: "boolean",
name: "Clamp to Ground",
description:
"Whether the polygon features in this KML should be clamped to the terrain surface."
"true if we want the geometry features (Polygons, LineStrings and LinearRings) clamped to the ground"
})
clampPolygonsToGround: boolean = true;
clampToGround: boolean = true;
}

0 comments on commit 9d6ebe4

Please sign in to comment.