Skip to content

Conversation

Oko-Tester
Copy link

@Oko-Tester Oko-Tester commented Sep 25, 2025

Fixes #5760 by adding declusteredEvent that provides both clustered and declustered entities, plus new API methods for accessing clustering state. Maintains backward compatibility.

Description

This PR adds comprehensive clustering state information to EntityCluster by introducing a new declusteredEvent and supporting API methods. The original clusterEvent only provided information about entities that were successfully clustered, but developers also needed access to entities that were processed but not clustered (declustered entities).

Key Changes

  • New declusteredEvent: Fires with complete clustering information including both clustered and declustered entities
  • New API methods:
    • getLastClusteredEntities() - Returns currently clustered entities
    • getLastDeclusteredEntities() - Returns currently declustered entities
    • getAllProcessedEntities() - Returns all entities processed during clustering
  • Enhanced event coverage: Events now fire when clustering is disabled or clusters become empty
  • Backward compatibility: Original clusterEvent remains unchanged and functional

Issue number and link

Fixes #5760 - Include declustered entities in cluster callback

This addresses multiple user requests from the forum and GitHub comments spanning several years.

Testing plan

Manual Testing

  1. Create CustomDataSource with clustering enabled
  2. Add entities at various distances to create both clustered and declustered entities
  3. Verify declusteredEvent fires with correct clustered and declustered arrays
  4. Disable clustering and verify event fires with all entities as declustered
  5. Test API methods return correct entity lists
  6. Verify original clusterEvent still works as before

Author checklist

  • I have submitted a Contributor License Agreement
  • I have added my name to CONTRIBUTORS.md
  • I have updated CHANGES.md with a short summary of my change
  • I have added or updated unit tests to ensure consistent code coverage
  • I have updated the inline documentation, and included code examples where relevant
  • I have performed a self-review of my code

Copy link

Thank you for the pull request, @Oko-Tester!

✅ We can confirm we have a CLA on file for you.

@Oko-Tester Oko-Tester force-pushed the fix-issue-5760-declustered-entities branch from 746701c to 2d42fdc Compare September 26, 2025 12:07
@Oko-Tester Oko-Tester marked this pull request as ready for review September 26, 2025 12:07
@Oko-Tester
Copy link
Author

this is ready

Comment on lines 925 to 954

if (entityCluster._declusteredEvent.numberOfListeners !== 0) {
const allVisibleEntities = [];

if (defined(entityCluster._labelCollection)) {
for (let i = 0; i < entityCluster._labelCollection.length; i++) {
const label = entityCluster._labelCollection.get(i);
if (defined(label.id) && label.show) {
allVisibleEntities.push(label.id);
}
}
}

if (defined(entityCluster._billboardCollection)) {
for (let i = 0; i < entityCluster._billboardCollection.length; i++) {
const billboard = entityCluster._billboardCollection.get(i);
if (defined(billboard.id) && billboard.show) {
allVisibleEntities.push(billboard.id);
}
}
}

if (defined(entityCluster._pointCollection)) {
for (let i = 0; i < entityCluster._pointCollection.length; i++) {
const point = entityCluster._pointCollection.get(i);
if (defined(point.id) && point.show) {
allVisibleEntities.push(point.id);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a prime candidate for a function, so we don't repeat basically the same thing 3x. Then you could even early-return on the defined check and save a level of indentation.

That said, these collections do not share an interface, so there's no guarantee they will continue to have these common methods and fields (show, id, get)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea ur right. I´ll extract this into a helper function.

disableCollectionClustering(entityCluster._billboardCollection);
disableCollectionClustering(entityCluster._pointCollection);

if (entityCluster._declusteredEvent.numberOfListeners !== 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like the level of conditional branching here may be unnecessary. I'm always an advocate of trying to reduce the levels of nesting for clarity - usually be introducing new functions and then early-returning from them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this was added in response to my comment at #12920 (comment) . And the behavior should be kept like that - it should not do that visible-stuff-computation when no listeners are present.

We can argue about details of the style. Some people strongly advocate for "One return statement per function!". But I think that "watchdogs" and "early returns" can often increase readability. So when there is something like

if (condition) {
    // 100 lines
} else {
    // 2 lines
}

I'm also leaning towards the pattern of

// Don't do anything when not necessary
if (!condition) {
    // 2 lines
    return;
}

// Now do the real work
// 100 lines

(No strong opinion here)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this was more of a comment on style than behavior.

Also, will say, I do have strong opinions about the early return pattern. I think by nature of being early, it's kind of an exception to the no-multiple-returns guideline. In my mind, the point of no-multiple-returns is to avoid missing a deeply nested return, which can drastically change the meaning of what comes after. Short functions, with early returns don't run into that issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Rules are for the obedience of fools and the guidance of wise men" (D. Bader)

When there's a rule that there shouldn't be multiple returns per function, then some people will follow that rule, no matter what. However, I'm also in the camp of "having to scroll to find an else is a bad sign".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are no specific requests to change the logic or further customise the style, I will keep the current implementation unchanged, provided that is acceptable to you.

javagl and others added 6 commits September 29, 2025 10:42
Fixes CesiumGS#5760 by adding declusteredEvent that provides both clustered
and declustered entities, plus new API methods for accessing
clustering state. Maintains backward compatibility.
@Oko-Tester Oko-Tester force-pushed the fix-issue-5760-declustered-entities branch from 9bd82e9 to 587e235 Compare September 29, 2025 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Include declustered entities in cluster callback
3 participants