Skip to content

GoogleMaps support#7604

Merged
mdastous-bentley merged 73 commits into
masterfrom
MichelD/GoogleMaps
Feb 21, 2025
Merged

GoogleMaps support#7604
mdastous-bentley merged 73 commits into
masterfrom
MichelD/GoogleMaps

Conversation

@mdastous-bentley
Copy link
Copy Markdown
Contributor

@mdastous-bentley mdastous-bentley commented Jan 24, 2025

New imagery format / proviter to support Google maps 2D tiles:
image

More details available in NextVersion.md.

Comment thread core/common/src/MapLayerSettings.ts Outdated
@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@pmconne Part of this PR, I need to have an async version of TileTreeReference.addLogoCards, mainly because a request need to Google web API is required to retrieve copyright strings associated with selected tiles. Currently it's being invoked through Viewport.forEachTileTreeRef, which is not async.

My only solution right now, would consist in created an async version of the forEach methods, but I feel like it will result in a ugly API.

Any thoughts?

@pmconne
Copy link
Copy Markdown
Member

pmconne commented Jan 24, 2025

My only solution right now, would consist in created an async version of the forEach methods, but I feel like it will result in a ugly API.

The forEach methods are a relic of the days when we were still learning how to do TypeScript.
I'd suggest supplanting them with synchronous method(s) that return Iterable<TileTreeReference>. Then the caller can worry about calling async methods on the references, halting iteration partway through, doing something with the return value of whatever he's calling on the references, etc etc.

Comment thread core/bentley/src/Compare.ts Outdated
@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@pmconne @aruniverse @matmarchand Looking for feedback on the actual implementation state:

  1. The new maplayer format / provider was added to @itwin/map-layers-formats package. Meaning, the package has to be installed in your iTwin application to get GoogleMaps support.
  2. Also, there's no new value built-in value for BackgroundMapProviderName to use with BaseMapLayerSettings.fromProvider
  3. Introduction of a new properties field on MapLayerSettings to pass provider specific properties, which will be part of the display style serialization.
  4. An utility GoogleMaps object is provided (could also be merged on GoogleImageryFormat class), is provided to easily create MapLayerSettings from GoogleMaps API parameters (i.e. you don't have to provide the property bag or the service URL by hand).
  5. We don't provided any GoogleMaps API key, each product will have to provider their own.

@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@pmconne An async version of TileTreeReference.addLogoCards will be needed, what strategy do you suggest to replace an existing public API?

@pmconne
Copy link
Copy Markdown
Member

pmconne commented Feb 3, 2025

An async version of TileTreeReference.addLogoCards will be needed, what strategy do you suggest to replace an existing public API?

The approach you've taken (deprecate it, add new addAttributions replacement) looks ok on the face of it but will introduce bugs. Existing implementations (outside of itiwnjs-core, where you've added the new method) will not have overridden the new method, so if you update callers of addLogoCards to call addAttributions instead, suddenly some attributions will go missing.

The simplest solution would be to change addLogoCards' return type to void | Promise<void> but that's a breaking change.

All but one of your addAttributions methods is just a copy-paste of addLogoCards. You could instead do something like:

class TileTreeReference {
  // Everyone who provides attributions today overrides this method.
  /** @deprecated in 5.0. Use [[addAttributions]] instead. */
  public addLogoCards(_cards: HTMLTableELement, _vp: ScreenViewport): void { }

  // People who need async attributions, or those reacting to deprecation warnings, would override this method instead of addLogoCards.
  protected addAttributions(cards: HTMLTableElement, vp: ScreenViewport): Promise<void> {
    return Promise.resolve(this.addLogoCards(cards, vp);
  }
}

@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

An async version of TileTreeReference.addLogoCards will be needed, what strategy do you suggest to replace an existing public API?

The approach you've taken (deprecate it, add new addAttributions replacement) looks ok on the face of it but will introduce bugs. Existing implementations (outside of itiwnjs-core, where you've added the new method) will not have overridden the new method, so if you update callers of addLogoCards to call addAttributions instead, suddenly some attributions will go missing.

The simplest solution would be to change addLogoCards' return type to void | Promise<void> but that's a breaking change.

All but one of your addAttributions methods is just a copy-paste of addLogoCards. You could instead do something like:

class TileTreeReference {
  // Everyone who provides attributions today overrides this method.
  /** @deprecated in 5.0. Use [[addAttributions]] instead. */
  public addLogoCards(_cards: HTMLTableELement, _vp: ScreenViewport): void { }

