@itwin/map-layers-formats 4.6.0-dev.18 → 4.6.0-dev.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/lib/cjs/ArcGisFeature/ArcGisFeatureProvider.d.ts +15 -6
  2. package/lib/cjs/ArcGisFeature/ArcGisFeatureProvider.d.ts.map +1 -1
  3. package/lib/cjs/ArcGisFeature/ArcGisFeatureProvider.js +61 -51
  4. package/lib/cjs/ArcGisFeature/ArcGisFeatureProvider.js.map +1 -1
  5. package/lib/cjs/ArcGisFeature/ArcGisFeatureReader.d.ts +7 -11
  6. package/lib/cjs/ArcGisFeature/ArcGisFeatureReader.d.ts.map +1 -1
  7. package/lib/cjs/ArcGisFeature/ArcGisFeatureReader.js +3 -19
  8. package/lib/cjs/ArcGisFeature/ArcGisFeatureReader.js.map +1 -1
  9. package/lib/cjs/ArcGisFeature/ArcGisJsonFeatureReader.d.ts +3 -3
  10. package/lib/cjs/ArcGisFeature/ArcGisJsonFeatureReader.d.ts.map +1 -1
  11. package/lib/cjs/ArcGisFeature/ArcGisJsonFeatureReader.js +3 -4
  12. package/lib/cjs/ArcGisFeature/ArcGisJsonFeatureReader.js.map +1 -1
  13. package/lib/cjs/ArcGisFeature/ArcGisPbfFeatureReader.d.ts +3 -3
  14. package/lib/cjs/ArcGisFeature/ArcGisPbfFeatureReader.d.ts.map +1 -1
  15. package/lib/cjs/ArcGisFeature/ArcGisPbfFeatureReader.js +2 -3
  16. package/lib/cjs/ArcGisFeature/ArcGisPbfFeatureReader.js.map +1 -1
  17. package/lib/cjs/ArcGisFeature/ArcGisSymbologyRenderer.d.ts +35 -15
  18. package/lib/cjs/ArcGisFeature/ArcGisSymbologyRenderer.d.ts.map +1 -1
  19. package/lib/cjs/ArcGisFeature/ArcGisSymbologyRenderer.js +53 -47
  20. package/lib/cjs/ArcGisFeature/ArcGisSymbologyRenderer.js.map +1 -1
  21. package/lib/cjs/ArcGisFeature/EsriSymbology.d.ts +2 -1
  22. package/lib/cjs/ArcGisFeature/EsriSymbology.d.ts.map +1 -1
  23. package/lib/cjs/ArcGisFeature/EsriSymbology.js +2 -1
  24. package/lib/cjs/ArcGisFeature/EsriSymbology.js.map +1 -1
  25. package/lib/cjs/Feature/DefaultMarkerIcon.d.ts +10 -0
  26. package/lib/cjs/Feature/DefaultMarkerIcon.d.ts.map +1 -0
  27. package/lib/cjs/Feature/DefaultMarkerIcon.js +31 -0
  28. package/lib/cjs/Feature/DefaultMarkerIcon.js.map +1 -0
  29. package/lib/cjs/Feature/FeatureCanvasRenderer.d.ts +20 -0
  30. package/lib/cjs/Feature/FeatureCanvasRenderer.d.ts.map +1 -0
  31. package/lib/cjs/{ArcGisFeature/ArcGisCanvasRenderer.js → Feature/FeatureCanvasRenderer.js} +7 -6
  32. package/lib/cjs/Feature/FeatureCanvasRenderer.js.map +1 -0
  33. package/lib/cjs/Feature/FeatureInfoReader.d.ts +11 -0
  34. package/lib/cjs/Feature/FeatureInfoReader.d.ts.map +1 -0
  35. package/lib/cjs/Feature/FeatureInfoReader.js +34 -0
  36. package/lib/cjs/Feature/FeatureInfoReader.js.map +1 -0
  37. package/lib/cjs/Feature/FeatureSymbology.d.ts +8 -0
  38. package/lib/cjs/Feature/FeatureSymbology.d.ts.map +1 -0
  39. package/lib/cjs/Feature/FeatureSymbology.js +12 -0
  40. package/lib/cjs/Feature/FeatureSymbology.js.map +1 -0
  41. package/lib/cjs/Feature/RandomMapColor.d.ts +8 -0
  42. package/lib/cjs/Feature/RandomMapColor.d.ts.map +1 -0
  43. package/lib/cjs/Feature/RandomMapColor.js +29 -0
  44. package/lib/cjs/Feature/RandomMapColor.js.map +1 -0
  45. package/lib/cjs/GeoJSON/GeoJSONGeometry.d.ts +18 -0
  46. package/lib/cjs/GeoJSON/GeoJSONGeometry.d.ts.map +1 -0
  47. package/lib/cjs/GeoJSON/GeoJSONGeometry.js +11 -0
  48. package/lib/cjs/GeoJSON/GeoJSONGeometry.js.map +1 -0
  49. package/lib/cjs/GeoJSON/GeoJSONGeometryReader.d.ts +11 -0
  50. package/lib/cjs/GeoJSON/GeoJSONGeometryReader.d.ts.map +1 -0
  51. package/lib/cjs/GeoJSON/GeoJSONGeometryReader.js +83 -0
  52. package/lib/cjs/GeoJSON/GeoJSONGeometryReader.js.map +1 -0
  53. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesFormat.d.ts +9 -0
  54. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesFormat.d.ts.map +1 -0
  55. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesFormat.js +94 -0
  56. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesFormat.js.map +1 -0
  57. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesProvider.d.ts +54 -0
  58. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesProvider.d.ts.map +1 -0
  59. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesProvider.js +477 -0
  60. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesProvider.js.map +1 -0
  61. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesReader.d.ts +23 -0
  62. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesReader.d.ts.map +1 -0
  63. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesReader.js +139 -0
  64. package/lib/cjs/OgcApiFeatures/OgcApiFeaturesReader.js.map +1 -0
  65. package/lib/cjs/mapLayersFormats.d.ts.map +1 -1
  66. package/lib/cjs/mapLayersFormats.js +4 -1
  67. package/lib/cjs/mapLayersFormats.js.map +1 -1
  68. package/lib/esm/ArcGisFeature/ArcGisFeatureProvider.d.ts +15 -6
  69. package/lib/esm/ArcGisFeature/ArcGisFeatureProvider.d.ts.map +1 -1
  70. package/lib/esm/ArcGisFeature/ArcGisFeatureProvider.js +61 -51
  71. package/lib/esm/ArcGisFeature/ArcGisFeatureProvider.js.map +1 -1
  72. package/lib/esm/ArcGisFeature/ArcGisFeatureReader.d.ts +7 -11
  73. package/lib/esm/ArcGisFeature/ArcGisFeatureReader.d.ts.map +1 -1
  74. package/lib/esm/ArcGisFeature/ArcGisFeatureReader.js +3 -19
  75. package/lib/esm/ArcGisFeature/ArcGisFeatureReader.js.map +1 -1
  76. package/lib/esm/ArcGisFeature/ArcGisJsonFeatureReader.d.ts +3 -3
  77. package/lib/esm/ArcGisFeature/ArcGisJsonFeatureReader.d.ts.map +1 -1
  78. package/lib/esm/ArcGisFeature/ArcGisJsonFeatureReader.js +3 -4
  79. package/lib/esm/ArcGisFeature/ArcGisJsonFeatureReader.js.map +1 -1
  80. package/lib/esm/ArcGisFeature/ArcGisPbfFeatureReader.d.ts +3 -3
  81. package/lib/esm/ArcGisFeature/ArcGisPbfFeatureReader.d.ts.map +1 -1
  82. package/lib/esm/ArcGisFeature/ArcGisPbfFeatureReader.js +2 -3
  83. package/lib/esm/ArcGisFeature/ArcGisPbfFeatureReader.js.map +1 -1
  84. package/lib/esm/ArcGisFeature/ArcGisSymbologyRenderer.d.ts +35 -15
  85. package/lib/esm/ArcGisFeature/ArcGisSymbologyRenderer.d.ts.map +1 -1
  86. package/lib/esm/ArcGisFeature/ArcGisSymbologyRenderer.js +51 -45
  87. package/lib/esm/ArcGisFeature/ArcGisSymbologyRenderer.js.map +1 -1
  88. package/lib/esm/ArcGisFeature/EsriSymbology.d.ts +2 -1
  89. package/lib/esm/ArcGisFeature/EsriSymbology.d.ts.map +1 -1
  90. package/lib/esm/ArcGisFeature/EsriSymbology.js +2 -1
  91. package/lib/esm/ArcGisFeature/EsriSymbology.js.map +1 -1
  92. package/lib/esm/Feature/DefaultMarkerIcon.d.ts +10 -0
  93. package/lib/esm/Feature/DefaultMarkerIcon.d.ts.map +1 -0
  94. package/lib/esm/Feature/DefaultMarkerIcon.js +27 -0
  95. package/lib/esm/Feature/DefaultMarkerIcon.js.map +1 -0
  96. package/lib/esm/Feature/FeatureCanvasRenderer.d.ts +20 -0
  97. package/lib/esm/Feature/FeatureCanvasRenderer.d.ts.map +1 -0
  98. package/lib/esm/{ArcGisFeature/ArcGisCanvasRenderer.js → Feature/FeatureCanvasRenderer.js} +6 -5
  99. package/lib/esm/Feature/FeatureCanvasRenderer.js.map +1 -0
  100. package/lib/esm/Feature/FeatureInfoReader.d.ts +11 -0
  101. package/lib/esm/Feature/FeatureInfoReader.d.ts.map +1 -0
  102. package/lib/esm/Feature/FeatureInfoReader.js +30 -0
  103. package/lib/esm/Feature/FeatureInfoReader.js.map +1 -0
  104. package/lib/esm/Feature/FeatureSymbology.d.ts +8 -0
  105. package/lib/esm/Feature/FeatureSymbology.d.ts.map +1 -0
  106. package/lib/esm/Feature/FeatureSymbology.js +8 -0
  107. package/lib/esm/Feature/FeatureSymbology.js.map +1 -0
  108. package/lib/esm/Feature/RandomMapColor.d.ts +8 -0
  109. package/lib/esm/Feature/RandomMapColor.d.ts.map +1 -0
  110. package/lib/esm/Feature/RandomMapColor.js +26 -0
  111. package/lib/esm/Feature/RandomMapColor.js.map +1 -0
  112. package/lib/esm/GeoJSON/GeoJSONGeometry.d.ts +18 -0
  113. package/lib/esm/GeoJSON/GeoJSONGeometry.d.ts.map +1 -0
  114. package/lib/esm/GeoJSON/GeoJSONGeometry.js +7 -0
  115. package/lib/esm/GeoJSON/GeoJSONGeometry.js.map +1 -0
  116. package/lib/esm/GeoJSON/GeoJSONGeometryReader.d.ts +11 -0
  117. package/lib/esm/GeoJSON/GeoJSONGeometryReader.d.ts.map +1 -0
  118. package/lib/esm/GeoJSON/GeoJSONGeometryReader.js +79 -0
  119. package/lib/esm/GeoJSON/GeoJSONGeometryReader.js.map +1 -0
  120. package/lib/esm/OgcApiFeatures/OgcApiFeaturesFormat.d.ts +9 -0
  121. package/lib/esm/OgcApiFeatures/OgcApiFeaturesFormat.d.ts.map +1 -0
  122. package/lib/esm/OgcApiFeatures/OgcApiFeaturesFormat.js +91 -0
  123. package/lib/esm/OgcApiFeatures/OgcApiFeaturesFormat.js.map +1 -0
  124. package/lib/esm/OgcApiFeatures/OgcApiFeaturesProvider.d.ts +54 -0
  125. package/lib/esm/OgcApiFeatures/OgcApiFeaturesProvider.d.ts.map +1 -0
  126. package/lib/esm/OgcApiFeatures/OgcApiFeaturesProvider.js +473 -0
  127. package/lib/esm/OgcApiFeatures/OgcApiFeaturesProvider.js.map +1 -0
  128. package/lib/esm/OgcApiFeatures/OgcApiFeaturesReader.d.ts +23 -0
  129. package/lib/esm/OgcApiFeatures/OgcApiFeaturesReader.d.ts.map +1 -0
  130. package/lib/esm/OgcApiFeatures/OgcApiFeaturesReader.js +135 -0
  131. package/lib/esm/OgcApiFeatures/OgcApiFeaturesReader.js.map +1 -0
  132. package/lib/esm/mapLayersFormats.d.ts.map +1 -1
  133. package/lib/esm/mapLayersFormats.js +4 -1
  134. package/lib/esm/mapLayersFormats.js.map +1 -1
  135. package/package.json +15 -13
  136. package/lib/cjs/ArcGisFeature/ArcGisCanvasRenderer.d.ts +0 -19
  137. package/lib/cjs/ArcGisFeature/ArcGisCanvasRenderer.d.ts.map +0 -1
  138. package/lib/cjs/ArcGisFeature/ArcGisCanvasRenderer.js.map +0 -1
  139. package/lib/esm/ArcGisFeature/ArcGisCanvasRenderer.d.ts +0 -19
  140. package/lib/esm/ArcGisFeature/ArcGisCanvasRenderer.d.ts.map +0 -1
  141. package/lib/esm/ArcGisFeature/ArcGisCanvasRenderer.js.map +0 -1
