@loaders.gl/i3s 4.0.0-alpha.1 → 4.0.0-alpha.11

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 (242) hide show
  1. package/dist/arcgis-webscene-loader.d.ts +7 -0
  2. package/dist/arcgis-webscene-loader.d.ts.map +1 -0
  3. package/dist/arcgis-webscene-loader.js +28 -0
  4. package/dist/bundle.d.ts +2 -0
  5. package/dist/bundle.d.ts.map +1 -0
  6. package/dist/bundle.js +2 -2
  7. package/dist/dist.min.js +15501 -0
  8. package/dist/es5/arcgis-webscene-loader.js +40 -0
  9. package/dist/es5/arcgis-webscene-loader.js.map +1 -0
  10. package/dist/es5/bundle.js +6 -0
  11. package/dist/es5/bundle.js.map +1 -0
  12. package/dist/es5/i3s-attribute-loader.js +195 -0
  13. package/dist/es5/i3s-attribute-loader.js.map +1 -0
  14. package/dist/es5/i3s-building-scene-layer-loader.js +46 -0
  15. package/dist/es5/i3s-building-scene-layer-loader.js.map +1 -0
  16. package/dist/es5/i3s-content-loader.js +56 -0
  17. package/dist/es5/i3s-content-loader.js.map +1 -0
  18. package/dist/es5/i3s-loader.js +193 -0
  19. package/dist/es5/i3s-loader.js.map +1 -0
  20. package/dist/es5/i3s-node-page-loader.js +39 -0
  21. package/dist/es5/i3s-node-page-loader.js.map +1 -0
  22. package/dist/es5/i3s-slpk-loader.js +20 -0
  23. package/dist/es5/i3s-slpk-loader.js.map +1 -0
  24. package/dist/es5/index.js +82 -0
  25. package/dist/es5/index.js.map +1 -0
  26. package/dist/es5/lib/helpers/i3s-nodepages-tiles.js +312 -0
  27. package/dist/es5/lib/helpers/i3s-nodepages-tiles.js.map +1 -0
  28. package/dist/es5/lib/parsers/constants.js +72 -0
  29. package/dist/es5/lib/parsers/constants.js.map +1 -0
  30. package/dist/es5/lib/parsers/parse-arcgis-webscene.js +158 -0
  31. package/dist/es5/lib/parsers/parse-arcgis-webscene.js.map +1 -0
  32. package/dist/es5/lib/parsers/parse-i3s-attribute.js +76 -0
  33. package/dist/es5/lib/parsers/parse-i3s-attribute.js.map +1 -0
  34. package/dist/es5/lib/parsers/parse-i3s-building-scene-layer.js +65 -0
  35. package/dist/es5/lib/parsers/parse-i3s-building-scene-layer.js.map +1 -0
  36. package/dist/es5/lib/parsers/parse-i3s-tile-content.js +510 -0
  37. package/dist/es5/lib/parsers/parse-i3s-tile-content.js.map +1 -0
  38. package/dist/es5/lib/parsers/parse-i3s.js +116 -0
  39. package/dist/es5/lib/parsers/parse-i3s.js.map +1 -0
  40. package/dist/es5/lib/parsers/parse-slpk/parse-slpk.js +107 -0
  41. package/dist/es5/lib/parsers/parse-slpk/parse-slpk.js.map +1 -0
  42. package/dist/es5/lib/parsers/parse-slpk/slpk-archieve.js +258 -0
  43. package/dist/es5/lib/parsers/parse-slpk/slpk-archieve.js.map +1 -0
  44. package/dist/es5/lib/parsers/parse-zip/buffer-file-provider.js +46 -0
  45. package/dist/es5/lib/parsers/parse-zip/buffer-file-provider.js.map +1 -0
  46. package/dist/es5/lib/parsers/parse-zip/cd-file-header.js +84 -0
  47. package/dist/es5/lib/parsers/parse-zip/cd-file-header.js.map +1 -0
  48. package/dist/es5/lib/parsers/parse-zip/file-provider.js +2 -0
  49. package/dist/es5/lib/parsers/parse-zip/file-provider.js.map +1 -0
  50. package/dist/es5/lib/parsers/parse-zip/local-file-header.js +72 -0
  51. package/dist/es5/lib/parsers/parse-zip/local-file-header.js.map +1 -0
  52. package/dist/es5/lib/utils/convert-i3s-obb-to-mbs.js +17 -0
  53. package/dist/es5/lib/utils/convert-i3s-obb-to-mbs.js.map +1 -0
  54. package/dist/es5/lib/utils/customize-/321/201olors.js +184 -0
  55. package/dist/es5/lib/utils/customize-/321/201olors.js.map +1 -0
  56. package/dist/es5/lib/utils/url-utils.js +33 -0
  57. package/dist/es5/lib/utils/url-utils.js.map +1 -0
  58. package/dist/es5/types.js +26 -0
  59. package/dist/es5/types.js.map +1 -0
  60. package/dist/es5/workers/i3s-content-worker-node.js +7 -0
  61. package/dist/es5/workers/i3s-content-worker-node.js.map +1 -0
  62. package/dist/es5/workers/i3s-content-worker.js +6 -0
  63. package/dist/es5/workers/i3s-content-worker.js.map +1 -0
  64. package/dist/esm/arcgis-webscene-loader.js +16 -0
  65. package/dist/esm/arcgis-webscene-loader.js.map +1 -0
  66. package/dist/esm/bundle.js +4 -0
  67. package/dist/esm/bundle.js.map +1 -0
  68. package/dist/esm/i3s-attribute-loader.js +119 -0
  69. package/dist/esm/i3s-attribute-loader.js.map +1 -0
  70. package/dist/esm/i3s-building-scene-layer-loader.js +19 -0
  71. package/dist/esm/i3s-building-scene-layer-loader.js.map +1 -0
  72. package/dist/esm/i3s-content-loader.js +30 -0
  73. package/dist/esm/i3s-content-loader.js.map +1 -0
  74. package/dist/esm/i3s-loader.js +87 -0
  75. package/dist/esm/i3s-loader.js.map +1 -0
  76. package/dist/esm/i3s-node-page-loader.js +15 -0
  77. package/dist/esm/i3s-node-page-loader.js.map +1 -0
  78. package/dist/esm/i3s-slpk-loader.js +13 -0
  79. package/dist/esm/i3s-slpk-loader.js.map +1 -0
  80. package/dist/esm/index.js +11 -0
  81. package/dist/esm/index.js.map +1 -0
  82. package/dist/esm/lib/helpers/i3s-nodepages-tiles.js +198 -0
  83. package/dist/esm/lib/helpers/i3s-nodepages-tiles.js.map +1 -0
  84. package/dist/esm/lib/parsers/constants.js +57 -0
  85. package/dist/esm/lib/parsers/constants.js.map +1 -0
  86. package/dist/esm/lib/parsers/parse-arcgis-webscene.js +70 -0
  87. package/dist/esm/lib/parsers/parse-arcgis-webscene.js.map +1 -0
  88. package/dist/esm/lib/parsers/parse-i3s-attribute.js +60 -0
  89. package/dist/esm/lib/parsers/parse-i3s-attribute.js.map +1 -0
  90. package/dist/esm/lib/parsers/parse-i3s-building-scene-layer.js +39 -0
  91. package/dist/esm/lib/parsers/parse-i3s-building-scene-layer.js.map +1 -0
  92. package/dist/esm/lib/parsers/parse-i3s-tile-content.js +435 -0
  93. package/dist/esm/lib/parsers/parse-i3s-tile-content.js.map +1 -0
  94. package/dist/esm/lib/parsers/parse-i3s.js +83 -0
  95. package/dist/esm/lib/parsers/parse-i3s.js.map +1 -0
  96. package/dist/esm/lib/parsers/parse-slpk/parse-slpk.js +41 -0
  97. package/dist/esm/lib/parsers/parse-slpk/parse-slpk.js.map +1 -0
  98. package/dist/esm/lib/parsers/parse-slpk/slpk-archieve.js +107 -0
  99. package/dist/esm/lib/parsers/parse-slpk/slpk-archieve.js.map +1 -0
  100. package/dist/esm/lib/parsers/parse-zip/buffer-file-provider.js +23 -0
  101. package/dist/esm/lib/parsers/parse-zip/buffer-file-provider.js.map +1 -0
  102. package/dist/esm/lib/parsers/parse-zip/cd-file-header.js +37 -0
  103. package/dist/esm/lib/parsers/parse-zip/cd-file-header.js.map +1 -0
  104. package/dist/esm/lib/parsers/parse-zip/file-provider.js +2 -0
  105. package/dist/esm/lib/parsers/parse-zip/file-provider.js.map +1 -0
  106. package/dist/esm/lib/parsers/parse-zip/local-file-header.js +25 -0
  107. package/dist/esm/lib/parsers/parse-zip/local-file-header.js.map +1 -0
  108. package/dist/esm/lib/utils/convert-i3s-obb-to-mbs.js +9 -0
  109. package/dist/esm/lib/utils/convert-i3s-obb-to-mbs.js.map +1 -0
  110. package/dist/esm/lib/utils/customize-/321/201olors.js +98 -0
  111. package/dist/esm/lib/utils/customize-/321/201olors.js.map +1 -0
  112. package/dist/esm/lib/utils/url-utils.js +28 -0
  113. package/dist/esm/lib/utils/url-utils.js.map +1 -0
  114. package/dist/esm/types.js +18 -0
  115. package/dist/esm/types.js.map +1 -0
  116. package/dist/esm/workers/i3s-content-worker-node.js +5 -0
  117. package/dist/esm/workers/i3s-content-worker-node.js.map +1 -0
  118. package/dist/esm/workers/i3s-content-worker.js +4 -0
  119. package/dist/esm/workers/i3s-content-worker.js.map +1 -0
  120. package/dist/i3s-attribute-loader.d.ts +21 -0
  121. package/dist/i3s-attribute-loader.d.ts.map +1 -0
  122. package/dist/i3s-attribute-loader.js +155 -132
  123. package/dist/i3s-building-scene-layer-loader.d.ts +6 -0
  124. package/dist/i3s-building-scene-layer-loader.d.ts.map +1 -0
  125. package/dist/i3s-building-scene-layer-loader.js +23 -18
  126. package/dist/i3s-content-loader.d.ts +6 -0
  127. package/dist/i3s-content-loader.d.ts.map +1 -0
  128. package/dist/i3s-content-loader.js +29 -22
  129. package/dist/i3s-content-worker-node.js +197 -0
  130. package/dist/i3s-content-worker-node.js.map +7 -0
  131. package/dist/i3s-content-worker.js +2308 -1376
  132. package/dist/i3s-loader.d.ts +11 -0
  133. package/dist/i3s-loader.d.ts.map +1 -0
  134. package/dist/i3s-loader.js +88 -81
  135. package/dist/i3s-node-page-loader.d.ts +7 -0
  136. package/dist/i3s-node-page-loader.d.ts.map +1 -0
  137. package/dist/i3s-node-page-loader.js +20 -20
  138. package/dist/i3s-slpk-loader.d.ts +13 -0
  139. package/dist/i3s-slpk-loader.d.ts.map +1 -0
  140. package/dist/i3s-slpk-loader.js +20 -0
  141. package/dist/index.d.ts +12 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +23 -5
  144. package/dist/lib/helpers/i3s-nodepages-tiles.d.ts +74 -0
  145. package/dist/lib/helpers/i3s-nodepages-tiles.d.ts.map +1 -0
  146. package/dist/lib/helpers/i3s-nodepages-tiles.js +232 -219
  147. package/dist/lib/parsers/constants.d.ts +40 -0
  148. package/dist/lib/parsers/constants.d.ts.map +1 -0
  149. package/dist/lib/parsers/constants.js +87 -42
  150. package/dist/lib/parsers/parse-arcgis-webscene.d.ts +7 -0
  151. package/dist/lib/parsers/parse-arcgis-webscene.d.ts.map +1 -0
  152. package/dist/lib/parsers/parse-arcgis-webscene.js +88 -0
  153. package/dist/lib/parsers/parse-i3s-attribute.d.ts +12 -0
  154. package/dist/lib/parsers/parse-i3s-attribute.d.ts.map +1 -0
  155. package/dist/lib/parsers/parse-i3s-attribute.js +87 -62
  156. package/dist/lib/parsers/parse-i3s-building-scene-layer.d.ts +9 -0
  157. package/dist/lib/parsers/parse-i3s-building-scene-layer.d.ts.map +1 -0
  158. package/dist/lib/parsers/parse-i3s-building-scene-layer.js +41 -38
  159. package/dist/lib/parsers/parse-i3s-tile-content.d.ts +4 -0
  160. package/dist/lib/parsers/parse-i3s-tile-content.d.ts.map +1 -0
  161. package/dist/lib/parsers/parse-i3s-tile-content.js +460 -415
  162. package/dist/lib/parsers/parse-i3s.d.ts +6 -0
  163. package/dist/lib/parsers/parse-i3s.d.ts.map +1 -0
  164. package/dist/lib/parsers/parse-i3s.js +92 -73
  165. package/dist/lib/parsers/parse-slpk/parse-slpk.d.ts +4 -0
  166. package/dist/lib/parsers/parse-slpk/parse-slpk.d.ts.map +1 -0
  167. package/dist/lib/parsers/parse-slpk/parse-slpk.js +54 -0
  168. package/dist/lib/parsers/parse-slpk/slpk-archieve.d.ts +38 -0
  169. package/dist/lib/parsers/parse-slpk/slpk-archieve.d.ts.map +1 -0
  170. package/dist/lib/parsers/parse-slpk/slpk-archieve.js +142 -0
  171. package/dist/lib/parsers/parse-zip/buffer-file-provider.d.ts +37 -0
  172. package/dist/lib/parsers/parse-zip/buffer-file-provider.d.ts.map +1 -0
  173. package/dist/lib/parsers/parse-zip/buffer-file-provider.js +47 -0
  174. package/dist/lib/parsers/parse-zip/cd-file-header.d.ts +27 -0
  175. package/dist/lib/parsers/parse-zip/cd-file-header.d.ts.map +1 -0
  176. package/dist/lib/parsers/parse-zip/cd-file-header.js +48 -0
  177. package/dist/lib/parsers/parse-zip/file-provider.d.ts +31 -0
  178. package/dist/lib/parsers/parse-zip/file-provider.d.ts.map +1 -0
  179. package/dist/lib/parsers/parse-zip/file-provider.js +2 -0
  180. package/dist/lib/parsers/parse-zip/local-file-header.d.ts +25 -0
  181. package/dist/lib/parsers/parse-zip/local-file-header.d.ts.map +1 -0
  182. package/dist/lib/parsers/parse-zip/local-file-header.js +34 -0
  183. package/dist/lib/utils/convert-i3s-obb-to-mbs.d.ts +2 -0
  184. package/dist/lib/utils/convert-i3s-obb-to-mbs.d.ts.map +1 -0
  185. package/dist/lib/utils/convert-i3s-obb-to-mbs.js +19 -8
  186. package/dist/lib/utils/customize-/321/201olors.d.ts +14 -0
  187. package/dist/lib/utils/customize-/321/201olors.d.ts.map +1 -0
  188. package/dist/lib/utils/customize-/321/201olors.js +104 -0
  189. package/dist/lib/utils/url-utils.d.ts +22 -0
  190. package/dist/lib/utils/url-utils.d.ts.map +1 -0
  191. package/dist/lib/utils/url-utils.js +41 -29
  192. package/dist/types.d.ts +1065 -0
  193. package/dist/types.d.ts.map +1 -0
  194. package/dist/types.js +20 -2
  195. package/dist/workers/i3s-content-worker-node.d.ts +2 -0
  196. package/dist/workers/i3s-content-worker-node.d.ts.map +1 -0
  197. package/dist/workers/i3s-content-worker-node.js +7 -0
  198. package/dist/workers/i3s-content-worker.d.ts +2 -0
  199. package/dist/workers/i3s-content-worker.d.ts.map +1 -0
  200. package/dist/workers/i3s-content-worker.js +5 -4
  201. package/package.json +18 -16
  202. package/src/arcgis-webscene-loader.ts +31 -0
  203. package/src/i3s-attribute-loader.ts +9 -9
  204. package/src/i3s-content-loader.ts +17 -5
  205. package/src/i3s-loader.ts +24 -13
  206. package/src/i3s-node-page-loader.ts +6 -10
  207. package/src/i3s-slpk-loader.ts +27 -0
  208. package/src/index.ts +28 -7
  209. package/src/lib/helpers/i3s-nodepages-tiles.ts +84 -57
  210. package/src/lib/parsers/constants.ts +71 -37
  211. package/src/lib/parsers/parse-arcgis-webscene.ts +102 -0
  212. package/src/lib/parsers/parse-i3s-attribute.ts +21 -14
  213. package/src/lib/parsers/parse-i3s-building-scene-layer.ts +2 -1
  214. package/src/lib/parsers/parse-i3s-tile-content.ts +278 -194
  215. package/src/lib/parsers/parse-i3s.ts +55 -39
  216. package/src/lib/parsers/parse-slpk/parse-slpk.ts +72 -0
  217. package/src/lib/parsers/parse-slpk/slpk-archieve.ts +173 -0
  218. package/src/lib/parsers/parse-zip/buffer-file-provider.ts +55 -0
  219. package/src/lib/parsers/parse-zip/cd-file-header.ts +86 -0
  220. package/src/lib/parsers/parse-zip/file-provider.ts +34 -0
  221. package/src/lib/parsers/parse-zip/local-file-header.ts +65 -0
  222. package/src/lib/utils/customize-/321/201olors.ts +144 -0
  223. package/src/lib/utils/url-utils.ts +7 -7
  224. package/src/types.ts +875 -86
  225. package/src/workers/i3s-content-worker-node.ts +6 -0
  226. package/dist/bundle.js.map +0 -1
  227. package/dist/i3s-attribute-loader.js.map +0 -1
  228. package/dist/i3s-building-scene-layer-loader.js.map +0 -1
  229. package/dist/i3s-content-loader.js.map +0 -1
  230. package/dist/i3s-loader.js.map +0 -1
  231. package/dist/i3s-node-page-loader.js.map +0 -1
  232. package/dist/index.js.map +0 -1
  233. package/dist/lib/helpers/i3s-nodepages-tiles.js.map +0 -1
  234. package/dist/lib/parsers/constants.js.map +0 -1
  235. package/dist/lib/parsers/parse-i3s-attribute.js.map +0 -1
  236. package/dist/lib/parsers/parse-i3s-building-scene-layer.js.map +0 -1
  237. package/dist/lib/parsers/parse-i3s-tile-content.js.map +0 -1
  238. package/dist/lib/parsers/parse-i3s.js.map +0 -1
  239. package/dist/lib/utils/convert-i3s-obb-to-mbs.js.map +0 -1
  240. package/dist/lib/utils/url-utils.js.map +0 -1
  241. package/dist/types.js.map +0 -1
  242. package/dist/workers/i3s-content-worker.js.map +0 -1
