Skip to content

Conversation

@lukemckinstry
Copy link
Contributor

@lukemckinstry lukemckinstry commented Oct 24, 2025

Description

Switches on the Azure2DImageryProvider class. Also adds viewport attribution logic for Azure layers.

To Do

DO NOT MERGE until complete

  • Change sandcastles to use production asset IDs, and remove links to ion staging urls

Issue number and link

Testing plan

NOTE: Test using ion staging asset IDs until prod assets are ready

Sandcastles (to publish in prod)

To view the sandcastles, add the key to your Ion Staging account.

Test both ways to add Azure 2D data

  • IonImageryProvider.fromAssetId() - sandcastles 1&2
  • Azure2DImageryProvider constructor test sandcastle
    • add Azure key
  • Check attribution - satellite map has most attribution
  • Test prod ion asset IDs, when ready

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

@github-actions
Copy link

Thank you for the pull request, @lukemckinstry!

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

@lukemckinstry lukemckinstry marked this pull request as ready for review October 27, 2025 15:31
@lukemckinstry
Copy link
Contributor Author

ready for review @ggetz

Copy link
Contributor

@ggetz ggetz left a comment

Choose a reason for hiding this comment

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

Thanks @lukemckinstry! I did an initial pass on the code and have a few questions and comments.

I will follow up to test this shortly.

Comment on lines +405 to +417
providerViewModels.push(
new ProviderViewModel({
name: "Azure Maps Labels Only",
iconUrl: buildModuleUrl(
"Widgets/Images/ImageryProviders/azureLabels.png",
),
tooltip:
"Place labels from Azure Maps to combine with other imagery such as Sentinel-2",
category: "Cesium ion",
creationFunction: function () {
return IonImageryProvider.fromAssetId(3891170);
},
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

Does a labels-only layer make sense for the base layer provider? I'm leaning towards no since labels-only is typically applied on top of another dataset as opposed to being used as the base layer.

style: Cesium.IonWorldImageryStyle.AERIAL_WITH_LABELS,
}),
baseLayer: Cesium.ImageryLayer.fromProviderAsync(
Cesium.IonImageryProvider.fromAssetId(3830183),
Copy link
Contributor

Choose a reason for hiding this comment

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

What was the motivation for changing this away from Bing?

this._subscriptionKey =
options.subscriptionKey ?? options["subscription-key"];
//>>includeStart('debug', pragmas.debug);
Check.defined("options.tilesetId", options.tilesetId);
Copy link
Contributor

Choose a reason for hiding this comment

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

I ran into this in https://github.com/CesiumGS/cesium/pull/13004/files#diff-8c9bd0da5a2315f5b1211e299d0d1517027f1bf8e7a3eab29a601b6761f548f1R46, but it looks like there is a discrepancy between the docs for Azure2DImageryProvider.ConstructorOptions which specifies a default and the implemented behavior.

In my PR, I implemented the default value. Please let me know if that assumption was wrong.

this._tileCredits = resource.credits;
this._attributionsByLevel = undefined;
// Asynchronously request and populate _attributionsByLevel
this.getViewportCredits();
Copy link
Contributor

Choose a reason for hiding this comment

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

The promise kicked off by this function could reject unpredictably, and that can lead to confusing behavior in isolation, like when called in a unit test.

Ideally, we should not kick off any async processes in the constructor. See how I handled this in https://github.com/CesiumGS/cesium/pull/13004/files#diff-7142af57f22c9916aeeac920512bb9d8211e4a6b769201230de03902b119fa1bR487-R501 and let me know if you have any feedback.

Comment on lines +365 to +376
const viewport = await Resource.fetch({
url: url,
queryParameters: {
tilesetId,
"subscription-key": key,
"api-version": "2024-04-01",
zoom: level,
bounds: "-180,-90,180,90",
},
data: JSON.stringify(Frozen.EMPTY_OBJECT),
});
const viewportJson = JSON.parse(viewport);
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and for Google2DImageryProvider

  1. We can use Resource.fetchJson to return JSON directly
  2. This should likely use a derived resource so that if the provider was created with an IonResource, we use the derived IonResource with the correct headers and refresh behvaior.

level,
),
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Not strictly required to merge this PR, but I wonder if we can more lazily request tile credits as needed based on the current zoom level, and potentially extents, alongside the image requests in requestImage.

This would also potentially apply to Google2DImageryProvider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants