import { DecoderOptions , OptionsMap , WorkerServiceProtocol } from "@here/harp-datasource-protocol" ; import { EarthConstants , TileKey , webMercatorTilingScheme } from "@here/harp-geoutils" ; import { DataSourceOptions , Tile } from "@here/harp-mapview" ; import { DataProvider , TileDataSource , TileDataSourceOptions , TileFactory } from "@here/harp-mapview-decoder" ; import { getOptionValue , LoggerManager } from "@here/harp-utils" ; import { FeatureModifierId , OmvDecoderOptions , OmvFeatureFilterDescription , VECTOR_TILE_DECODER_SERVICE_TYPE } from "./OmvDecoderDefs" ; import { APIFormat , AuthenticationMethod , OmvRestClient , OmvRestClientParameters } from "./OmvRestClient" ; const logger = LoggerManager . instance . create ( "VectorTileDataSource" ) ; export interface VectorTileFactory { /** Create an instance of  {@link @here/harp-mapview#Tile} or a subclass.  createTile ( dataSource , tileKey ) : Tile ; } export interface VectorTileDataSourceParameters extends DataSourceOptions , Omit < TileDataSourceOptions , "dataProvider" | "tilingScheme" > { /**
     * If set to `true`, features that have no technique in the theme will be printed to the console
     * (can be excessive!).
     */ showMissingTechniques ? : boolean ; deprecated createTileInfo ? : boolean ; /**
     * Optionally specify the DataProvider that should be used.
     */ dataProvider ? : DataProvider ; deprecated gatherFeatureIds ? : boolean ; /**
     * Gather feature attributes from `OmvData`. Defaults to `false`.
     */ gatherFeatureAttributes ? : boolean ; deprecated gatherRoadSegments ? : boolean ; /**
     * If not set to `false`, very short text labels will be skipped during decoding based on a
     * heuristic.
     */ skipShortLabels ? : boolean ; remarks It has to be generated with the help of the [[OmvFeatureFilterDescriptionBuilder]]
     * (to guarantee correctness). This parameter gets applied to the decoder used in the
     *  VectorTileDataSource which might be shared between
     * various  VectorTileDataSource s.
      filterDescr ? : OmvFeatureFilterDescription ; /**
     * Optional, custom factory for  {@link @here/harp-mapview#Tile} instances created
     * by this  VectorTileDataSource .
      tileFactory ? : TileFactory < Tile > ; remarks note This parameter gets applied to the decoder used in the  VectorTileDataSource * which might be shared between various  VectorTileDataSource s.
      featureModifierId ? : FeatureModifierId ; see featureModifiers politicalView ? : string ; /**
     * Indicates whether overlay on elevation is enabled. Defaults to `false`.
     */ enableElevationOverlay ? : boolean ; remarks addGroundPlane ? : boolean ; defaultValue roundUpCoordinatesIfNeeded ? : boolean ; } /**
 * A helper function to retrieve the [[DataProvider]] from the
 *  VectorTileDataSource s parameters.
 *
 *  param params function getDataProvider ( params ) { if ( ( params as OmvWithCustomDataProvider ) . dataProvider ) { return ( params as OmvWithCustomDataProvider ) . dataProvider ; } else if ( ( params as OmvWithRestClientParams ) . baseUrl ?? ( params as OmvWithRestClientParams ) . url ) { return new OmvRestClient ( params as OmvRestClientParameters ) ; } else { throw new Error ( "OmvDataSource: missing url, baseUrl or dataProvider params" ) ; } } export type OmvWithRestClientParams = VectorTileDataSourceParameters & OmvRestClientParameters ; export type OmvWithCustomDataProvider = VectorTileDataSourceParameters & { dataProvider : DataProvider ; } ; let missingOmvDecoderServiceInfoEmitted = false ; /**
 * The default vector tile service.
 */ const hereVectorTileBaseUrl = "https://vector.hereapi.com/v2/vectortiles/base/mc" ; /**
 * Default options for the HERE Vector Tile service.
 */ const hereVectorTileDefaultOptions = { baseUrl : hereVectorTileBaseUrl , apiFormat : APIFormat . XYZOMV , styleSetName : "tilezen" , authenticationMethod : { method : AuthenticationMethod . QueryString , name : "apikey" } , copyrightInfo : [ { id : "here.com" , year : new Date ( ) . getFullYear ( ) , label : "HERE" , link : "https://legal.here.com/terms" } ] } ; const defaultOptions = new Map < string , OmvWithRestClientParams > ( [ [ hereVectorTileBaseUrl , hereVectorTileDefaultOptions ] ] ) ; param object function hasCustomDataProvider ( object ) { return object . dataProvider !== undefined ; } param params function completeDataSourceParameters ( params ) { if ( ! hasCustomDataProvider ( params ) && params . url === undefined ) { const baseUrl = params . baseUrl ?? hereVectorTileBaseUrl ; const completedParams = { ... defaultOptions . get ( baseUrl ) , ... params } ; return { ... completedParams , tilingScheme : webMercatorTilingScheme , dataProvider : new OmvRestClient ( completedParams ) } ; } return { ... params , tilingScheme : webMercatorTilingScheme , dataProvider : getDataProvider ( params ) } ; } example export class VectorTileDataSource extends TileDataSource { private readonly m_decoderOptions : OmvDecoderOptions ; constructor ( private readonly m_params ) { super ( m_params . tileFactory ?? new TileFactory ( Tile ) , { styleSetName : m_params . styleSetName ?? "omv" , concurrentDecoderServiceName : m_params . concurrentDecoderServiceName ?? VECTOR_TILE_DECODER_SERVICE_TYPE , minDataLevel : m_params . minDataLevel ?? 1 , maxDataLevel : m_params . maxDataLevel ?? 17 , storageLevelOffset : m_params . storageLevelOffset ?? - 1 , ... completeDataSourceParameters ( m_params ) } ) ; this . cacheable = true ; this . addGroundPlane = m_params . addGroundPlane === undefined || m_params . addGroundPlane === true ; let roundUpCoordinatesIfNeeded = m_params . roundUpCoordinatesIfNeeded ; if ( roundUpCoordinatesIfNeeded === undefined && ( m_params as Partial < OmvWithRestClientParams > ) ?. baseUrl === hereVectorTileBaseUrl ) { roundUpCoordinatesIfNeeded = true ; } this . m_decoderOptions = { showMissingTechniques : this . m_params . showMissingTechniques === true , filterDescription : this . m_params . filterDescr , gatherFeatureAttributes : this . m_params . gatherFeatureAttributes === true , featureModifiers : this . m_params . featureModifierId ? [ this . m_params . featureModifierId ] : undefined , politicalView : this . m_params . politicalView , skipShortLabels : this . m_params . skipShortLabels , storageLevelOffset : m_params . storageLevelOffset ?? - 1 , enableElevationOverlay : this . m_params . enableElevationOverlay === true , roundUpCoordinatesIfNeeded } ; this . maxGeometryHeight = getOptionValue ( m_params . maxGeometryHeight , EarthConstants . MAX_BUILDING_HEIGHT ) ; this . minGeometryHeight = getOptionValue ( m_params . minGeometryHeight , 0 ) ; } @override  async connect ( ) { try { await super . connect ( ) ; } catch ( error ) { if ( error . message && WorkerServiceProtocol . isUnknownServiceError ( error ) && ! missingOmvDecoderServiceInfoEmitted ) { logger . info ( "Unable to create decoder service in worker. Use " + " 'OmvTileDecoderService.start();' in decoder script." ) ; missingOmvDecoderServiceInfoEmitted = true ; } throw typeof error === "string" ? new Error ( error ) : error ; } this . configureDecoder ( undefined , this . m_decoderOptions ) ; } /**
     * Remove the current data filter.
     * Will be applied to the decoder, which might be shared with other omv datasources.
     */ removeDataFilter ( ) { this . configureDecoder ( undefined , { filterDescription : null } ) ; } /**
     * Set a new data filter. Can also be done during
     * the creation of an  VectorTileDataSource .
     * Will be applied to the decoder, which might be shared with other omv datasources.
     *
     *  param filterDescription setDataFilter ( filterDescription ) { this . m_decoderOptions . filterDescription = filterDescription !== null ? filterDescription : undefined ; this . configureDecoder ( undefined , { filterDescription , featureModifiers : this . m_decoderOptions . featureModifiers , politicalView : this . m_decoderOptions . politicalView } ) ; } @override  shouldPreloadTiles ( ) { return true ; } @override  setPoliticalView ( politicalView ? ) { politicalView = politicalView ?. toLowerCase ( ) ; if ( this . m_decoderOptions . politicalView !== politicalView ) { this . m_decoderOptions . politicalView = politicalView ; this . configureDecoder ( undefined , { filterDescription : this . m_decoderOptions . filterDescription , featureModifiers : this . m_decoderOptions . featureModifiers , politicalView : politicalView !== undefined ? politicalView : "" } ) ; } } @override  get storageLevelOffset ( ) { return super . storageLevelOffset ; } @override  set storageLevelOffset ( levelOffset ) { super . storageLevelOffset = levelOffset ; this . m_decoderOptions . storageLevelOffset = this . storageLevelOffset ; this . configureDecoder ( undefined , { storageLevelOffset : this . storageLevelOffset } ) ; } @override  setEnableElevationOverlay ( enable ) { if ( this . m_decoderOptions . enableElevationOverlay !== enable ) { this . m_decoderOptions . enableElevationOverlay = enable ; this . configureDecoder ( undefined , { enableElevationOverlay : enable } ) ; } } private configureDecoder ( options ? , customOptions ? ) { this . clearCache ( ) ; this . decoder . configure ( options , customOptions ) ; this . mapView . markTilesDirty ( this ) ; } }