  // People who need async attributions, or those reacting to deprecation warnings, would override this method instead of addLogoCards.
  protected addAttributions(cards: HTMLTableElement, vp: ScreenViewport): Promise<void> {
    return Promise.resolve(this.addLogoCards(cards, vp);
  }
}

Thanks for the suggestion, I totally agree too much code duplication in previous approach.

@pmconne
Copy link
Copy Markdown
Member

pmconne commented Feb 5, 2025

Looking for feedback on the actual implementation state

I guess the user interface is going to have to expose the provider-specific config options (property bag)? Should the provider expose a schema describing the available properties and their types?

I note you've basically reintroduced the equivalent of BackgroundMapProps.providerData which was originally a bag of provider-specific config properties, going back to MicroStation. That's probably where the "map type" belongs (and where it used to live), since each provider can have its own set of map types (or only one, and no need to specify), but unfortunately that'd be a breaking change.

@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

Looking for feedback on the actual implementation state

I guess the user interface is going to have to expose the provider-specific config options (property bag)? Should the provider expose a schema describing the available properties and their types?

Currently it's the job of the GoogleMaps object: it provides an interfaced name CreateGoogleMapsSessionOptions, and utility methods such as createPropertiesFromSessionOptions and createMapLayerSettings so that you never have to deal directly with the properties bag.

It doesn't offer though, a set of abstract types that could be shared among future providers interested in using properties bag.

@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@pmconne There are function inside GoogleMaps.ts that I would to keep private, meaning it should not be discoverable in the typing. Do we have any utilities in this repo to achieve that?

@pmconne
Copy link
Copy Markdown
Member

pmconne commented Feb 7, 2025

@pmconne There are function inside GoogleMaps.ts that I would to keep private, meaning it should not be discoverable in the typing. Do we have any utilities in this repo to achieve that?

Guidelines for internal APIs. Is this what you mean?

@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@pmconne There are function inside GoogleMaps.ts that I would to keep private, meaning it should not be discoverable in the typing. Do we have any utilities in this repo to achieve that?

Guidelines for internal APIs. Is this what you mean?

Not quite, @internal items are still visible when consuming the API, which I find rather confusing for our API consumers.

@pmconne
Copy link
Copy Markdown
Member

pmconne commented Feb 10, 2025

@internal items are still visible when consuming the API

Only if you export them from the package.
Be more specific about which APIs you are trying to keep private, and what you mean by "private" (only accessible in the same package? only in monorepo? only for other special repos?)

@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@aruniverse @eringram One of you need to approve I think

Comment thread extensions/map-layers-formats/src/internal/GoogleMapsUtils.ts Outdated
Copy link
Copy Markdown
Member

@aruniverse aruniverse left a comment

Choose a reason for hiding this comment

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

newly added beta apis exposed to users seem fine to me in map-layers-format

i think a lot is left to be desired here for formatting of the code but trying to not be picky, and hope we come back to it later

Comment thread test-apps/display-test-app/src/common/DtaConfiguration.ts
@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

newly added beta apis exposed to users seem fine to me in map-layers-format

i think a lot is left to be desired here for formatting of the code but trying to not be picky, and hope we come back to it later

Any example of what you are referring to ?

@mdastous-bentley mdastous-bentley enabled auto-merge (squash) February 20, 2025 21:15
@mdastous-bentley mdastous-bentley merged commit ce418d1 into master Feb 21, 2025
@mdastous-bentley mdastous-bentley deleted the MichelD/GoogleMaps branch February 21, 2025 16:15
pankhur94 pushed a commit that referenced this pull request Feb 24, 2025
Co-authored-by: pmconne <22944042+pmconne@users.noreply.github.com>
Co-authored-by: Arun George <11051042+aruniverse@users.noreply.github.com>
@mdastous-bentley
Copy link
Copy Markdown
Contributor Author

@Mergifyio backport release/4.11.x

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Feb 26, 2025

backport release/4.11.x

✅ Backports have been created

Details

mergify Bot pushed a commit that referenced this pull request Feb 26, 2025
Co-authored-by: pmconne <22944042+pmconne@users.noreply.github.com>
Co-authored-by: Arun George <11051042+aruniverse@users.noreply.github.com>
(cherry picked from commit ce418d1)

# Conflicts:
#	common/config/rush/pnpm-lock.yaml
#	core/frontend/src/Viewport.ts
#	core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts
#	core/frontend/src/tile/map/ImageryProviders/AzureMapsLayerImageryProvider.ts
#	core/frontend/src/tile/map/ImageryProviders/MapBoxLayerImageryProvider.ts
#	core/frontend/src/tile/map/ImageryTileTree.ts
#	core/frontend/src/tile/map/MapTileTree.ts
#	docs/changehistory/NextVersion.md
* If defined, sets the MapBox key for the `MapLayerOptions` as an "access_token".
* IMJS_BING_MAPS_KEY
* If defined, sets a Bing Maps key within the `MapLayerOptions` as a "key" type.
* IMJS_BING_MAPS_KEY
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

bad copy and paste,

Suggested change
* IMJS_BING_MAPS_KEY
* IMJS_GOOGLE_MAPS_KEY

ben-polinsky added a commit that referenced this pull request Mar 20, 2026
ScreenViewport.addDecorations() was iterating getTileTreeRefs() which includes
the view's own model and displayStyle refs — these are already decorated via
context.addFromDecorator(this.view). This redundant iteration was introduced in
ce418d1 (GoogleMaps support #7604).

The fix iterates only mapTileTreeRefs (needed for map layer decorations like
Google Maps attribution) and tiledGraphicsProviderRefs (external providers),
matching the 4.11 behavior while preserving the map decoration support that
#7604 intended.

This reduces per-frame overhead during dynamics (move/copy drag) when
decorations are invalidated, especially with many physical models generating
many tile tree references.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

4 participants