From bd9e8b5240840633c7a2d32e1590f2bf88890cc3 Mon Sep 17 00:00:00 2001 From: glughi Date: Wed, 19 Jun 2024 17:53:02 +0200 Subject: [PATCH 1/3] Add clustering trait to GeoJson (and consequently to WFS, ...) --- CHANGES.md | 2 +- lib/ModelMixins/GeojsonMixin.ts | 28 +++++++++++++ lib/Traits/TraitsClasses/ClusteringTraits.ts | 43 ++++++++++++++++++++ lib/Traits/TraitsClasses/GeoJsonTraits.ts | 9 ++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 lib/Traits/TraitsClasses/ClusteringTraits.ts diff --git a/CHANGES.md b/CHANGES.md index 40e3d36c10d..85855f03531 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,7 @@ #### next release (8.7.5) -- [The next improvement] +- Add clustering trait to GeoJson (and consequently to WFS, ...). #### 8.7.4 - 2024-06-07 diff --git a/lib/ModelMixins/GeojsonMixin.ts b/lib/ModelMixins/GeojsonMixin.ts index e1331270128..130bb8503ef 100644 --- a/lib/ModelMixins/GeojsonMixin.ts +++ b/lib/ModelMixins/GeojsonMixin.ts @@ -105,6 +105,8 @@ import { ExportData } from "./ExportableMixin"; import FeatureInfoUrlTemplateMixin from "./FeatureInfoUrlTemplateMixin"; import { isDataSource } from "./MappableMixin"; import TableMixin from "./TableMixin"; +import PinBuilder from "terriajs-cesium/Source/Core/PinBuilder"; +import VerticalOrigin from "terriajs-cesium/Source/Scene/VerticalOrigin"; export const FEATURE_ID_PROP = "_id_"; @@ -602,6 +604,32 @@ function GeoJsonMixin>(Base: T) { }); } else { const dataSource = await this.loadGeoJsonDataSource(geoJsonWgs84); + + if (this.clustering.enabled) { + const pinBackgroundColor = this.clustering.pinBackgroundColor; + const pinSize = this.clustering.pinSize; + + const pinBuilder = new PinBuilder(); + dataSource.clustering.enabled = true; + dataSource.clustering.pixelRange = this.clustering.pixelRange; + dataSource.clustering.minimumClusterSize = this.clustering.minimumClusterSize; + dataSource.clustering.clusterEvent.addEventListener(function ( + entities, + cluster + ) { + cluster.label.show = false; + cluster.billboard.verticalOrigin = VerticalOrigin.BOTTOM; + cluster.billboard.image = pinBuilder + .fromText( + entities.length.toLocaleString(), + Color.fromCssColorString(pinBackgroundColor), + pinSize + ) + .toDataURL(); + cluster.billboard.show = true; + }); + } + runInAction(() => { this._dataSource = dataSource; this._imageryProvider = undefined; diff --git a/lib/Traits/TraitsClasses/ClusteringTraits.ts b/lib/Traits/TraitsClasses/ClusteringTraits.ts new file mode 100644 index 00000000000..2ec2dfea445 --- /dev/null +++ b/lib/Traits/TraitsClasses/ClusteringTraits.ts @@ -0,0 +1,43 @@ +import ModelTraits from "../ModelTraits"; +import primitiveTrait from "../Decorators/primitiveTrait"; + +export default class ClusteringTraits extends ModelTraits { + @primitiveTrait({ + name: "Enabled", + description: "True to enable clustering. False by default", + type: "boolean" + }) + enabled = false; + + @primitiveTrait({ + name: "pixelRange", + description: + "The pixel range to extend the screen space bounding box", + type: "number" + }) + pixelRange: number = 35; + + @primitiveTrait({ + name: "minimumClusterSize", + description: + "The minimum number of screen space objects that can be clustered", + type: "number" + }) + minimumClusterSize: number = 5; + + @primitiveTrait({ + name: "pinSize", + description: + "The size of the pin, in pixels", + type: "number" + }) + pinSize: number = 60; + + @primitiveTrait({ + name: "pinBackgroundColor", + type: "string", + description: + "The color of the pin" + }) + pinBackgroundColor: string = "gray"; +} \ No newline at end of file diff --git a/lib/Traits/TraitsClasses/GeoJsonTraits.ts b/lib/Traits/TraitsClasses/GeoJsonTraits.ts index 6cb5aeb9b94..a4901868c23 100644 --- a/lib/Traits/TraitsClasses/GeoJsonTraits.ts +++ b/lib/Traits/TraitsClasses/GeoJsonTraits.ts @@ -5,6 +5,7 @@ import objectTrait from "../Decorators/objectTrait"; import primitiveTrait from "../Decorators/primitiveTrait"; import mixTraits from "../mixTraits"; import ModelTraits from "../ModelTraits"; +import ClusteringTraits from "./ClusteringTraits"; import FeatureInfoUrlTemplateTraits from "./FeatureInfoTraits"; import LegendOwnerTraits from "./LegendOwnerTraits"; import StyleTraits from "./StyleTraits"; @@ -163,4 +164,12 @@ export class GeoJsonTraits extends mixTraits( "Replaces `MultiPoint` features with its equivalent `Point` features when `true`. This is useful for example when using Table mode which does not support `MultiPoint` features currently." }) explodeMultiPoints = true; + + @objectTrait({ + type: ClusteringTraits, + name: "clustering", + description: + "" + }) + clustering?: ClusteringTraits; } From e65b150f62c790b0d9c831743c510f0256a098f5 Mon Sep 17 00:00:00 2001 From: glughi Date: Thu, 20 Jun 2024 16:21:18 +0200 Subject: [PATCH 2/3] Add missing description of "clustering" parameter --- CHANGES.md | 2 +- lib/Traits/TraitsClasses/GeoJsonTraits.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b9c8136dea4..2fb14623639 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,7 @@ #### next release (8.7.5) -- Add clustering trait to GeoJson (and consequently to WFS, ...). +- Add clustering trait to GeoJson (and consequently to WFS, ...) using Cesium as viewer. - TSify some `js` and `jsx` files and provide `.d.ts` ambient type files for a few others. This is so that running `tsc` on an external project that imports Terria code will typecheck successfully. - Upgraded a bunch of d3 dependencies for fixing security errors. - Show rectangle selector for WPS bounding box parameter diff --git a/lib/Traits/TraitsClasses/GeoJsonTraits.ts b/lib/Traits/TraitsClasses/GeoJsonTraits.ts index a4901868c23..dd24b791b28 100644 --- a/lib/Traits/TraitsClasses/GeoJsonTraits.ts +++ b/lib/Traits/TraitsClasses/GeoJsonTraits.ts @@ -169,7 +169,7 @@ export class GeoJsonTraits extends mixTraits( type: ClusteringTraits, name: "clustering", description: - "" + "Allows to activate the clustering of entities, works only with Cesium as a viewer." }) clustering?: ClusteringTraits; } From 856387a042d5cb3267995b746b1a7f9eb1d455df Mon Sep 17 00:00:00 2001 From: glughi Date: Mon, 28 Oct 2024 18:05:29 +0100 Subject: [PATCH 3/3] Fix lint problems --- lib/ModelMixins/GeojsonMixin.ts | 3 +- lib/Traits/TraitsClasses/ClusteringTraits.ts | 67 ++++++++++---------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/lib/ModelMixins/GeojsonMixin.ts b/lib/ModelMixins/GeojsonMixin.ts index 130bb8503ef..1f22f8b15ce 100644 --- a/lib/ModelMixins/GeojsonMixin.ts +++ b/lib/ModelMixins/GeojsonMixin.ts @@ -612,7 +612,8 @@ function GeoJsonMixin>(Base: T) { const pinBuilder = new PinBuilder(); dataSource.clustering.enabled = true; dataSource.clustering.pixelRange = this.clustering.pixelRange; - dataSource.clustering.minimumClusterSize = this.clustering.minimumClusterSize; + dataSource.clustering.minimumClusterSize = + this.clustering.minimumClusterSize; dataSource.clustering.clusterEvent.addEventListener(function ( entities, cluster diff --git a/lib/Traits/TraitsClasses/ClusteringTraits.ts b/lib/Traits/TraitsClasses/ClusteringTraits.ts index 2ec2dfea445..e10f34998c3 100644 --- a/lib/Traits/TraitsClasses/ClusteringTraits.ts +++ b/lib/Traits/TraitsClasses/ClusteringTraits.ts @@ -2,42 +2,39 @@ import ModelTraits from "../ModelTraits"; import primitiveTrait from "../Decorators/primitiveTrait"; export default class ClusteringTraits extends ModelTraits { - @primitiveTrait({ - name: "Enabled", - description: "True to enable clustering. False by default", - type: "boolean" - }) - enabled = false; + @primitiveTrait({ + name: "Enabled", + description: "True to enable clustering. False by default", + type: "boolean" + }) + enabled = false; - @primitiveTrait({ - name: "pixelRange", - description: - "The pixel range to extend the screen space bounding box", - type: "number" - }) - pixelRange: number = 35; + @primitiveTrait({ + name: "pixelRange", + description: "The pixel range to extend the screen space bounding box", + type: "number" + }) + pixelRange: number = 35; - @primitiveTrait({ - name: "minimumClusterSize", - description: - "The minimum number of screen space objects that can be clustered", - type: "number" - }) - minimumClusterSize: number = 5; + @primitiveTrait({ + name: "minimumClusterSize", + description: + "The minimum number of screen space objects that can be clustered", + type: "number" + }) + minimumClusterSize: number = 5; - @primitiveTrait({ - name: "pinSize", - description: - "The size of the pin, in pixels", - type: "number" - }) - pinSize: number = 60; + @primitiveTrait({ + name: "pinSize", + description: "The size of the pin, in pixels", + type: "number" + }) + pinSize: number = 60; - @primitiveTrait({ - name: "pinBackgroundColor", - type: "string", - description: - "The color of the pin" - }) - pinBackgroundColor: string = "gray"; -} \ No newline at end of file + @primitiveTrait({ + name: "pinBackgroundColor", + type: "string", + description: "The color of the pin" + }) + pinBackgroundColor: string = "gray"; +}