@@ -0,0 +1,91 @@
1
+ import { appendQueryParams, ImageryMapLayerFormat, MapLayerSourceStatus, setBasicAuthorization } from "@itwin/core-frontend";
2
+ import { OgcApiFeaturesProvider } from "./OgcApiFeaturesProvider";
3
+ /** @internal */
4
+ class OgcApiFeaturesMapLayerFormat extends ImageryMapLayerFormat {
5
+ static createImageryProvider(settings) { return new OgcApiFeaturesProvider(settings); }
6
+ static async validate(args) {
7
+ const { source } = args;
8
+ const { userName, password } = source;
9
+ let status = MapLayerSourceStatus.InvalidUrl;
10
+ try {
11
+ let headers;
12
+ if (userName && password) {
13
+ headers = new Headers();
14
+ setBasicAuthorization(headers, userName, password);
15
+ }
16
+ const opts = {
17
+ method: "GET",
18
+ headers,
19
+ };
20
+ let url = appendQueryParams(source.url, source.savedQueryParams);
21
+ url = appendQueryParams(url, source.unsavedQueryParams);
22
+ let response = await fetch(url, opts);
23
+ let json = await response.json();
24
+ if (!json) {
25
+ return { status };
26
+ }
27
+ const createCollectionsList = (data) => {
28
+ let array;
29
+ for (const collection of data.collections) {
30
+ if (collection.itemType === "feature") {
31
+ const subLayerProps = {
32
+ id: collection.id,
33
+ name: collection.id,
34
+ title: collection.title,
35
+ visible: true,
36
+ parent: undefined,
37
+ children: undefined,
38
+ };
39
+ if (array)
40
+ array.push(subLayerProps);
41
+ else
42
+ array = [subLayerProps];
43
+ }
44
+ }
45
+ return array;
46
+ };
47
+ let subLayers;
48
+ if (Array.isArray(json.collections)) {
49
+ subLayers = createCollectionsList(json);
50
+ status = MapLayerSourceStatus.Valid;
51
+ }
52
+ else if (json.itemType === "feature" || json.type === "FeatureCollection") {
53
+ // We expect one of the following URL:
54
+ // http://server/collections/<collectionName>
55
+ // http://server/collections/<collectionName>/items
56
+ subLayers = [{
57
+ id: json.id,
58
+ name: json.id,
59
+ title: json.title,
60
+ visible: true,
61
+ parent: undefined,
62
+ children: undefined,
63
+ }];
64
+ status = MapLayerSourceStatus.Valid;
65
+ }
66
+ else if (Array.isArray(json.links)) {
67
+ // This might be the main landing page
68
+ const collectionsLink = json.links.find((link) => link.rel.includes("data") && link.type === "application/json");
69
+ let collectionsUrl = appendQueryParams(collectionsLink.href, source.savedQueryParams);
70
+ collectionsUrl = appendQueryParams(collectionsUrl, source.unsavedQueryParams);
71
+ response = await fetch(collectionsUrl, opts);
72
+ json = await response.json();
73
+ if (Array.isArray(json.collections)) {
74
+ subLayers = createCollectionsList(json);
75
+ status = MapLayerSourceStatus.Valid;
76
+ }
77
+ }
78
+ return { status, subLayers };
79
+ }
80
+ catch (err) {
81
+ status = MapLayerSourceStatus.InvalidUrl;
82
+ if (err?.status === 401) {
83
+ status = ((userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth);
84
+ }
85
+ return { status };
86
+ }
87
+ }
88
+ }
89
+ OgcApiFeaturesMapLayerFormat.formatId = "OgcApiFeatures";
90
+ export { OgcApiFeaturesMapLayerFormat };
91
+ //# sourceMappingURL=OgcApiFeaturesFormat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OgcApiFeaturesFormat.js","sourceRoot":"","sources":["../../../src/OgcApiFeatures/OgcApiFeaturesFormat.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\nimport { ImageMapLayerSettings, MapSubLayerProps } from \"@itwin/core-common\";\r\nimport { appendQueryParams, ImageryMapLayerFormat, MapLayerImageryProvider, MapLayerSourceStatus, MapLayerSourceValidation, setBasicAuthorization, ValidateSourceArgs } from \"@itwin/core-frontend\";\r\nimport { OgcApiFeaturesProvider } from \"./OgcApiFeaturesProvider\";\r\n\r\n/** @internal */\r\nexport class OgcApiFeaturesMapLayerFormat extends ImageryMapLayerFormat {\r\n public static override formatId = \"OgcApiFeatures\";\r\n public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { return new OgcApiFeaturesProvider(settings); }\r\n\r\n public static override async validate(args: ValidateSourceArgs): Promise<MapLayerSourceValidation> {\r\n\r\n const {source} = args;\r\n const { userName, password } = source;\r\n let status = MapLayerSourceStatus.InvalidUrl;\r\n try {\r\n\r\n let headers: Headers | undefined;\r\n if (userName && password) {\r\n headers = new Headers();\r\n setBasicAuthorization(headers, userName, password);\r\n }\r\n const opts: RequestInit = {\r\n method: \"GET\",\r\n headers,\r\n };\r\n\r\n let url = appendQueryParams(source.url, source.savedQueryParams);\r\n url = appendQueryParams(url, source.unsavedQueryParams);\r\n let response = await fetch(url, opts);\r\n let json = await response.json();\r\n if (!json) {\r\n return { status };\r\n }\r\n\r\n const createCollectionsList = (data: any) => {\r\n let array: MapSubLayerProps[] | undefined;\r\n for (const collection of data.collections) {\r\n if (collection.itemType === \"feature\") {\r\n const subLayerProps = {\r\n id: collection.id,\r\n name: collection.id,\r\n title: collection.title,\r\n visible: true,\r\n parent: undefined,\r\n children: undefined,\r\n };\r\n if (array)\r\n array.push(subLayerProps);\r\n else\r\n array = [subLayerProps];\r\n }\r\n }\r\n return array;\r\n };\r\n\r\n let subLayers: MapSubLayerProps[] | undefined;\r\n if (Array.isArray(json.collections)) {\r\n subLayers = createCollectionsList(json);\r\n status = MapLayerSourceStatus.Valid;\r\n } else if (json.itemType === \"feature\" || json.type === \"FeatureCollection\") {\r\n // We expect one of the following URL:\r\n // http://server/collections/<collectionName>\r\n // http://server/collections/<collectionName>/items\r\n subLayers = [{\r\n id: json.id,\r\n name: json.id,\r\n title: json.title,\r\n visible: true,\r\n parent: undefined,\r\n children: undefined,\r\n }];\r\n status = MapLayerSourceStatus.Valid;\r\n } else if (Array.isArray(json.links)) {\r\n // This might be the main landing page\r\n const collectionsLink = json.links.find((link: any)=> link.rel.includes(\"data\") && link.type === \"application/json\");\r\n let collectionsUrl = appendQueryParams(collectionsLink.href, source.savedQueryParams);\r\n collectionsUrl = appendQueryParams(collectionsUrl, source.unsavedQueryParams);\r\n response = await fetch(collectionsUrl, opts);\r\n json = await response.json();\r\n if (Array.isArray(json.collections)) {\r\n subLayers = createCollectionsList(json);\r\n status = MapLayerSourceStatus.Valid;\r\n }\r\n\r\n }\r\n\r\n return { status, subLayers };\r\n\r\n } catch (err: any) {\r\n status = MapLayerSourceStatus.InvalidUrl;\r\n if (err?.status === 401) {\r\n status = ((userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth);\r\n }\r\n return { status};\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,54 @@
1
+ import { HitDetail, ImageryMapTileTree, MapFeatureInfoOptions, MapLayerFeatureInfo, MapLayerImageryProvider, QuadId } from "@itwin/core-frontend";
2
+ import { EsriSymbol } from "../ArcGisFeature/EsriSymbology";
3
+ import { Cartographic, ImageMapLayerSettings, ImageSource } from "@itwin/core-common";
4
+ import { FeatureDefaultSymbology } from "../Feature/FeatureSymbology";
5
+ import { RandomMapColor } from "../Feature/RandomMapColor";
6
+ /** Provide tiles from a ESRI ArcGIS Feature service
7
+ * @internal
8
+ */
9
+ export declare class DefaultOgcSymbology implements FeatureDefaultSymbology {
10
+ private static readonly _defaultPMSProps;
11
+ private _defaultPMS;
12
+ private static readonly _defaultSLSProps;
13
+ private _defaultSLS;
14
+ private static readonly _defaultSFSProps;
15
+ private _defaultSFS;
16
+ constructor(randomColor?: RandomMapColor);
17
+ initialize(): Promise<void>;
18
+ getSymbology(geometryType: string): EsriSymbol;
19
+ }
20
+ /** @internal */
21
+ export declare class OgcApiFeaturesProvider extends MapLayerImageryProvider {
22
+ private readonly _drawDebugInfo;
23
+ private readonly _limitParamMaxValue;
24
+ private readonly _tiledModeMinLod;
25
+ private readonly _staticModeFetchTimeout;
26
+ private readonly _tileModeFetchTimeout;
27
+ private readonly _forceTileMode;
28
+ private _spatialIdx;
29
+ private _defaultSymbol;
30
+ private _renderer;
31
+ private _collectionUrl;
32
+ private _itemsUrl;
33
+ private readonly _itemsCrs;
34
+ private _queryables;
35
+ serviceJson: any;
36
+ private _staticData;
37
+ constructor(settings: ImageMapLayerSettings);
38
+ get supportsMapFeatureInfo(): boolean;
39
+ get minimumZoomLevel(): number;
40
+ get staticMode(): boolean;
41
+ initialize(): Promise<void>;
42
+ private fetchMetadata;
43
+ private fetchAllItems;
44
+ private fetchItems;
45
+ private indexStaticData;
46
+ get tileSize(): number;
47
+ constructUrl(_row: number, _column: number, _zoomLevel: number): Promise<string>;
48
+ drawTileDebugInfo(row: number, column: number, zoomLevel: number, context: CanvasRenderingContext2D): void;
49
+ computeTileWorld2CanvasTransform(row: number, column: number, zoomLevel: number): import("@itwin/core-geometry").Transform | undefined;
50
+ loadTile(row: number, column: number, zoomLevel: number): Promise<ImageSource | undefined>;
51
+ private createImageSourceFromDataURL;
52
+ getFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, _tree: ImageryMapTileTree, hit: HitDetail, options?: MapFeatureInfoOptions): Promise<void>;
53
+ }
54
+ //# sourceMappingURL=OgcApiFeaturesProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OgcApiFeaturesProvider.d.ts","sourceRoot":"","sources":["../../../src/OgcApiFeatures/OgcApiFeaturesProvider.ts"],"names":[],"mappings":"AAKA,OAAO,EAA2B,SAAS,EAAE,kBAAkB,EAAqB,qBAAqB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,EAAe,MAAM,sBAAsB,CAAC;AAC3M,OAAO,EAAqF,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC/I,OAAO,EAAE,YAAY,EAAY,qBAAqB,EAAE,WAAW,EAA8C,MAAM,oBAAoB,CAAC;AAM5I,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAM3D;;EAEE;AACF,qBAAa,mBAAoB,YAAW,uBAAuB;IAEjE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAQtC;IACF,OAAO,CAAC,WAAW,CAAU;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAKtC;IACF,OAAO,CAAC,WAAW,CAAU;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAKtC;IACF,OAAO,CAAC,WAAW,CAA0D;gBAE1D,WAAW,CAAC,EAAE,cAAc;IA4BlC,UAAU;IAKhB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU;CAUtD;AACD,gBAAgB;AAChB,qBAAa,sBAAuB,SAAQ,uBAAuB;IAGjE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAGxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IACvC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,cAAc,CAAiD;IACvE,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkD;IAC5E,OAAO,CAAC,WAAW,CAAM;IAElB,WAAW,EAAE,GAAG,CAAC;IACxB,OAAO,CAAC,WAAW,CAAsC;gBAE7C,QAAQ,EAAE,qBAAqB;IAI3C,IAAoB,sBAAsB,YAAkB;IAC5D,IAAoB,gBAAgB,IAAI,MAAM,CAA6E;IAC3H,IAAW,UAAU,IAAI,OAAO,CAA6E;IAEvF,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAyHnC,aAAa;YAMb,aAAa;YAQb,UAAU;YAqCV,eAAe;IA+D7B,IAAoB,QAAQ,IAAI,MAAM,CAAgB;IAGzC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItF,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB;IAUnG,gCAAgC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IA2BhE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAkFhH,OAAO,CAAC,4BAA4B;IAad,cAAc,CAAC,YAAY,EAAE,mBAAmB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAuC1M"}
@@ -0,0 +1,473 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { FeatureGraphicsRenderer, MapCartoRectangle, MapLayerImageryProvider } from "@itwin/core-frontend";
6
+ import { EsriPMS, EsriSFS, EsriSLS } from "../ArcGisFeature/EsriSymbology";
7
+ import { ColorDef, ImageSource, ImageSourceFormat, ServerError } from "@itwin/core-common";
8
+ import { Matrix4d, Point3d, Range2d } from "@itwin/core-geometry";
9
+ import { ArcGisSymbologyCanvasRenderer } from "../ArcGisFeature/ArcGisSymbologyRenderer";
10
+ import { FeatureCanvasRenderer } from "../Feature/FeatureCanvasRenderer";
11
+ import { base64StringToUint8Array, IModelStatus, Logger } from "@itwin/core-bentley";
12
+ import { OgcApiFeaturesReader } from "./OgcApiFeaturesReader";
13
+ import { RandomMapColor } from "../Feature/RandomMapColor";
14
+ import { DefaultMarkerIcon } from "../Feature/DefaultMarkerIcon";
15
+ const loggerCategory = "MapLayersFormats.OgcApiFeatures";
16
+ const dataUrlHeaderToken = "base64,";
17
+ /** Provide tiles from a ESRI ArcGIS Feature service
18
+ * @internal
19
+ */
20
+ class DefaultOgcSymbology {
21
+ constructor(randomColor) {
22
+ this._defaultSFS = EsriSFS.fromJSON(DefaultOgcSymbology._defaultSFSProps);
23
+ const color = randomColor ? randomColor.getColorDef() : ColorDef.blue;
24
+ this._defaultPMS = EsriPMS.fromJSON({
25
+ ...DefaultMarkerIcon.getContent(color),
26
+ type: "esriPMS",
27
+ url: "",
28
+ width: 16,
29
+ height: 24,
30
+ xoffset: 0,
31
+ yoffset: -12,
32
+ });
33
+ const randomColors = color.colors;
34
+ const newSLSProps = {
35
+ ...DefaultOgcSymbology._defaultSLSProps,
36
+ color: [randomColors.r, randomColors.g, randomColors.b, 255],
37
+ };
38
+ this._defaultSLS = EsriSLS.fromJSON(newSLSProps);
39
+ this._defaultSFS = EsriSFS.fromJSON({
40
+ ...DefaultOgcSymbology._defaultSFSProps,
41
+ color: [randomColors.r, randomColors.g, randomColors.b, 255],
42
+ outline: {
43
+ ...DefaultOgcSymbology._defaultSLSProps,
44
+ color: [0, 0, 0, 255],
45
+ },
46
+ });
47
+ }
48
+ async initialize() {
49
+ // Marker image need to be loaded upfront;
50
+ await this._defaultPMS.loadImage();
51
+ }
52
+ getSymbology(geometryType) {
53
+ if (geometryType === "LineString" || geometryType === "MultiLineString")
54
+ return this._defaultSLS;
55
+ else if (geometryType === "Polygon" || geometryType === "MultiPolygon")
56
+ return this._defaultSFS;
57
+ else if (geometryType === "Point" || geometryType === "MultiPoint")
58
+ return this._defaultPMS;
59
+ throw new Error(`Could not get default symbology for geometry type ${geometryType}`);
60
+ }
61
+ }
62
+ DefaultOgcSymbology._defaultPMSProps = {
63
+ type: "esriPMS",
64
+ url: "",
65
+ width: 16,
66
+ height: 24,
67
+ // We want the anchor point to be the bottom of the push pin, so apply offset on the y-axis (anchor point is already in the center of the icon)
68
+ xoffset: 0,
69
+ yoffset: -12,
70
+ };
71
+ DefaultOgcSymbology._defaultSLSProps = {
72
+ type: "esriSLS",
73
+ color: [0, 0, 255, 255],
74
+ width: 1,
75
+ style: "esriSLSSolid",
76
+ };
77
+ DefaultOgcSymbology._defaultSFSProps = {
78
+ type: "esriSFS",
79
+ color: [0, 0, 255, 255],
80
+ style: "esriSFSSolid",
81
+ outline: DefaultOgcSymbology._defaultSLSProps,
82
+ };
83
+ export { DefaultOgcSymbology };
84
+ /** @internal */
85
+ export class OgcApiFeaturesProvider extends MapLayerImageryProvider {
86
+ constructor(settings) {
87
+ super(settings, true);
88
+ // Debug flags, should always be committed to FALSE !
89
+ this._drawDebugInfo = false;
90
+ /// ////////////////////////////
91
+ this._limitParamMaxValue = 10000; // This is documented in OGC Features specification; a single items request never returns more than 10 000 items
92
+ this._tiledModeMinLod = 14;
93
+ this._staticModeFetchTimeout = 10000;
94
+ this._tileModeFetchTimeout = 10000;
95
+ this._forceTileMode = false;
96
+ this._defaultSymbol = new DefaultOgcSymbology(new RandomMapColor());
97
+ this._collectionUrl = "";
98
+ this._itemsUrl = "";
99
+ this._itemsCrs = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"; // Fixed fow now
100
+ }
101
+ get supportsMapFeatureInfo() { return true; }
102
+ get minimumZoomLevel() { return this.staticMode ? super.minimumZoomLevel : this._tiledModeMinLod; }
103
+ get staticMode() { return !!(this._spatialIdx && this._staticData && !this._forceTileMode); }
104
+ async initialize() {
105
+ this._collectionUrl = this._settings.url;
106
+ let layerId;
107
+ // OGC Feature service request can only serve data for a single feature
108
+ // so if multiple sub-layer ids are specified, we pick the first one.
109
+ if (this._settings.subLayers && this._settings.subLayers.length > 0) {
110
+ layerId = this._settings.subLayers[0].id;
111
+ }
112
+ const readCollectionsPage = (data) => {
113
+ const collection = data.collections.find((col) => col.id === layerId);
114
+ const collectionLinks = collection?.links;
115
+ if (!collectionLinks) {
116
+ const msg = `Missing layer id or matching collection could not be found`;
117
+ Logger.logError(loggerCategory, msg);
118
+ throw new Error(msg);
119
+ }
120
+ const collectionLink = collectionLinks.find((link) => link.rel.includes("collection") && link.type === "application/json");
121
+ this._collectionUrl = collectionLink.href;
122
+ };
123
+ const layerIdMismatch = () => {
124
+ const msg = `Collection metadata and sub-layers id mismatch`;
125
+ Logger.logError(loggerCategory, msg);
126
+ throw new Error(msg);
127
+ };
128
+ let collectionMetadata;
129
+ let json = await this.fetchMetadata(this._settings.url);
130
+ if (json?.type === "FeatureCollection") {
131
+ // We landed on the items page, we need to look for the collection metadata url
132
+ if (Array.isArray(json.links)) {
133
+ const collectionLink = json.links.find((link) => link.rel.includes("collection") && link.type === "application/json");
134
+ this._collectionUrl = collectionLink.href;
135
+ }
136
+ }
137
+ else if (json.itemType === "feature") {
138
+ // We landed on a specific collection page.
139
+ collectionMetadata = json;
140
+ // Check if the collection id matches at least one sub-layer
141
+ if (this._settings.subLayers && this._settings.subLayers.length > 0) {
142
+ const subLayer = this._settings.subLayers.find((s) => s.id === collectionMetadata.id);
143
+ if (subLayer)
144
+ layerId = subLayer.id;
145
+ }
146
+ else {
147
+ // No sub-layers were specified, defaults to collection id.
148
+ layerId = collectionMetadata.id;
149
+ }
150
+ }
151
+ else if (Array.isArray(json.collections)) {
152
+ // We landed in the "Collections" page
153
+ // Find to find the specified layer id among the available collections
154
+ readCollectionsPage(json);
155
+ }
156
+ else if (Array.isArray(json.links)) {
157
+ // This might be the main landing page
158
+ // We need to find the the "Collections" page
159
+ const collectionsLink = json.links.find((link) => link.rel.includes("data") && link.type === "application/json");
160
+ if (!collectionsLink) {
161
+ Logger.logError(loggerCategory, "Could not find collections link");
162
+ throw new ServerError(IModelStatus.ValidationFailed, "");
163
+ }
164
+ json = await this.fetchMetadata(collectionsLink.href);
165
+ if (Array.isArray(json.collections)) {
166
+ readCollectionsPage(json);
167
+ }
168
+ }
169
+ // Read collection metadata
170
+ if (!collectionMetadata)
171
+ collectionMetadata = await this.fetchMetadata(this._collectionUrl);
172
+ if (layerId !== undefined && layerId !== collectionMetadata.id) {
173
+ layerIdMismatch();
174
+ }
175
+ // Read cartographic range
176
+ if (Array.isArray(collectionMetadata?.extent?.spatial?.bbox)
177
+ && collectionMetadata.extent.spatial.bbox.length > 0
178
+ && collectionMetadata.extent.spatial.crs === this._itemsCrs) {
179
+ const firstBbox = collectionMetadata.extent.spatial?.bbox[0];
180
+ this.cartoRange = MapCartoRectangle.fromDegrees(firstBbox[0], firstBbox[1], firstBbox[2], firstBbox[3]);
181
+ }
182
+ // Read important links
183
+ let queryablesHref;
184
+ let itemsHref;
185
+ if (Array.isArray(collectionMetadata?.links)) {
186
+ // Items links (Mandatory)
187
+ const itemsLink = collectionMetadata.links.find((link) => link.rel.includes("items") && link.type === "application/geo+json");
188
+ itemsHref = itemsLink.href;
189
+ // Queryables link (Optional)
190
+ const queryablesLink = collectionMetadata.links.find((link) => link.rel.includes("queryables") && link.type === "application/schema+json");
191
+ queryablesHref = queryablesLink.href;
192
+ }
193
+ if (itemsHref)
194
+ this._itemsUrl = itemsHref;
195
+ else {
196
+ const msg = "Unable to find items link on collection";
197
+ Logger.logError(loggerCategory, msg);
198
+ throw new Error(msg);
199
+ }
200
+ if (queryablesHref)
201
+ this._queryables = await this.fetchMetadata(queryablesHref);
202
+ if (!this._forceTileMode) {
203
+ const status = await this.fetchAllItems();
204
+ if (status) {
205
+ await this.indexStaticData();
206
+ }
207
+ }
208
+ await this._defaultSymbol.initialize(); // images must be loaded upfront
209
+ }
210
+ async fetchMetadata(url) {
211
+ const tmpUrl = this.appendCustomParams(url);
212
+ const response = await this.makeRequest(tmpUrl);
213
+ return response.json();
214
+ }
215
+ async fetchAllItems() {
216
+ const urlObj = new URL(this._itemsUrl);
217
+ urlObj.searchParams.append("limit", `${this._limitParamMaxValue}`);
218
+ const url = this.appendCustomParams(urlObj.toString());
219
+ this._staticData = await this.fetchItems(url, this._staticModeFetchTimeout);
220
+ return this._staticData ? true : false;
221
+ }
222
+ async fetchItems(url, timeout) {
223
+ let data;
224
+ let success = true;
225
+ try {
226
+ const fetchBegin = Date.now();
227
+ let tmpUrl = this.appendCustomParams(url);
228
+ let response = await this.makeTileRequest(tmpUrl, timeout);
229
+ let json = await response.json();
230
+ data = json;
231
+ // Follow "next" link if any
232
+ let nextLink = json.links?.find((link) => link.rel === "next");
233
+ while (nextLink && (Date.now() - fetchBegin) < timeout && success) {
234
+ tmpUrl = this.appendCustomParams(nextLink.href);
235
+ response = await this.makeTileRequest(tmpUrl, this._staticModeFetchTimeout);
236
+ json = await response.json();
237
+ if (json?.features)
238
+ data.features = this._staticData?.features ? [...this._staticData.features, ...json.features] : json.features;
239
+ else
240
+ success = false;
241
+ nextLink = json.links?.find((link) => link.rel === "next");
242
+ }
243
+ if (Date.now() - fetchBegin >= this._staticModeFetchTimeout) {
244
+ // We ran out of time, let switch to tile mode
245
+ success = false;
246
+ }
247
+ }
248
+ catch (e) {
249
+ success = false;
250
+ if (e instanceof DOMException && e.name === "AbortError") {
251
+ Logger.logInfo(loggerCategory, "Request to fetch all features time out, switching to tile mode.");
252
+ }
253
+ else {
254
+ Logger.logError(loggerCategory, "Unknown error occurred when fetching OgcApiFeatures data.");
255
+ }
256
+ }
257
+ return success ? data : undefined;
258
+ }
259
+ // Read features range and build in-memory spatial index
260
+ async indexStaticData() {
261
+ // UGLY IMPORT:
262
+ // flatbush only provides ECM modules, and since mocha is not very good with ECM modules,
263
+ // we need to have this special import, until we replace mocha with something else.
264
+ const flatbush = (await import("flatbush")).default;
265
+ let success = true;
266
+ try {
267
+ const datasetRange = new Range2d();
268
+ const buildPositionRange = (coords, range) => range.extendXY(coords[0], coords[1]);
269
+ const buildPositionArrayRange = (coords, range) => coords.forEach((position) => buildPositionRange(position, range));
270
+ const buildDoublePositionRange = (coords, range) => coords.forEach((position) => buildPositionArrayRange(position, range));
271
+ const buildTriplePositionRange = (coords, range) => coords.forEach((position) => buildDoublePositionRange(position, range));
272
+ const readGeomRange = (geom, range) => {
273
+ if (geom.type === "Point")
274
+ buildPositionRange(geom.coordinates, range);
275
+ else if (geom.type === "LineString" || geom.type === "MultiPoint")
276
+ buildPositionArrayRange(geom.coordinates, range);
277
+ else if (geom.type === "Polygon" || geom.type === "MultiLineString")
278
+ buildDoublePositionRange(geom.coordinates, range);
279
+ else if (geom.type === "MultiPolygon")
280
+ buildTriplePositionRange(geom.coordinates, range);
281
+ };
282
+ if (this._staticData && Array.isArray(this._staticData.features)) {
283
+ this._spatialIdx = new flatbush(this._staticData.features.length);
284
+ this._staticData.features.forEach((feature) => {
285
+ try {
286
+ if (feature.geometry.type === "LineString"
287
+ || feature.geometry.type === "MultiLineString"
288
+ || feature.geometry.type === "Point"
289
+ || feature.geometry.type === "MultiPoint"
290
+ || feature.geometry.type === "Polygon"
291
+ || feature.geometry.type === "MultiPolygon") {
292
+ readGeomRange(feature.geometry, datasetRange);
293
+ this._spatialIdx?.add(datasetRange.xLow, datasetRange.yLow, datasetRange.xHigh, datasetRange.yHigh);
294
+ datasetRange.setNull();
295
+ }
296
+ else if (feature.geometry.type === "GeometryCollection") {
297
+ feature.geometry.geometries.forEach((geom) => {
298
+ readGeomRange(geom, datasetRange);
299
+ this._spatialIdx?.add(datasetRange.xLow, datasetRange.yLow, datasetRange.xHigh, datasetRange.yHigh);
300
+ });
301
+ datasetRange.setNull();
302
+ }
303
+ }
304
+ catch (e) {
305
+ Logger.logInfo(loggerCategory, `Unknown error occurred indexing feature: ${e.message}`);
306
+ success = false;
307
+ }
308
+ });
309
+ if (success) {
310
+ this._spatialIdx.finish();
311
+ }
312
+ }
313
+ }
314
+ catch (_e) {
315
+ Logger.logError(loggerCategory, "Unknown error occurred when index static data");
316
+ success = false;
317
+ }
318
+ return success;
319
+ }
320
+ get tileSize() { return 512; }
321
+ // We don't use this method inside this provider (see constructFeatureUrl), but since this is an abstract method, we need to define something
322
+ async constructUrl(_row, _column, _zoomLevel) {
323
+ return "";
324
+ }
325
+ drawTileDebugInfo(row, column, zoomLevel, context) {
326
+ context.fillStyle = "cyan";
327
+ context.strokeRect(0, 0, this.tileSize, this.tileSize);
328
+ context.font = "30px Arial";
329
+ context.lineWidth = 5;
330
+ context.fillText(`${zoomLevel}-${row}-${column}`, 10, 50);
331
+ }
332
+ // Compute transform that provides coordinates in the canvas coordinate system (pixels, origin = top-left)
333
+ // from coordinate in world
334
+ computeTileWorld2CanvasTransform(row, column, zoomLevel) {
335
+ const tileExtentWorld4326 = this.getEPSG4326Extent(row, column, zoomLevel);
336
+ const worldTileWidth = tileExtentWorld4326.longitudeRight - tileExtentWorld4326.longitudeLeft;
337
+ const worldTileHeight = tileExtentWorld4326.latitudeTop - tileExtentWorld4326.latitudeBottom;
338
+ const canvasTileWidth = this.tileSize;
339
+ const canvasTileHeight = this.tileSize;
340
+ const world2CanvasRatioX = canvasTileWidth / worldTileWidth;
341
+ const world2CanvasRatioY = canvasTileHeight / worldTileHeight;
342
+ const worldTileOrigin = Point3d.create(tileExtentWorld4326.longitudeLeft, tileExtentWorld4326.latitudeBottom);
343
+ const worldTileExtent = Point3d.create(tileExtentWorld4326.longitudeRight, tileExtentWorld4326.latitudeTop);
344
+ const canvasTileOriginOffset = worldTileOrigin.clone();
345
+ const canvasTileExtentOffset = worldTileExtent.clone();
346
+ canvasTileOriginOffset.x *= world2CanvasRatioX;
347
+ canvasTileOriginOffset.y *= world2CanvasRatioY;
348
+ canvasTileExtentOffset.x *= world2CanvasRatioX;
349
+ canvasTileExtentOffset.y *= world2CanvasRatioY;
350
+ const xTranslate = -1 * canvasTileOriginOffset.x;
351
+ // Canvas origin is upper left corner, so we need to flip the y axis
352
+ const yTranslate = canvasTileExtentOffset.y; // y-axis flip
353
+ const yWorld2CanvasRatio = -1 * world2CanvasRatioY; // y-axis flip
354
+ const matrix = Matrix4d.createTranslationAndScaleXYZ(xTranslate, yTranslate, 0, world2CanvasRatioX, yWorld2CanvasRatio, 1);
355
+ return matrix.asTransform;
356
+ }
357
+ async loadTile(row, column, zoomLevel) {
358
+ const extent4326 = this.getEPSG4326Extent(row, column, zoomLevel);
359
+ let data;
360
+ if (this.staticMode) {
361
+ // Static data mode
362
+ const filteredData = { type: "FeatureCollection", features: [] };
363
+ this._spatialIdx?.search(extent4326.longitudeLeft, extent4326.latitudeBottom, extent4326.longitudeRight, extent4326.latitudeTop, (index) => {
364
+ filteredData.features.push(this._staticData.features[index]);
365
+ return true;
366
+ });
367
+ data = filteredData;
368
+ }
369
+ else {
370
+ // Tiled data mode
371
+ const extent4326Str = this.getEPSG4326TileExtentString(row, column, zoomLevel, false);
372
+ const urlObj = new URL(this._itemsUrl);
373
+ urlObj.searchParams.append("bbox", `${extent4326Str}`);
374
+ urlObj.searchParams.append("bbox-crs", this._itemsCrs);
375
+ urlObj.searchParams.append("limit", `${this._limitParamMaxValue}`);
376
+ const url = this.appendCustomParams(urlObj.toString());
377
+ try {
378
+ data = await this.fetchItems(url, this._tileModeFetchTimeout);
379
+ }
380
+ catch (_e) {
381
+ }
382
+ if (!data) {
383
+ Logger.logError(loggerCategory, "Could not fetch OgcApiFeatures data.");
384
+ }
385
+ }
386
+ if (!data || !Array.isArray(data.features) || data.features.length === 0) {
387
+ Logger.logInfo(loggerCategory, `No data to render for tile (${zoomLevel}/${row}/${column}).`);
388
+ }
389
+ // Rendering starts here
390
+ const canvas = document.createElement("canvas");
391
+ canvas.width = this.tileSize;
392
+ canvas.height = this.tileSize;
393
+ const ctx = canvas.getContext("2d");
394
+ if (ctx == null) {
395
+ Logger.logError(loggerCategory, "No canvas context available for loading tile.");
396
+ return undefined;
397
+ }
398
+ try {
399
+ // Compute transform if CoordinatesQuantization is not supported by service
400
+ const transfo = this.computeTileWorld2CanvasTransform(row, column, zoomLevel);
401
+ if (!transfo) {
402
+ Logger.logError(loggerCategory, `Could not compute data transformation for tile (${zoomLevel}/${row}/${column})`);
403
+ }
404
+ // Create the renderer
405
+ // Instead of passing a Transform oject to the render, it should be possible
406
+ // instead to set the Transform directly on the Canvas, when I tried the display was incorrect, floating point issue?
407
+ // const transfoRow = transfo!.toRows();
408
+ // ctx.setTransform(transfoRow[0][0], transfoRow[1][0], transfoRow[0][1], transfoRow[1][1], transfoRow[0][3], transfoRow[1][3]);
409
+ const symbRenderer = ArcGisSymbologyCanvasRenderer.create(this._renderer, this._defaultSymbol);
410
+ const renderer = new FeatureCanvasRenderer(ctx, symbRenderer, transfo);
411
+ const featureReader = new OgcApiFeaturesReader();
412
+ await featureReader.readAndRender(data, renderer);
413
+ if (this._drawDebugInfo)
414
+ this.drawTileDebugInfo(row, column, zoomLevel, ctx);
415
+ }
416
+ catch (e) {
417
+ Logger.logError(loggerCategory, `Exception occurred while loading tile (${zoomLevel}/${row}/${column}) : ${e}`);
418
+ }
419
+ try {
420
+ return this.createImageSourceFromDataURL(canvas.toDataURL("image/png"), ImageSourceFormat.Png);
421
+ }
422
+ catch (e) {
423
+ Logger.logError(loggerCategory, `Exception occurred while rendering tile (${zoomLevel}/${row}/${column}) : ${e}.`);
424
+ }
425
+ return undefined;
426
+ }
427
+ createImageSourceFromDataURL(dataUrl, format) {
428
+ if (!dataUrl)
429
+ return undefined;
430
+ const dataStartPos = dataUrl.indexOf(dataUrlHeaderToken) + dataUrlHeaderToken.length;
431
+ if (dataStartPos < 0)
432
+ return undefined;
433
+ const base64Png = dataUrl.substring(dataStartPos);
434
+ return new ImageSource(base64StringToUint8Array(base64Png), format);
435
+ }
436
+ async getFeatureInfo(featureInfos, quadId, carto, _tree, hit, options) {
437
+ const tileExtent = this.getEPSG4326Extent(quadId.row, quadId.column, quadId.level);
438
+ const tilePixelSizeX = (tileExtent.longitudeRight - tileExtent.longitudeLeft) / this.tileSize;
439
+ const tilePixelSizeY = (tileExtent.latitudeTop - tileExtent.latitudeBottom) / this.tileSize;
440
+ const tolerancePixel = options?.tolerance ?? 7;
441
+ const toleranceWorldX = tilePixelSizeX * tolerancePixel;
442
+ const toleranceWorldY = tilePixelSizeY * tolerancePixel;
443
+ // Note: We used to pass a single point as the query 'geometry' and leverage the 'distance' parameter, turns
444
+ // out that approach was a lot slower on some server compared to using a single envelope.
445
+ const bbox = {
446
+ longitudeLeft: carto.longitudeDegrees - toleranceWorldX, latitudeBottom: carto.latitudeDegrees - toleranceWorldY,
447
+ longitudeRight: carto.longitudeDegrees + toleranceWorldX, latitudeTop: carto.latitudeDegrees + toleranceWorldY,
448
+ };
449
+ const bboxStr = this.getEPSG4326ExtentString(bbox, false);
450
+ const urlObj = new URL(this._itemsUrl);
451
+ urlObj.searchParams.append("bbox", `${bboxStr}`);
452
+ urlObj.searchParams.append("bbox-crs", this._itemsCrs);
453
+ urlObj.searchParams.append("limit", `${this._limitParamMaxValue}`);
454
+ const url = this.appendCustomParams(urlObj.toString());
455
+ let data;
456
+ try {
457
+ data = await this.fetchItems(url, this._tileModeFetchTimeout);
458
+ }
459
+ catch (_e) {
460
+ }
461
+ if (!data) {
462
+ Logger.logError(loggerCategory, "Could not fetch OgcApiFeatures data.");
463
+ }
464
+ const featureReader = new OgcApiFeaturesReader();
465
+ await featureReader.readFeatureInfo({
466
+ collection: data,
467
+ layerSettings: this._settings,
468
+ queryables: this._queryables,
469
+ geomRenderer: new FeatureGraphicsRenderer({ viewport: hit.viewport, crs: "wgs84" })
470
+ }, featureInfos);
471
+ }
472
+ }
473
+ //# sourceMappingURL=OgcApiFeaturesProvider.js.map