UNPKG

@itwin/core-frontend

Version:
135 lines • 8.04 kB
/** @packageDocumentation * @module IModelConnection */ import { BeEvent, Dictionary, SortedArray } from "@itwin/core-bentley"; import { WritableXYAndZ, XYAndZ, XYZProps } from "@itwin/core-geometry"; import { GeoCoordinatesRequestProps, GeoCoordinatesResponseProps, GeographicCRSProps, IModelCoordinatesRequestProps, IModelCoordinatesResponseProps, PointWithStatus } from "@itwin/core-common"; import { IModelConnection } from "./IModelConnection"; /** Options used to create a [[CoordinateConverter]]. * @internal exported strictly for tests. */ export interface CoordinateConverterOptions { isIModelClosed: () => boolean; /** Asynchronously convert each point. The resultant array should have the same number and order of points as the input. */ requestPoints: (points: XYAndZ[]) => Promise<PointWithStatus[]>; /** Maximum number of points to include in each request. Default: 300. */ maxPointsPerRequest?: number; } type CoordinateConverterState = "idle" | "scheduled" | "in-flight"; /** Performs conversion of coordinates from one coordinate system to another. * A [[GeoConverter]] has a pair of these for converting between iModel coordinates and geographic coordinates. * Uses a cache to avoid repeatedly requesting the same points, and a batching strategy to avoid making frequent small requests. * The cache stores every point that was ever converted by [[convert]]. It is currently permitted to grow to unbounded size. * The batching works as follows: * When a conversion is requested via [[convert]], if all the requested points are in the cache, they are returned immediately. * Otherwise, any points not in the cache and not in the current in-flight request (if any) are placed onto the queue of pending requests. * A pending request is scheduled if one hasn't already been scheduled, via requestAnimationFrame. * In the animation frame callback, the pending requests are split into batches of no more than options.maxPointsPerRequest and dispatched to the backend. * Once the response is received, the results are loaded into and returned from the cache. * If more calls to convert occurred while the request was in flight, another request is dispatched. * @internal exported strictly for tests. */ export declare class CoordinateConverter { protected readonly _cache: Dictionary<XYAndZ, PointWithStatus>; protected _state: CoordinateConverterState; protected _pending: SortedArray<XYAndZ>; protected _inflight: SortedArray<XYAndZ>; protected _onCompleted: BeEvent<() => void>; protected readonly _scratchXYZ: { x: number; y: number; z: number; }; protected readonly _maxPointsPerRequest: number; protected readonly _isIModelClosed: () => boolean; protected readonly _requestPoints: (points: XYAndZ[]) => Promise<PointWithStatus[]>; protected _redispatchOnCompletion: boolean; get isIdle(): boolean; protected toXYAndZ(input: XYZProps, output: WritableXYAndZ): XYAndZ; constructor(opts: CoordinateConverterOptions); protected dispatch(): Promise<void>; protected enqueue(points: XYZProps[]): number; protected getFromCache(inputs: XYZProps[]): PointWithStatus[]; protected scheduleDispatch(): Promise<void>; convert(inputs: XYZProps[]): Promise<{ points: PointWithStatus[]; fromCache: number; }>; findCached(inputs: XYZProps[]): CachedIModelCoordinatesResponseProps; } /** Response to a request to obtain imodel coordinates from cache. * @internal */ export interface CachedIModelCoordinatesResponseProps { /** An array of the same length as the input array, with undefined entries at indices corresponding to points not found in cache. */ result: Array<PointWithStatus | undefined>; /** An array of points in the input array which were not found in the cache, or undefined if all points were found in the cache. */ missing?: XYZProps[]; } /** Options used to create a [[GeoConverter]]. * @internal exported strictly for tests. */ export interface GeoConverterOptions { readonly datum: string; isIModelClosed: () => boolean; toIModelCoords: (request: IModelCoordinatesRequestProps) => Promise<PointWithStatus[]>; fromIModelCoords: (request: GeoCoordinatesRequestProps) => Promise<PointWithStatus[]>; } /** An object capable of communicating with the backend to convert between coordinates in a geographic coordinate system and coordinates in an [[IModelConnection]]'s own coordinate system. * @see [[GeoServices.getConverter]] to obtain a converter. * @see [GeographicCRS]($common) for more information about geographic coordinate reference systems. * @public */ export declare class GeoConverter { private readonly _geoToIModel; private readonly _iModelToGeo; /** Used for removing this converter from GeoServices' cache after all requests are completed. * @internal */ readonly onAllRequestsCompleted: BeEvent<() => void>; /** @internal */ constructor(opts: GeoConverterOptions); /** Convert the specified geographic coordinates into iModel coordinates. */ convertToIModelCoords(geoPoints: XYZProps[]): Promise<PointWithStatus[]>; /** Convert the specified iModel coordinates into geographic coordinates. */ convertFromIModelCoords(iModelCoords: XYZProps[]): Promise<PointWithStatus[]>; /** @internal */ getIModelCoordinatesFromGeoCoordinates(geoPoints: XYZProps[]): Promise<IModelCoordinatesResponseProps>; /** @internal */ getGeoCoordinatesFromIModelCoordinates(iModelPoints: XYZProps[]): Promise<GeoCoordinatesResponseProps>; private checkCompletion; /** @internal */ getCachedIModelCoordinatesFromGeoCoordinates(geoPoints: XYZProps[]): CachedIModelCoordinatesResponseProps; } /** @internal */ export type GeoServicesOptions = Omit<GeoConverterOptions, "datum">; /** The Geographic Services available for an [[IModelConnection]]. * @see [[IModelConnection.geoServices]] to obtain the GeoServices for a specific iModel. * @public */ export declare class GeoServices { private readonly _options; /** Each GeoConverter has its own independent request queue and cache of previously-converted points. * Some callers like RealityTileTree obtain a single GeoConverter and reuse it throughout their own lifetime. Therefore they benefit from both batching and caching, and * the cache gets deleted once the RealityTileTree becomes disused. * * Other callers like IModelConnection.spatialToCartographic obtain a new GeoConverter every time they need one, use it to convert a single point(!), and then discard the converter. * This entirely prevents batching - e.g., calling spatialToCartographic 20 times in one frame results in 20 http requests. * To address that, we cache each GeoConverter returned by getConverter until it has converted at least one point and has no further outstanding conversion requests. * In this way, the converter lives for as long as (and no longer than) any caller is awaiting conversion to/from its datum - it and its cache are deleted once it becomes disused. * This makes the coordinate caching generally less useful, but at least bounded - and maximizes batching of requests. */ private readonly _cache; /** @internal */ constructor(options: GeoServicesOptions); /** @internal */ static createForIModel(iModel: IModelConnection): GeoServices; /** Obtain a converter that can convert between a geographic coordinate system and the iModel's own coordinate system. * @param datumOrGCRS The name or JSON representation of the geographic coordinate system datum - for example, "WGS84". * @returns a converter, or `undefined` if the iModel is not open. * @note A [[BlankConnection]] has no connection to a backend, so it is never "open"; therefore it always returns `undefined`. */ getConverter(datumOrGCRS?: string | GeographicCRSProps): GeoConverter | undefined; } export {}; //# sourceMappingURL=GeoServices.d.ts.map