@@ -1,114 +1,142 @@
1
1
  import type {TypedArray} from '@loaders.gl/schema';
2
2
  import {load, parse} from '@loaders.gl/core';
3
- import {Matrix4} from '@math.gl/core';
4
-
3
+ import {Vector3, Matrix4} from '@math.gl/core';
4
+ import {Ellipsoid} from '@math.gl/geospatial';
5
5
  import type {LoaderOptions, LoaderContext} from '@loaders.gl/loader-utils';
6
6
  import {ImageLoader} from '@loaders.gl/images';
7
- import {DracoLoader} from '@loaders.gl/draco';
7
+ import {DracoLoader, DracoMesh} from '@loaders.gl/draco';
8
8
  import {BasisLoader, CompressedTextureLoader} from '@loaders.gl/textures';
9
9
 
10
- import {Tileset, Tile} from '../../types';
10
+ import {
11
+ FeatureAttribute,
12
+ VertexAttribute,
13
+ I3SMeshAttributes,
14
+ I3SMeshAttribute,
15
+ TileContentTexture,
16
+ HeaderAttributeProperty,
17
+ I3SMaterialDefinition,
18
+ I3STileContent,
19
+ I3STileOptions,
20
+ I3STilesetOptions
21
+ } from '../../types';
11
22
  import {getUrlWithToken} from '../utils/url-utils';
12
23
 
13
- import {
14
- GL_TYPE_MAP,
15
- TYPE_ARRAY_MAP,
16
- SIZEOF,
17
- I3S_NAMED_HEADER_ATTRIBUTES,
18
- I3S_NAMED_VERTEX_ATTRIBUTES,
19
- I3S_NAMED_GEOMETRY_ATTRIBUTES
20
- } from './constants';
21
-
22
- // https://github.com/visgl/deck.gl/blob/46d378fe7693baff25382ac3b9f9cbc2e71e9ebc/modules/core/src/lib/constants.js#L40
23
- const COORDINATE_SYSTEM_LNGLAT_OFFSETS = 3;
24
-
25
- const FORMAT_LOADER_MAP = {
26
- jpeg: ImageLoader,
27
- png: ImageLoader,
28
- 'ktx-etc2': CompressedTextureLoader,
29
- dds: CompressedTextureLoader,
30
- ktx2: BasisLoader
31
- };
24
+ import {GL_TYPE_MAP, getConstructorForDataFormat, sizeOf, COORDINATE_SYSTEM} from './constants';
25
+ import {I3SLoaderOptions} from '../../i3s-loader';
26
+ import {customizeColors} from '../utils/customize-сolors';
27
+
28
+ const scratchVector = new Vector3([0, 0, 0]);
29
+
30
+ function getLoaderForTextureFormat(textureFormat?: 'jpg' | 'png' | 'ktx-etc2' | 'dds' | 'ktx2') {
31
+ switch (textureFormat) {
32
+ case 'ktx-etc2':
33
+ case 'dds':
34
+ return CompressedTextureLoader;
35
+ case 'ktx2':
36
+ return BasisLoader;
37
+ case 'jpg':
38
+ case 'png':
39
+ default:
40
+ return ImageLoader;
41
+ }
42
+ }
32
43
 
33
44
  const I3S_ATTRIBUTE_TYPE = 'i3s-attribute-type';
34
45
 
35
46
  export async function parseI3STileContent(
36
47
  arrayBuffer: ArrayBuffer,
37
- tile: Tile,
38
- tileset: Tileset,
48
+ tileOptions: I3STileOptions,
49
+ tilesetOptions: I3STilesetOptions,
39
50
  options?: LoaderOptions,
40
51
  context?: LoaderContext
41
- ) {
42
- tile.content = tile.content || {};
43
- tile.content.featureIds = tile.content.featureIds || null;
44
-
45
- // construct featureData from defaultGeometrySchema;
46
- tile.content.featureData = constructFeatureDataStruct(tile, tileset);
47
- tile.content.attributes = {};
48
-
49
- if (tile.textureUrl) {
50
- const url = getUrlWithToken(tile.textureUrl, options?.i3s?.token);
51
- const loader = FORMAT_LOADER_MAP[tile.textureFormat] || ImageLoader;
52
- // @ts-ignore context must be defined
53
- const response = await fetch(url);
52
+ ): Promise<I3STileContent> {
53
+ const content: I3STileContent = {
54
+ attributes: {},
55
+ indices: null,
56
+ featureIds: [],
57
+ vertexCount: 0,
58
+ modelMatrix: new Matrix4(),
59
+ coordinateSystem: 0,
60
+ byteLength: 0,
61
+ texture: null
62
+ };
63
+
64
+ if (tileOptions.textureUrl) {
65
+ // @ts-expect-error options is not properly typed
66
+ const url = getUrlWithToken(tileOptions.textureUrl, options?.i3s?.token);
67
+ const loader = getLoaderForTextureFormat(tileOptions.textureFormat);
68
+ const response = await fetch(url, options?.fetch as RequestInit);
54
69
  const arrayBuffer = await response.arrayBuffer();
55
70
 
71
+ // @ts-expect-error options is not properly typed
56
72
  if (options?.i3s.decodeTextures) {
57
73
  if (loader === ImageLoader) {
58
- const options = {...tile.textureLoaderOptions, image: {type: 'data'}};
59
- // @ts-ignore context must be defined
60
- // Image constructor is not supported in worker thread.
61
- // Do parsing image data on the main thread by using context to avoid worker issues.
62
- tile.content.texture = await context.parse(arrayBuffer, options);
74
+ const options = {...tileOptions.textureLoaderOptions, image: {type: 'data'}};
75
+ try {
76
+ // @ts-ignore context must be defined
77
+ // Image constructor is not supported in worker thread.
78
+ // Do parsing image data on the main thread by using context to avoid worker issues.
79
+ content.texture = await context.parse(arrayBuffer, options);
80
+ } catch (e) {
81
+ // context object is different between worker and node.js conversion script.
82
+ // To prevent error we parse data in ordinary way if it is not parsed by using context.
83
+ // @ts-expect-error
84
+ content.texture = await parse(arrayBuffer, loader, options);
85
+ }
63
86
  } else if (loader === CompressedTextureLoader || loader === BasisLoader) {
64
- // @ts-ignore context must be defined
65
- const texture = await load(arrayBuffer, loader, tile.textureLoaderOptions);
66
- tile.content.texture = {
87
+ let texture = await load(arrayBuffer, loader, tileOptions.textureLoaderOptions);
88
+ if (loader === BasisLoader) {
89
+ // @ts-expect-error
90
+ texture = texture[0];
91
+ }
92
+ content.texture = {
67
93
  compressed: true,
68
94
  mipmaps: false,
95
+ // @ts-expect-error
69
96
  width: texture[0].width,
97
+ // @ts-expect-error
70
98
  height: texture[0].height,
99
+ // @ts-expect-error
71
100
  data: texture
72
101
  };
73
102
  }
74
103
  } else {
75
- tile.content.texture = arrayBuffer;
104
+ content.texture = arrayBuffer;
76
105
  }
77
106
  }
78
107
 
79
- tile.content.material = makePbrMaterial(tile.materialDefinition, tile.content.texture);
80
- if (tile.content.material) {
81
- tile.content.texture = null;
108
+ content.material = makePbrMaterial(tileOptions.materialDefinition, content.texture);
109
+ if (content.material) {
110
+ content.texture = null;
82
111
  }
83
112
 
84
- return await parseI3SNodeGeometry(arrayBuffer, tile, context);
113
+ return await parseI3SNodeGeometry(arrayBuffer, content, tileOptions, tilesetOptions, options);
85
114
  }
86
115
 
87
116
  /* eslint-disable max-statements */
88
117
  async function parseI3SNodeGeometry(
89
118
  arrayBuffer: ArrayBuffer,
90
- tile: Tile = {},
91
- context?: LoaderContext
92
- ) {
93
- if (!tile.content) {
94
- return tile;
95
- }
96
-
97
- const content = tile.content;
98
- let attributes;
99
- let vertexCount;
100
- let byteOffset = 0;
101
- let featureCount = 0;
102
-
103
- if (tile.isDracoGeometry) {
104
- const decompressedGeometry = await parse(arrayBuffer, DracoLoader, {
119
+ content: I3STileContent,
120
+ tileOptions: I3STileOptions,
121
+ tilesetOptions: I3STilesetOptions,
122
+ options?: I3SLoaderOptions
123
+ ): Promise<I3STileContent> {
124
+ const contentByteLength = arrayBuffer.byteLength;
125
+ let attributes: I3SMeshAttributes;
126
+ let vertexCount: number;
127
+ let byteOffset: number = 0;
128
+ let featureCount: number = 0;
129
+ let indices: TypedArray | undefined;
130
+
131
+ if (tileOptions.isDracoGeometry) {
132
+ const decompressedGeometry: DracoMesh = await parse(arrayBuffer, DracoLoader, {
105
133
  draco: {
106
134
  attributeNameEntry: I3S_ATTRIBUTE_TYPE
107
135
  }
108
136
  });
109
-
137
+ // @ts-expect-error
110
138
  vertexCount = decompressedGeometry.header.vertexCount;
111
- const indices = decompressedGeometry.indices.value;
139
+ indices = decompressedGeometry.indices?.value;
112
140
  const {
113
141
  POSITION,
114
142
  NORMAL,
@@ -124,8 +152,7 @@ async function parseI3SNodeGeometry(
124
152
  color: COLOR_0,
125
153
  uv0: TEXCOORD_0,
126
154
  uvRegion,
127
- id: featureIndex,
128
- indices
155
+ id: featureIndex
129
156
  };
130
157
 
131
158
  updateAttributesMetadata(attributes, decompressedGeometry);
@@ -136,10 +163,14 @@ async function parseI3SNodeGeometry(
136
163
  flattenFeatureIdsByFeatureIndices(attributes, featureIds);
137
164
  }
138
165
  } else {
139
- const {vertexAttributes, attributesOrder, featureAttributes, featureAttributeOrder} =
140
- content.featureData;
166
+ const {
167
+ vertexAttributes,
168
+ ordering: attributesOrder,
169
+ featureAttributes,
170
+ featureAttributeOrder
171
+ } = tilesetOptions.store.defaultGeometrySchema;
141
172
  // First 8 bytes reserved for header (vertexCount and featureCount)
142
- const headers = parseHeaders(content, arrayBuffer);
173
+ const headers = parseHeaders(arrayBuffer, tilesetOptions);
143
174
  byteOffset = headers.byteOffset;
144
175
  vertexCount = headers.vertexCount;
145
176
  featureCount = headers.featureCount;
@@ -165,17 +196,37 @@ async function parseI3SNodeGeometry(
165
196
  attributes = concatAttributes(normalizedVertexAttributes, normalizedFeatureAttributes);
166
197
  }
167
198
 
199
+ if (
200
+ !options?.i3s?.coordinateSystem ||
201
+ options.i3s.coordinateSystem === COORDINATE_SYSTEM.METER_OFFSETS
202
+ ) {
203
+ const enuMatrix = parsePositions(attributes.position, tileOptions);
204
+ content.modelMatrix = enuMatrix.invert();
205
+ content.coordinateSystem = COORDINATE_SYSTEM.METER_OFFSETS;
206
+ } else {
207
+ content.modelMatrix = getModelMatrix(attributes.position);
208
+ content.coordinateSystem = COORDINATE_SYSTEM.LNGLAT_OFFSETS;
209
+ }
210
+
211
+ attributes.color = await customizeColors(
212
+ attributes.color,
213
+ attributes.id,
214
+ tileOptions,
215
+ tilesetOptions,
216
+ options
217
+ );
218
+
168
219
  content.attributes = {
169
220
  positions: attributes.position,
170
221
  normals: attributes.normal,
171
222
  colors: normalizeAttribute(attributes.color), // Normalize from UInt8
172
223
  texCoords: attributes.uv0,
173
- uvRegions: normalizeAttribute(attributes.uvRegion) // Normalize from UInt16
224
+ uvRegions: normalizeAttribute(attributes.uvRegion || attributes.region) // Normalize from UInt16
174
225
  };
175
- content.indices = attributes.indices || null;
226
+ content.indices = indices || null;
176
227
 
177
228
  if (attributes.id && attributes.id.value) {
178
- tile.content.featureIds = attributes.id.value;
229
+ content.featureIds = attributes.id.value;
179
230
  }
180
231
 
181
232
  // Remove undefined attributes
@@ -186,11 +237,9 @@ async function parseI3SNodeGeometry(
186
237
  }
187
238
 
188
239
  content.vertexCount = vertexCount;
189
- content.modelMatrix = getModelMatrix(attributes.position);
190
- content.coordinateSystem = COORDINATE_SYSTEM_LNGLAT_OFFSETS;
191
- content.byteLength = arrayBuffer.byteLength;
240
+ content.byteLength = contentByteLength;
192
241
 
193
- return tile;
242
+ return content;
194
243
  }
195
244
 
196
245
  /**
@@ -198,7 +247,10 @@ async function parseI3SNodeGeometry(
198
247
  * @param decompressedGeometry
199
248
  * @param attributes
200
249
  */
201
- function updateAttributesMetadata(attributes, decompressedGeometry) {
250
+ function updateAttributesMetadata(
251
+ attributes: I3SMeshAttributes,
252
+ decompressedGeometry: DracoMesh
253
+ ): void {
202
254
  for (const key in decompressedGeometry.loaderData.attributes) {
203
255
  const dracoAttribute = decompressedGeometry.loaderData.attributes[key];
204
256
 
@@ -218,20 +270,23 @@ function updateAttributesMetadata(attributes, decompressedGeometry) {
218
270
  /**
219
271
  * Do concatenation of attribute objects.
220
272
  * Done as separate fucntion to avoid ts errors.
221
- * @param {Object} normalizedVertexAttributes
222
- * @param {Object} normalizedFeatureAttributes
223
- * @returns {object} - result of attributes concatenation.
273
+ * @param normalizedVertexAttributes
274
+ * @param normalizedFeatureAttributes
275
+ * @returns - result of attributes concatenation.
224
276
  */
225
- function concatAttributes(normalizedVertexAttributes, normalizedFeatureAttributes) {
277
+ function concatAttributes(
278
+ normalizedVertexAttributes: I3SMeshAttributes,
279
+ normalizedFeatureAttributes: I3SMeshAttributes
280
+ ): I3SMeshAttributes {
226
281
  return {...normalizedVertexAttributes, ...normalizedFeatureAttributes};
227
282
  }
228
283
 
229
284
  /**
230
285
  * Normalize attribute to range [0..1] . Eg. convert colors buffer from [255,255,255,255] to [1,1,1,1]
231
- * @param {Object} attribute - geometry attribute
232
- * @returns {Object} - geometry attribute in right format
286
+ * @param attribute - geometry attribute
287
+ * @returns - geometry attribute in right format
233
288
  */
234
- function normalizeAttribute(attribute) {
289
+ function normalizeAttribute(attribute: I3SMeshAttribute): I3SMeshAttribute {
235
290
  if (!attribute) {
236
291
  return attribute;
237
292
  }
@@ -239,49 +294,27 @@ function normalizeAttribute(attribute) {
239
294
  return attribute;
240
295
  }
241
296
 
242
- function constructFeatureDataStruct(tile, tileset) {
243
- // seed featureData from defaultGeometrySchema
244
- const defaultGeometrySchema = tileset.store.defaultGeometrySchema;
245
- const featureData = defaultGeometrySchema;
246
- // populate the vertex attributes value types and values per element
247
- for (const geometryAttribute in I3S_NAMED_GEOMETRY_ATTRIBUTES) {
248
- for (const namedAttribute in I3S_NAMED_VERTEX_ATTRIBUTES) {
249
- const attribute = defaultGeometrySchema[geometryAttribute][namedAttribute];
250
- if (attribute) {
251
- const {byteOffset = 0, count = 0, valueType, valuesPerElement} = attribute;
252
-
253
- featureData[geometryAttribute][namedAttribute] = {
254
- valueType,
255
- valuesPerElement,
256
- byteOffset,
257
- count
258
- };
259
- }
260
- }
261
- }
262
-
263
- featureData.attributesOrder = defaultGeometrySchema.ordering;
264
- return featureData;
265
- }
266
-
267
- function parseHeaders(content, buffer) {
297
+ function parseHeaders(arrayBuffer: ArrayBuffer, options: I3STilesetOptions) {
268
298
  let byteOffset = 0;
269
299
  // First 8 bytes reserved for header (vertexCount and featurecount)
270
300
  let vertexCount = 0;
271
301
  let featureCount = 0;
272
- const headers = content.featureData[I3S_NAMED_HEADER_ATTRIBUTES.header];
273
- for (const header in headers) {
274
- const {property, type} = headers[header];
275
- const TypedArrayTypeHeader = TYPE_ARRAY_MAP[type];
276
- if (property === I3S_NAMED_HEADER_ATTRIBUTES.vertexCount) {
277
- vertexCount = new TypedArrayTypeHeader(buffer, 0, 4)[0];
278
- byteOffset += SIZEOF[type];
279
- }
280
- if (property === I3S_NAMED_HEADER_ATTRIBUTES.featureCount) {
281
- featureCount = new TypedArrayTypeHeader(buffer, 4, 4)[0];
282
- byteOffset += SIZEOF[type];
302
+ for (const {property, type} of options.store.defaultGeometrySchema.header) {
303
+ const TypedArrayTypeHeader = getConstructorForDataFormat(type);
304
+ switch (property) {
305
+ case HeaderAttributeProperty.vertexCount:
306
+ vertexCount = new TypedArrayTypeHeader(arrayBuffer, 0, 4)[0];
307
+ byteOffset += sizeOf(type);
308
+ break;
309
+ case HeaderAttributeProperty.featureCount:
310
+ featureCount = new TypedArrayTypeHeader(arrayBuffer, 4, 4)[0];
311
+ byteOffset += sizeOf(type);
312
+ break;
313
+ default:
314
+ break;
283
315
  }
284
316
  }
317
+
285
318
  return {
286
319
  vertexCount,
287
320
  featureCount,
@@ -292,57 +325,59 @@ function parseHeaders(content, buffer) {
292
325
  /* eslint-enable max-statements */
293
326
 
294
327
  function normalizeAttributes(
295
- arrayBuffer,
296
- byteOffset,
297
- vertexAttributes,
298
- vertexCount,
299
- attributesOrder
328
+ arrayBuffer: ArrayBuffer,
329
+ byteOffset: number,
330
+ vertexAttributes: VertexAttribute | FeatureAttribute,
331
+ attributeCount: number,
332
+ attributesOrder: string[]
300
333
  ) {
301
- const attributes = {};
334
+ const attributes: I3SMeshAttributes = {};
302
335
 
303
336
  // the order of attributes depend on the order being added to the vertexAttributes object
304
337
  for (const attribute of attributesOrder) {
305
338
  if (vertexAttributes[attribute]) {
306
- const {valueType, valuesPerElement} = vertexAttributes[attribute];
307
- // update count and byteOffset count by calculating from defaultGeometrySchema + binnary content
308
- const count = vertexCount;
339
+ const {valueType, valuesPerElement}: {valueType: string; valuesPerElement: number} =
340
+ vertexAttributes[attribute];
309
341
  // protect from arrayBuffer read overunns by NOT assuming node has regions always even though its declared in defaultGeometrySchema.
310
342
  // In i3s 1.6: client is required to decide that based on ./shared resource of the node (materialDefinitions.[Mat_id].params.vertexRegions == true)
311
343
  // In i3s 1.7 the property has been rolled into the 3d scene layer json/node pages.
312
344
  // Code below does not account when the bytelength is actually bigger than
313
345
  // the calculated value (b\c the tile potentially could have mesh segmentation information).
314
346
  // In those cases tiles without regions could fail or have garbage values.
315
- if (byteOffset + count * valuesPerElement > arrayBuffer.byteLength) {
316
- break;
317
- }
318
- const buffer = arrayBuffer.slice(byteOffset);
319
- let value: number[] | TypedArray = [];
320
-
321
- if (valueType === 'UInt64') {
322
- value = parseUint64Values(buffer, count * valuesPerElement, SIZEOF[valueType]);
323
- } else {
324
- const TypedArrayType = TYPE_ARRAY_MAP[valueType];
325
- value = new TypedArrayType(buffer, 0, count * valuesPerElement);
326
- }
347
+ if (
348
+ byteOffset + attributeCount * valuesPerElement * sizeOf(valueType) <=
349
+ arrayBuffer.byteLength
350
+ ) {
351
+ const buffer = arrayBuffer.slice(byteOffset);
352
+ let value: TypedArray;
353
+
354
+ if (valueType === 'UInt64') {
355
+ value = parseUint64Values(buffer, attributeCount * valuesPerElement, sizeOf(valueType));
356
+ } else {
357
+ const TypedArrayType = getConstructorForDataFormat(valueType);
358
+ value = new TypedArrayType(buffer, 0, attributeCount * valuesPerElement);
359
+ }
360
+
361
+ attributes[attribute] = {
362
+ value,
363
+ type: GL_TYPE_MAP[valueType],
364
+ size: valuesPerElement
365
+ };
327
366
 
328
- attributes[attribute] = {
329
- value,
330
- type: GL_TYPE_MAP[valueType],
331
- size: valuesPerElement
332
- };
333
-
334
- switch (attribute) {
335
- case 'color':
336
- // @ts-ignore
337
- attributes.color.normalized = true;
338
- break;
339
- case 'position':
340
- case 'region':
341
- case 'normal':
342
- default:
367
+ switch (attribute) {
368
+ case 'color':
369
+ attributes.color.normalized = true;
370
+ break;
371
+ case 'position':
372
+ case 'region':
373
+ case 'normal':
374
+ default:
375
+ }
376
+
377
+ byteOffset = byteOffset + attributeCount * valuesPerElement * sizeOf(valueType);
378
+ } else if (attribute !== 'uv0') {
379
+ break;
343
380
  }
344
-
345
- byteOffset = byteOffset + count * valuesPerElement * SIZEOF[valueType];
346
381
  }
347
382
  }
348
383
 
@@ -360,7 +395,7 @@ function parseUint64Values(
360
395
  buffer: ArrayBuffer,
361
396
  elementsCount: number,
362
397
  attributeSize: number
363
- ): number[] {
398
+ ): Uint32Array {
364
399
  const values: number[] = [];
365
400
  const dataView = new DataView(buffer);
366
401
  let offset = 0;
@@ -376,7 +411,54 @@ function parseUint64Values(
376
411
  offset += attributeSize;
377
412
  }
378
413
 
379
- return values;
414
+ return new Uint32Array(values);
415
+ }
416
+
417
+ function parsePositions(attribute: I3SMeshAttribute, options: I3STileOptions): Matrix4 {
418
+ const mbs = options.mbs;
419
+ const value = attribute.value;
420
+ const metadata = attribute.metadata;
421
+ const enuMatrix = new Matrix4();
422
+ const cartographicOrigin = new Vector3(mbs[0], mbs[1], mbs[2]);
423
+ const cartesianOrigin = new Vector3();
424
+ Ellipsoid.WGS84.cartographicToCartesian(cartographicOrigin, cartesianOrigin);
425
+ Ellipsoid.WGS84.eastNorthUpToFixedFrame(cartesianOrigin, enuMatrix);
426
+ attribute.value = offsetsToCartesians(value, metadata, cartographicOrigin);
427
+
428
+ return enuMatrix;
429
+ }
430
+
431
+ /**
432
+ * Converts position coordinates to absolute cartesian coordinates
433
+ * @param vertices - "position" attribute data
434
+ * @param metadata - When the geometry is DRACO compressed, contain position attribute's metadata
435
+ * https://github.com/Esri/i3s-spec/blob/master/docs/1.7/compressedAttributes.cmn.md
436
+ * @param cartographicOrigin - Cartographic origin coordinates
437
+ * @returns - converted "position" data
438
+ */
439
+ function offsetsToCartesians(
440
+ vertices: number[] | TypedArray,
441
+ metadata: any = {},
442
+ cartographicOrigin: Vector3
443
+ ): Float64Array {
444
+ const positions = new Float64Array(vertices.length);
445
+ const scaleX = (metadata['i3s-scale_x'] && metadata['i3s-scale_x'].double) || 1;
446
+ const scaleY = (metadata['i3s-scale_y'] && metadata['i3s-scale_y'].double) || 1;
447
+ for (let i = 0; i < positions.length; i += 3) {
448
+ positions[i] = vertices[i] * scaleX + cartographicOrigin.x;
449
+ positions[i + 1] = vertices[i + 1] * scaleY + cartographicOrigin.y;
450
+ positions[i + 2] = vertices[i + 2] + cartographicOrigin.z;
451
+ }
452
+
453
+ for (let i = 0; i < positions.length; i += 3) {
454
+ // @ts-ignore
455
+ Ellipsoid.WGS84.cartographicToCartesian(positions.subarray(i, i + 3), scratchVector);
456
+ positions[i] = scratchVector.x;
457
+ positions[i + 1] = scratchVector.y;
458
+ positions[i + 2] = scratchVector.z;
459
+ }
460
+
461
+ return positions;
380
462
  }
381
463
 
382
464
  /**
@@ -384,10 +466,10 @@ function parseUint64Values(
384
466
  * @param positions positions attribute
385
467
  * @returns Matrix4 - model matrix for geometry transformation
386
468
  */
387
- function getModelMatrix(positions) {
469
+ function getModelMatrix(positions: I3SMeshAttribute): Matrix4 {
388
470
  const metadata = positions.metadata;
389
- const scaleX = metadata?.['i3s-scale_x']?.double || 1;
390
- const scaleY = metadata?.['i3s-scale_y']?.double || 1;
471
+ const scaleX: number = metadata?.['i3s-scale_x']?.double || 1;
472
+ const scaleY: number = metadata?.['i3s-scale_y']?.double || 1;
391
473
  const modelMatrix = new Matrix4();
392
474
  modelMatrix[0] = scaleX;
393
475
  modelMatrix[5] = scaleY;
@@ -396,12 +478,12 @@ function getModelMatrix(positions) {
396
478
 
397
479
  /**
398
480
  * Makes a glTF-compatible PBR material from an I3S material definition
399
- * @param {object} materialDefinition - i3s material definition
481
+ * @param materialDefinition - i3s material definition
400
482
  * https://github.com/Esri/i3s-spec/blob/master/docs/1.7/materialDefinitions.cmn.md
401
- * @param {object} texture - texture image
483
+ * @param texture - texture image
402
484
  * @returns {object}
403
485
  */
404
- function makePbrMaterial(materialDefinition, texture) {
486
+ function makePbrMaterial(materialDefinition?: I3SMaterialDefinition, texture?: TileContentTexture) {
405
487
  let pbrMaterial;
406
488
  if (materialDefinition) {
407
489
  pbrMaterial = {
@@ -439,17 +521,19 @@ function makePbrMaterial(materialDefinition, texture) {
439
521
  );
440
522
  }
441
523
 
442
- setMaterialTexture(pbrMaterial, texture);
524
+ if (texture) {
525
+ setMaterialTexture(pbrMaterial, texture);
526
+ }
443
527
 
444
528
  return pbrMaterial;
445
529
  }
446
530
 
447
531
  /**
448
532
  * Convert color from [255,255,255,255] to [1,1,1,1]
449
- * @param {Array} colorFactor - color array
450
- * @returns {Array} - new color array
533
+ * @param colorFactor - color array
534
+ * @returns - new color array
451
535
  */
452
- function convertColorFormat(colorFactor) {
536
+ function convertColorFormat(colorFactor: number[]): number[] {
453
537
  const normalizedColor = [...colorFactor];
454
538
  for (let index = 0; index < colorFactor.length; index++) {
455
539
  normalizedColor[index] = colorFactor[index] / 255;
@@ -460,10 +544,10 @@ function convertColorFormat(colorFactor) {
460
544
  /**
461
545
  * Set texture in PBR material
462
546
  * @param {object} material - i3s material definition
463
- * @param {object} image - texture image
464
- * @returns {void}
547
+ * @param image - texture image
548
+ * @returns
465
549
  */
466
- function setMaterialTexture(material, image) {
550
+ function setMaterialTexture(material, image: TileContentTexture): void {
467
551
  const texture = {source: {image}};
468
552
  // I3SLoader now support loading only one texture. This elseif sequence will assign this texture to one of
469
553
  // properties defined in materialDefinition
@@ -491,10 +575,10 @@ function setMaterialTexture(material, image) {
491
575
 
492
576
  /**
493
577
  * Flatten feature ids using face ranges
494
- * @param {object} normalizedFeatureAttributes
495
- * @returns {void}
578
+ * @param normalizedFeatureAttributes
579
+ * @returns
496
580
  */
497
- function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes) {
581
+ function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes: I3SMeshAttributes): void {
498
582
  const {id, faceRange} = normalizedFeatureAttributes;
499
583
 
500
584
  if (!id || !faceRange) {
@@ -527,11 +611,14 @@ function flattenFeatureIdsByFaceRanges(normalizedFeatureAttributes) {
527
611
 
528
612
  /**
529
613
  * Flatten feature ids using featureIndices
530
- * @param {object} attributes
531
- * @param {any} featureIds
532
- * @returns {void}
614
+ * @param attributes
615
+ * @param featureIds
616
+ * @returns
533
617
  */
534
- function flattenFeatureIdsByFeatureIndices(attributes, featureIds) {
618
+ function flattenFeatureIdsByFeatureIndices(
619
+ attributes: I3SMeshAttributes,
620
+ featureIds: Int32Array
621
+ ): void {
535
622
  const featureIndices = attributes.id.value;
536
623
  const result = new Float32Array(featureIndices.length);
537
624
 
@@ -544,14 +631,11 @@ function flattenFeatureIdsByFeatureIndices(attributes, featureIds) {
544
631
 
545
632
  /**
546
633
  * Flatten feature ids using featureIndices
547
- * @param {object} featureIndex
548
- * @returns {Int32Array}
634
+ * @param featureIndex
635
+ * @returns
549
636
  */
550
- function getFeatureIdsFromFeatureIndexMetadata(featureIndex) {
551
- return (
552
- featureIndex &&
553
- featureIndex.metadata &&
554
- featureIndex.metadata['i3s-feature-ids'] &&
555
- featureIndex.metadata['i3s-feature-ids'].intArray
556
- );
637
+ function getFeatureIdsFromFeatureIndexMetadata(
638
+ featureIndex: I3SMeshAttribute
639
+ ): Int32Array | undefined {
640
+ return featureIndex?.metadata?.['i3s-feature-ids']?.intArray;
557
641
  }