@loaders.gl/tile-converter 3.3.0-alpha.1 → 3.3.0-alpha.10

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 (252) hide show
  1. package/dist/3d-tiles-attributes-worker.d.ts +3 -3
  2. package/dist/3d-tiles-attributes-worker.d.ts.map +1 -1
  3. package/dist/3d-tiles-attributes-worker.js +2 -3
  4. package/dist/3d-tiles-attributes-worker.js.map +3 -3
  5. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts +8 -0
  6. package/dist/3d-tiles-converter/3d-tiles-converter.d.ts.map +1 -1
  7. package/dist/3d-tiles-converter/3d-tiles-converter.js +57 -43
  8. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts +5 -5
  9. package/dist/3d-tiles-converter/helpers/b3dm-converter.d.ts.map +1 -1
  10. package/dist/3d-tiles-converter/helpers/b3dm-converter.js +21 -17
  11. package/dist/converter-cli.js +29 -4
  12. package/dist/converter.min.js +24 -21
  13. package/dist/deps-installer/deps-installer.d.ts +5 -1
  14. package/dist/deps-installer/deps-installer.d.ts.map +1 -1
  15. package/dist/deps-installer/deps-installer.js +29 -1
  16. package/dist/dist.min.js +61034 -64112
  17. package/dist/es5/3d-tiles-attributes-worker.js +4 -7
  18. package/dist/es5/3d-tiles-attributes-worker.js.map +1 -1
  19. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js +125 -210
  20. package/dist/es5/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  21. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js +53 -85
  22. package/dist/es5/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  23. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +0 -8
  24. package/dist/es5/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
  25. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js +0 -5
  26. package/dist/es5/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
  27. package/dist/es5/3d-tiles-converter/json-templates/tileset.js +0 -6
  28. package/dist/es5/3d-tiles-converter/json-templates/tileset.js.map +1 -1
  29. package/dist/es5/bundle.js +0 -1
  30. package/dist/es5/bundle.js.map +1 -1
  31. package/dist/es5/constants.js.map +1 -1
  32. package/dist/es5/converter-cli.js +25 -58
  33. package/dist/es5/converter-cli.js.map +1 -1
  34. package/dist/es5/deps-installer/deps-installer.js +73 -28
  35. package/dist/es5/deps-installer/deps-installer.js.map +1 -1
  36. package/dist/es5/i3s-attributes-worker.js +3 -6
  37. package/dist/es5/i3s-attributes-worker.js.map +1 -1
  38. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js +18 -29
  39. package/dist/es5/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  40. package/dist/es5/i3s-converter/helpers/coordinate-converter.js +8 -25
  41. package/dist/es5/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  42. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js +0 -11
  43. package/dist/es5/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
  44. package/dist/es5/i3s-converter/helpers/feature-attributes.js +184 -0
  45. package/dist/es5/i3s-converter/helpers/feature-attributes.js.map +1 -0
  46. package/dist/es5/i3s-converter/helpers/geometry-attributes.js +60 -51
  47. package/dist/es5/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  48. package/dist/es5/i3s-converter/helpers/geometry-converter.js +504 -350
  49. package/dist/es5/i3s-converter/helpers/geometry-converter.js.map +1 -1
  50. package/dist/es5/i3s-converter/helpers/gltf-attributes.js +57 -57
  51. package/dist/es5/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  52. package/dist/es5/i3s-converter/helpers/node-debug.js +4 -23
  53. package/dist/es5/i3s-converter/helpers/node-debug.js.map +1 -1
  54. package/dist/es5/i3s-converter/helpers/node-index-document.js +507 -0
  55. package/dist/es5/i3s-converter/helpers/node-index-document.js.map +1 -0
  56. package/dist/es5/i3s-converter/helpers/node-pages.js +478 -168
  57. package/dist/es5/i3s-converter/helpers/node-pages.js.map +1 -1
  58. package/dist/es5/i3s-converter/i3s-converter.js +794 -1125
  59. package/dist/es5/i3s-converter/i3s-converter.js.map +1 -1
  60. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js +107 -0
  61. package/dist/es5/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  62. package/dist/es5/i3s-converter/json-templates/layers.js +2 -107
  63. package/dist/es5/i3s-converter/json-templates/layers.js.map +1 -1
  64. package/dist/es5/i3s-converter/json-templates/metadata.js +0 -2
  65. package/dist/es5/i3s-converter/json-templates/metadata.js.map +1 -1
  66. package/dist/es5/i3s-converter/json-templates/node.js +2 -12
  67. package/dist/es5/i3s-converter/json-templates/node.js.map +1 -1
  68. package/dist/es5/i3s-converter/json-templates/scene-server.js +0 -2
  69. package/dist/es5/i3s-converter/json-templates/scene-server.js.map +1 -1
  70. package/dist/es5/i3s-converter/json-templates/shared-resources.js +9 -32
  71. package/dist/es5/i3s-converter/json-templates/shared-resources.js.map +1 -1
  72. package/dist/es5/i3s-converter/json-templates/store.js.map +1 -1
  73. package/dist/es5/i3s-converter/types.js.map +1 -1
  74. package/dist/es5/i3s-server/app.js +0 -5
  75. package/dist/es5/i3s-server/app.js.map +1 -1
  76. package/dist/es5/i3s-server/controllers/index-controller.js +0 -16
  77. package/dist/es5/i3s-server/controllers/index-controller.js.map +1 -1
  78. package/dist/es5/i3s-server/routes/index.js +1 -10
  79. package/dist/es5/i3s-server/routes/index.js.map +1 -1
  80. package/dist/es5/index.js +0 -3
  81. package/dist/es5/index.js.map +1 -1
  82. package/dist/es5/lib/utils/compress-util.js +19 -74
  83. package/dist/es5/lib/utils/compress-util.js.map +1 -1
  84. package/dist/es5/lib/utils/file-utils.js +103 -47
  85. package/dist/es5/lib/utils/file-utils.js.map +1 -1
  86. package/dist/es5/lib/utils/lod-conversion-utils.js +0 -7
  87. package/dist/es5/lib/utils/lod-conversion-utils.js.map +1 -1
  88. package/dist/es5/lib/utils/queue.js +0 -14
  89. package/dist/es5/lib/utils/queue.js.map +1 -1
  90. package/dist/es5/lib/utils/statistic-utills.js +1 -46
  91. package/dist/es5/lib/utils/statistic-utills.js.map +1 -1
  92. package/dist/es5/lib/utils/write-queue.js +86 -87
  93. package/dist/es5/lib/utils/write-queue.js.map +1 -1
  94. package/dist/es5/pgm-loader.js +1 -8
  95. package/dist/es5/pgm-loader.js.map +1 -1
  96. package/dist/es5/workers/3d-tiles-attributes-worker.js +2 -9
  97. package/dist/es5/workers/3d-tiles-attributes-worker.js.map +1 -1
  98. package/dist/es5/workers/i3s-attributes-worker.js +2 -10
  99. package/dist/es5/workers/i3s-attributes-worker.js.map +1 -1
  100. package/dist/esm/3d-tiles-attributes-worker.js +4 -2
  101. package/dist/esm/3d-tiles-attributes-worker.js.map +1 -1
  102. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js +60 -77
  103. package/dist/esm/3d-tiles-converter/3d-tiles-converter.js.map +1 -1
  104. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js +29 -50
  105. package/dist/esm/3d-tiles-converter/helpers/b3dm-converter.js.map +1 -1
  106. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js +1 -0
  107. package/dist/esm/3d-tiles-converter/helpers/i3s-obb-to-3d-tiles-obb.js.map +1 -1
  108. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js +1 -4
  109. package/dist/esm/3d-tiles-converter/helpers/texture-atlas.js.map +1 -1
  110. package/dist/esm/3d-tiles-converter/json-templates/tileset.js +0 -3
  111. package/dist/esm/3d-tiles-converter/json-templates/tileset.js.map +1 -1
  112. package/dist/esm/bundle.js +1 -1
  113. package/dist/esm/bundle.js.map +1 -1
  114. package/dist/esm/constants.js.map +1 -1
  115. package/dist/esm/converter-cli.js +26 -43
  116. package/dist/esm/converter-cli.js.map +1 -1
  117. package/dist/esm/deps-installer/deps-installer.js +30 -4
  118. package/dist/esm/deps-installer/deps-installer.js.map +1 -1
  119. package/dist/esm/i3s-attributes-worker.js +3 -1
  120. package/dist/esm/i3s-attributes-worker.js.map +1 -1
  121. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js +20 -24
  122. package/dist/esm/i3s-converter/helpers/batch-ids-extensions.js.map +1 -1
  123. package/dist/esm/i3s-converter/helpers/coordinate-converter.js +11 -12
  124. package/dist/esm/i3s-converter/helpers/coordinate-converter.js.map +1 -1
  125. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js +1 -0
  126. package/dist/esm/i3s-converter/helpers/create-scene-server-path.js.map +1 -1
  127. package/dist/esm/i3s-converter/helpers/feature-attributes.js +158 -0
  128. package/dist/esm/i3s-converter/helpers/feature-attributes.js.map +1 -0
  129. package/dist/esm/i3s-converter/helpers/geometry-attributes.js +39 -33
  130. package/dist/esm/i3s-converter/helpers/geometry-attributes.js.map +1 -1
  131. package/dist/esm/i3s-converter/helpers/geometry-converter.js +286 -192
  132. package/dist/esm/i3s-converter/helpers/geometry-converter.js.map +1 -1
  133. package/dist/esm/i3s-converter/helpers/gltf-attributes.js +59 -48
  134. package/dist/esm/i3s-converter/helpers/gltf-attributes.js.map +1 -1
  135. package/dist/esm/i3s-converter/helpers/node-debug.js +3 -13
  136. package/dist/esm/i3s-converter/helpers/node-debug.js.map +1 -1
  137. package/dist/esm/i3s-converter/helpers/node-index-document.js +197 -0
  138. package/dist/esm/i3s-converter/helpers/node-index-document.js.map +1 -0
  139. package/dist/esm/i3s-converter/helpers/node-pages.js +161 -87
  140. package/dist/esm/i3s-converter/helpers/node-pages.js.map +1 -1
  141. package/dist/esm/i3s-converter/i3s-converter.js +235 -508
  142. package/dist/esm/i3s-converter/i3s-converter.js.map +1 -1
  143. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js +89 -0
  144. package/dist/esm/i3s-converter/json-templates/geometry-definitions.js.map +1 -0
  145. package/dist/esm/i3s-converter/json-templates/layers.js +2 -95
  146. package/dist/esm/i3s-converter/json-templates/layers.js.map +1 -1
  147. package/dist/esm/i3s-converter/json-templates/metadata.js.map +1 -1
  148. package/dist/esm/i3s-converter/json-templates/node.js +0 -4
  149. package/dist/esm/i3s-converter/json-templates/node.js.map +1 -1
  150. package/dist/esm/i3s-converter/json-templates/scene-server.js.map +1 -1
  151. package/dist/esm/i3s-converter/json-templates/shared-resources.js +3 -15
  152. package/dist/esm/i3s-converter/json-templates/shared-resources.js.map +1 -1
  153. package/dist/esm/i3s-converter/json-templates/store.js.map +1 -1
  154. package/dist/esm/i3s-converter/types.js.map +1 -1
  155. package/dist/esm/i3s-server/app.js +0 -5
  156. package/dist/esm/i3s-server/app.js.map +1 -1
  157. package/dist/esm/i3s-server/controllers/index-controller.js +0 -5
  158. package/dist/esm/i3s-server/controllers/index-controller.js.map +1 -1
  159. package/dist/esm/i3s-server/routes/index.js +0 -3
  160. package/dist/esm/i3s-server/routes/index.js.map +1 -1
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/lib/utils/compress-util.js +19 -12
  163. package/dist/esm/lib/utils/compress-util.js.map +1 -1
  164. package/dist/esm/lib/utils/file-utils.js +54 -11
  165. package/dist/esm/lib/utils/file-utils.js.map +1 -1
  166. package/dist/esm/lib/utils/lod-conversion-utils.js +2 -6
  167. package/dist/esm/lib/utils/lod-conversion-utils.js.map +1 -1
  168. package/dist/esm/lib/utils/queue.js +0 -4
  169. package/dist/esm/lib/utils/queue.js.map +1 -1
  170. package/dist/esm/lib/utils/statistic-utills.js +0 -11
  171. package/dist/esm/lib/utils/statistic-utills.js.map +1 -1
  172. package/dist/esm/lib/utils/write-queue.js +29 -28
  173. package/dist/esm/lib/utils/write-queue.js.map +1 -1
  174. package/dist/esm/pgm-loader.js +3 -1
  175. package/dist/esm/pgm-loader.js.map +1 -1
  176. package/dist/esm/workers/3d-tiles-attributes-worker.js +4 -1
  177. package/dist/esm/workers/3d-tiles-attributes-worker.js.map +1 -1
  178. package/dist/esm/workers/i3s-attributes-worker.js +4 -1
  179. package/dist/esm/workers/i3s-attributes-worker.js.map +1 -1
  180. package/dist/i3s-attributes-worker.d.ts +7 -3
  181. package/dist/i3s-attributes-worker.d.ts.map +1 -1
  182. package/dist/i3s-attributes-worker.js +2 -3
  183. package/dist/i3s-attributes-worker.js.map +3 -3
  184. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts +5 -6
  185. package/dist/i3s-converter/helpers/batch-ids-extensions.d.ts.map +1 -1
  186. package/dist/i3s-converter/helpers/batch-ids-extensions.js +18 -4
  187. package/dist/i3s-converter/helpers/coordinate-converter.d.ts +2 -2
  188. package/dist/i3s-converter/helpers/coordinate-converter.d.ts.map +1 -1
  189. package/dist/i3s-converter/helpers/coordinate-converter.js +8 -6
  190. package/dist/i3s-converter/helpers/feature-attributes.d.ts +56 -0
  191. package/dist/i3s-converter/helpers/feature-attributes.d.ts.map +1 -0
  192. package/dist/i3s-converter/helpers/feature-attributes.js +216 -0
  193. package/dist/i3s-converter/helpers/geometry-attributes.d.ts.map +1 -1
  194. package/dist/i3s-converter/helpers/geometry-attributes.js +42 -17
  195. package/dist/i3s-converter/helpers/geometry-converter.d.ts +18 -6
  196. package/dist/i3s-converter/helpers/geometry-converter.d.ts.map +1 -1
  197. package/dist/i3s-converter/helpers/geometry-converter.js +337 -92
  198. package/dist/i3s-converter/helpers/gltf-attributes.d.ts.map +1 -1
  199. package/dist/i3s-converter/helpers/gltf-attributes.js +51 -32
  200. package/dist/i3s-converter/helpers/node-index-document.d.ts +91 -0
  201. package/dist/i3s-converter/helpers/node-index-document.d.ts.map +1 -0
  202. package/dist/i3s-converter/helpers/node-index-document.js +242 -0
  203. package/dist/i3s-converter/helpers/node-pages.d.ts +81 -42
  204. package/dist/i3s-converter/helpers/node-pages.d.ts.map +1 -1
  205. package/dist/i3s-converter/helpers/node-pages.js +200 -92
  206. package/dist/i3s-converter/i3s-converter.d.ts +52 -108
  207. package/dist/i3s-converter/i3s-converter.d.ts.map +1 -1
  208. package/dist/i3s-converter/i3s-converter.js +234 -420
  209. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts +7 -0
  210. package/dist/i3s-converter/json-templates/geometry-definitions.d.ts.map +1 -0
  211. package/dist/i3s-converter/json-templates/geometry-definitions.js +87 -0
  212. package/dist/i3s-converter/json-templates/layers.d.ts +1 -30
  213. package/dist/i3s-converter/json-templates/layers.d.ts.map +1 -1
  214. package/dist/i3s-converter/json-templates/layers.js +2 -86
  215. package/dist/i3s-converter/json-templates/shared-resources.js +3 -3
  216. package/dist/i3s-converter/types.d.ts +37 -55
  217. package/dist/i3s-converter/types.d.ts.map +1 -1
  218. package/dist/lib/utils/file-utils.d.ts +17 -1
  219. package/dist/lib/utils/file-utils.d.ts.map +1 -1
  220. package/dist/lib/utils/file-utils.js +64 -7
  221. package/dist/lib/utils/write-queue.d.ts +19 -2
  222. package/dist/lib/utils/write-queue.d.ts.map +1 -1
  223. package/dist/lib/utils/write-queue.js +26 -7
  224. package/dist/pgm-loader.d.ts.map +1 -1
  225. package/dist/pgm-loader.js +2 -1
  226. package/dist/workers/3d-tiles-attributes-worker.js +1 -1
  227. package/dist/workers/i3s-attributes-worker.js +1 -1
  228. package/package.json +18 -16
  229. package/src/3d-tiles-attributes-worker.ts +1 -1
  230. package/src/3d-tiles-converter/3d-tiles-converter.ts +71 -55
  231. package/src/3d-tiles-converter/helpers/b3dm-converter.ts +25 -18
  232. package/src/converter-cli.ts +38 -4
  233. package/src/deps-installer/deps-installer.ts +38 -2
  234. package/src/i3s-attributes-worker.ts +5 -1
  235. package/src/i3s-converter/helpers/batch-ids-extensions.ts +38 -14
  236. package/src/i3s-converter/helpers/coordinate-converter.ts +10 -8
  237. package/src/i3s-converter/helpers/feature-attributes.ts +247 -0
  238. package/src/i3s-converter/helpers/geometry-attributes.ts +46 -18
  239. package/src/i3s-converter/helpers/geometry-converter.ts +405 -108
  240. package/src/i3s-converter/helpers/gltf-attributes.ts +55 -35
  241. package/src/i3s-converter/helpers/node-index-document.ts +306 -0
  242. package/src/i3s-converter/helpers/node-pages.ts +222 -109
  243. package/src/i3s-converter/i3s-converter.ts +279 -499
  244. package/src/i3s-converter/json-templates/geometry-definitions.ts +83 -0
  245. package/src/i3s-converter/json-templates/layers.ts +2 -91
  246. package/src/i3s-converter/json-templates/shared-resources.ts +3 -3
  247. package/src/i3s-converter/types.ts +31 -51
  248. package/src/lib/utils/file-utils.ts +62 -7
  249. package/src/lib/utils/write-queue.ts +43 -10
  250. package/src/pgm-loader.ts +2 -2
  251. package/src/workers/3d-tiles-attributes-worker.ts +1 -1
  252. package/src/workers/i3s-attributes-worker.ts +2 -1
@@ -1,20 +1,11 @@
1
1
  import type {Tile3D, Tileset3DProps} from '@loaders.gl/tiles';
2
- import type {BatchTableJson, B3DMContent} from '@loaders.gl/3d-tiles';
2
+ import type {FeatureTableJson} from '@loaders.gl/3d-tiles';
3
3
  import type {WriteQueueItem} from '../lib/utils/write-queue';
4
4
  import type {
5
- AttributeStorageInfo,
6
5
  SceneLayer3D,
7
6
  BoundingVolumes,
8
- Node3DIndexDocument,
9
- NodeReference,
10
7
  MaxScreenThresholdSQ,
11
- NodeInPage,
12
- LodSelection,
13
- Attribute,
14
- ESRIField,
15
- Field,
16
- PopupInfo,
17
- FieldInfo
8
+ NodeInPage
18
9
  } from '@loaders.gl/i3s';
19
10
  import {load, encode, fetchFile, getLoaderOptions, isBrowser} from '@loaders.gl/core';
20
11
  import {Tileset3D} from '@loaders.gl/tiles';
@@ -27,14 +18,15 @@ import transform from 'json-map-transform';
27
18
  import md5 from 'md5';
28
19
 
29
20
  import NodePages from './helpers/node-pages';
30
- import {writeFile, removeDir, writeFileForSlpk} from '../lib/utils/file-utils';
21
+ import {writeFile, removeDir, writeFileForSlpk, removeFile} from '../lib/utils/file-utils';
31
22
  import {
23
+ compressFileWithGzip,
32
24
  compressWithChildProcess
33
25
  // generateHash128FromZip,
34
26
  // addFileToZip
35
27
  } from '../lib/utils/compress-util';
36
28
  import {calculateFilesSize, timeConverter} from '../lib/utils/statistic-utills';
37
- import convertB3dmToI3sGeometry from './helpers/geometry-converter';
29
+ import convertB3dmToI3sGeometry, {getPropertyTable} from './helpers/geometry-converter';
38
30
  import {
39
31
  createBoundingVolumes,
40
32
  convertBoundingVolumeToI3SFullExtent
@@ -44,7 +36,7 @@ import {convertGeometricErrorToScreenThreshold} from '../lib/utils/lod-conversio
44
36
  import {PGMLoader} from '../pgm-loader';
45
37
 
46
38
  import {LAYERS as layersTemplate} from './json-templates/layers';
47
- import {NODE as nodeTemplate} from './json-templates/node';
39
+ import {GEOMETRY_DEFINITION as geometryDefinitionTemlate} from './json-templates/geometry-definitions';
48
40
  import {SHARED_RESOURCES as sharedResourcesTemplate} from './json-templates/shared-resources';
49
41
  import {validateNodeBoundingVolumes} from './helpers/node-debug';
50
42
  import TileHeader from '@loaders.gl/tiles/src/tileset/tile-3d';
@@ -59,6 +51,14 @@ import {DracoWriterWorker} from '@loaders.gl/draco';
59
51
  import WriteQueue from '../lib/utils/write-queue';
60
52
  import {I3SAttributesWorker} from '../i3s-attributes-worker';
61
53
  import {BROWSER_ERROR_MESSAGE} from '../constants';
54
+ import {
55
+ createdStorageAttribute,
56
+ createFieldAttribute,
57
+ createPopupInfo,
58
+ getAttributeType,
59
+ getFieldAttributeType
60
+ } from './helpers/feature-attributes';
61
+ import {NodeIndexDocument} from './helpers/node-index-document';
62
62
 
63
63
  const ION_DEFAULT_TOKEN =
64
64
  process.env?.IonToken || // eslint-disable-line
@@ -66,10 +66,6 @@ const ION_DEFAULT_TOKEN =
66
66
  const HARDCODED_NODES_PER_PAGE = 64;
67
67
  const _3D_TILES = '3DTILES';
68
68
  const _3D_OBJECT_LAYER_TYPE = '3DObject';
69
- const STRING_TYPE = 'string';
70
- const SHORT_INT_TYPE = 'Int32';
71
- const DOUBLE_TYPE = 'double';
72
- const OBJECT_ID_TYPE = 'OBJECTID';
73
69
  const REFRESH_TOKEN_TIMEOUT = 1800; // 30 minutes in seconds
74
70
  const CESIUM_DATASET_PREFIX = 'https://';
75
71
  // const FS_FILE_TOO_LARGE = 'ERR_FS_FILE_TOO_LARGE';
@@ -81,8 +77,10 @@ export default class I3SConverter {
81
77
  nodePages: NodePages;
82
78
  options: any;
83
79
  layers0Path: string;
84
- materialMap: Map<any, any>;
80
+ materialMap: Map<string, number>;
85
81
  materialDefinitions: I3SMaterialDefinition[];
82
+ geometryMap: Map<string, number>;
83
+ geometryConfigs: {hasTexture: boolean; hasUvRegions: boolean}[];
86
84
  vertexCounter: number;
87
85
  layers0: SceneLayer3D | null;
88
86
  featuresHashArray: string[];
@@ -102,13 +100,16 @@ export default class I3SConverter {
102
100
  layersHasTexture: boolean;
103
101
  workerSource: {[key: string]: string} = {};
104
102
  writeQueue: WriteQueue<WriteQueueItem> = new WriteQueue();
103
+ compressList: string[] | null = null;
105
104
 
106
105
  constructor() {
107
- this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE);
106
+ this.nodePages = new NodePages(writeFile, HARDCODED_NODES_PER_PAGE, this);
108
107
  this.options = {};
109
108
  this.layers0Path = '';
110
109
  this.materialMap = new Map();
111
110
  this.materialDefinitions = [];
111
+ this.geometryMap = new Map();
112
+ this.geometryConfigs = [];
112
113
  this.vertexCounter = 0;
113
114
  this.layers0 = null;
114
115
  this.featuresHashArray = [];
@@ -120,6 +121,7 @@ export default class I3SConverter {
120
121
  this.generateTextures = false;
121
122
  this.generateBoundingVolumes = false;
122
123
  this.layersHasTexture = false;
124
+ this.compressList = null;
123
125
  }
124
126
 
125
127
  /**
@@ -135,6 +137,9 @@ export default class I3SConverter {
135
137
  * @param options.token Token for Cesium ION tilesets authentication
136
138
  * @param options.draco Generate I3S 1.7 draco compressed geometries
137
139
  * @param options.validate -enable validation
140
+ * @param options.generateTextures - generate alternative type of textures (to have non-compressed jpeg/png and compressed ktx2)
141
+ * @param options.generateBoundingVolumes - generate bounding volumes from vertices coordinates instead of source tiles bounding volumes
142
+ * @param options.instantNodeWriting - Keep created 3DNodeIndexDocument files on disk instead of memory. This option reduce memory usage but decelerates conversion speed
138
143
  */
139
144
  async convert(options: {
140
145
  inputUrl: string;
@@ -146,9 +151,11 @@ export default class I3SConverter {
146
151
  slpk?: boolean;
147
152
  token?: string;
148
153
  draco?: boolean;
154
+ mergeMaterials?: boolean;
149
155
  validate?: boolean;
150
156
  generateTextures?: boolean;
151
157
  generateBoundingVolumes?: boolean;
158
+ instantNodeWriting?: boolean;
152
159
  }): Promise<any> {
153
160
  if (isBrowser) {
154
161
  console.log(BROWSER_ERROR_MESSAGE);
@@ -162,14 +169,27 @@ export default class I3SConverter {
162
169
  inputUrl,
163
170
  validate,
164
171
  outputPath,
165
- draco,
172
+ draco = true,
166
173
  sevenZipExe,
167
174
  maxDepth,
168
175
  token,
169
176
  generateTextures,
170
- generateBoundingVolumes
177
+ generateBoundingVolumes,
178
+ instantNodeWriting = false,
179
+ mergeMaterials = true
171
180
  } = options;
172
- this.options = {maxDepth, slpk, sevenZipExe, egmFilePath, draco, token, inputUrl};
181
+ this.options = {
182
+ maxDepth,
183
+ slpk,
184
+ sevenZipExe,
185
+ egmFilePath,
186
+ draco,
187
+ token,
188
+ inputUrl,
189
+ instantNodeWriting,
190
+ mergeMaterials
191
+ };
192
+ this.compressList = (this.options.instantNodeWriting && []) || null;
173
193
  this.validate = Boolean(validate);
174
194
  this.Loader = inputUrl.indexOf(CESIUM_DATASET_PREFIX) !== -1 ? CesiumIonLoader : Tiles3DLoader;
175
195
  this.generateTextures = Boolean(generateTextures);
@@ -190,7 +210,18 @@ export default class I3SConverter {
190
210
 
191
211
  try {
192
212
  const preloadOptions = await this._fetchPreloadOptions();
193
- const tilesetOptions: Tileset3DProps = {loadOptions: {basis: {format: 'rgba32'}}};
213
+ const tilesetOptions: Tileset3DProps = {
214
+ loadOptions: {
215
+ _nodeWorkers: true,
216
+ reuseWorkers: true,
217
+ basis: {format: 'rgba32'},
218
+ 'basis-nodejs': {
219
+ format: 'rgba32',
220
+ workerUrl: './modules/textures/dist/basis-nodejs-worker.js'
221
+ },
222
+ 'draco-nodejs': {workerUrl: './modules/draco/dist/draco-nodejs-worker.js'}
223
+ }
224
+ };
194
225
  if (preloadOptions.headers) {
195
226
  tilesetOptions.loadOptions!.fetch = {headers: preloadOptions.headers};
196
227
  }
@@ -199,7 +230,11 @@ export default class I3SConverter {
199
230
  // console.log(tilesetJson); // eslint-disable-line
200
231
  this.sourceTileset = new Tileset3D(sourceTilesetJson, tilesetOptions);
201
232
 
202
- await this._createAndSaveTileset(outputPath, tilesetName);
233
+ await this._createAndSaveTileset(
234
+ outputPath,
235
+ tilesetName,
236
+ sourceTilesetJson?.root?.boundingVolume?.region
237
+ );
203
238
  await this._finishConversion({slpk: Boolean(slpk), outputPath, tilesetName});
204
239
  return sourceTilesetJson;
205
240
  } catch (error) {
@@ -216,7 +251,11 @@ export default class I3SConverter {
216
251
  * @param outputPath - path to save output data
217
252
  * @param tilesetName - new tileset path
218
253
  */
219
- private async _createAndSaveTileset(outputPath: string, tilesetName: string): Promise<void> {
254
+ private async _createAndSaveTileset(
255
+ outputPath: string,
256
+ tilesetName: string,
257
+ boundingVolumeRegion?: number[]
258
+ ): Promise<void> {
220
259
  const tilesetPath = join(`${outputPath}`, `${tilesetName}`);
221
260
  // Removing the tilesetPath needed to exclude erroneous files after conversion
222
261
  try {
@@ -227,26 +266,31 @@ export default class I3SConverter {
227
266
 
228
267
  this.layers0Path = join(tilesetPath, 'SceneServer', 'layers', '0');
229
268
 
230
- this._formLayers0(tilesetName);
269
+ this._formLayers0(tilesetName, boundingVolumeRegion);
231
270
 
232
271
  this.materialDefinitions = [];
233
272
  this.materialMap = new Map();
234
273
 
235
274
  const sourceRootTile: TileHeader = this.sourceTileset!.root!;
236
275
  const boundingVolumes = createBoundingVolumes(sourceRootTile, this.geoidHeightModel!);
237
- const parentId = this.nodePages.push({
276
+ await this.nodePages.push({
238
277
  index: 0,
239
278
  lodThreshold: 0,
240
279
  obb: boundingVolumes.obb,
241
280
  children: []
242
281
  });
243
282
 
244
- const isCreateSlpk = this.options.slpk;
245
- const root0 = this._formRootNodeIndexDocument(boundingVolumes);
246
-
247
- await this._convertNodesTree(root0, sourceRootTile, parentId, boundingVolumes);
283
+ const rootNode = await NodeIndexDocument.createRootNode(boundingVolumes, this);
284
+ await this._convertNodesTree(rootNode, sourceRootTile);
248
285
 
249
286
  this.layers0!.materialDefinitions = this.materialDefinitions;
287
+ // @ts-ignore
288
+ this.layers0.geometryDefinitions = transform(
289
+ this.geometryConfigs.map((config) => ({
290
+ geometryConfig: {...config, draco: this.options.draco}
291
+ })),
292
+ geometryDefinitionTemlate()
293
+ );
250
294
 
251
295
  if (this.layersHasTexture === false) {
252
296
  this.layers0!.store.defaultGeometrySchema.ordering =
@@ -257,8 +301,11 @@ export default class I3SConverter {
257
301
 
258
302
  await this._writeLayers0();
259
303
  createSceneServerPath(tilesetName, this.layers0!, tilesetPath);
260
- await this._writeNodeIndexDocument(root0, 'root', join(this.layers0Path, 'nodes', 'root'));
261
- await this.nodePages.save(this.layers0Path, this.writeQueue, isCreateSlpk);
304
+ for (const filePath of this.compressList || []) {
305
+ await compressFileWithGzip(filePath);
306
+ await removeFile(filePath);
307
+ }
308
+ await this.nodePages.save();
262
309
  await this.writeQueue.finalize();
263
310
  await this._createSlpk(tilesetPath);
264
311
  }
@@ -267,10 +314,14 @@ export default class I3SConverter {
267
314
  * Form object of 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
268
315
  * @param tilesetName - Name of layer
269
316
  */
270
- private _formLayers0(tilesetName: string): void {
317
+ private _formLayers0(tilesetName: string, boundingVolumeRegion?: number[]): void {
271
318
  const fullExtent = convertBoundingVolumeToI3SFullExtent(
272
319
  this.sourceTileset?.boundingVolume || this.sourceTileset?.root?.boundingVolume
273
320
  );
321
+ if (boundingVolumeRegion) {
322
+ fullExtent.zmin = boundingVolumeRegion[4];
323
+ fullExtent.zmax = boundingVolumeRegion[5];
324
+ }
274
325
  const extent = [fullExtent.xmin, fullExtent.ymin, fullExtent.xmax, fullExtent.ymax];
275
326
  const layers0data = {
276
327
  version: `{${uuidv4().toUpperCase()}}`,
@@ -290,77 +341,31 @@ export default class I3SConverter {
290
341
  this.layers0 = transform(layers0data, layersTemplate());
291
342
  }
292
343
 
293
- /**
294
- * Convert and save the layer and embedded tiles
295
- * @param boundingVolumes - mbs and obb data about node's bounding volume
296
- * @return 3DNodeIndexDocument data https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
297
- */
298
- private _formRootNodeIndexDocument(boundingVolumes: BoundingVolumes): Node3DIndexDocument {
299
- const root0data = {
300
- version: `{${uuidv4().toUpperCase()}}`,
301
- id: 'root',
302
- level: 0,
303
- lodSelection: [
304
- {
305
- metricType: 'maxScreenThresholdSQ',
306
- maxError: 0
307
- },
308
- {
309
- metricType: 'maxScreenThreshold',
310
- maxError: 0
311
- }
312
- ],
313
- ...boundingVolumes,
314
- children: []
315
- };
316
- return transform(root0data, nodeTemplate());
317
- }
318
-
319
344
  /**
320
345
  * Form object of 3DSceneLayer https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DSceneLayer.cmn.md
321
- * @param root0 - 3DNodeIndexDocument of root node https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
346
+ * @param rootNode - 3DNodeIndexDocument of root node https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md
322
347
  * @param sourceRootTile - Source (3DTile) tile data
323
- * @param parentId - node id in node pages
324
- * @param boundingVolumes - mbs and obb data about node's bounding volume
325
348
  */
326
349
  private async _convertNodesTree(
327
- root0: Node3DIndexDocument,
328
- sourceRootTile: TileHeader,
329
- parentId: number,
330
- boundingVolumes: BoundingVolumes
350
+ rootNode: NodeIndexDocument,
351
+ sourceRootTile: TileHeader
331
352
  ): Promise<void> {
332
353
  await this.sourceTileset!._loadTile(sourceRootTile);
333
354
  if (this.isContentSupported(sourceRootTile)) {
334
- root0.children = root0.children || [];
335
- root0.children.push({
336
- id: '1',
337
- href: './1',
338
- ...boundingVolumes
339
- });
340
- const [child] = await this._createNode(root0, sourceRootTile, parentId, 0);
341
- const childPath = join(this.layers0Path, 'nodes', child.path!);
342
-
343
- if (this.options.slpk) {
344
- this.writeQueue.enqueue({
345
- archiveKey: 'nodes/1/3dNodeIndexDocument.json.gz',
346
- writePromise: writeFileForSlpk(
347
- childPath,
348
- JSON.stringify(child),
349
- '3dNodeIndexDocument.json'
350
- )
351
- });
352
- } else {
353
- this.writeQueue.enqueue({writePromise: writeFile(childPath, JSON.stringify(child))});
355
+ const childNodes = await this._createNode(rootNode, sourceRootTile, 0);
356
+ for (const childNode of childNodes) {
357
+ await childNode.save();
354
358
  }
359
+ await rootNode.addChildren(childNodes);
355
360
  } else {
356
361
  await this._addChildrenWithNeighborsAndWriteFile({
357
- parentNode: root0,
362
+ parentNode: rootNode,
358
363
  sourceTiles: sourceRootTile.children,
359
- parentId,
360
364
  level: 1
361
365
  });
362
366
  }
363
367
  await sourceRootTile.unloadContent();
368
+ await rootNode.save();
364
369
  }
365
370
 
366
371
  /**
@@ -368,36 +373,15 @@ export default class I3SConverter {
368
373
  */
369
374
  private async _writeLayers0(): Promise<void> {
370
375
  if (this.options.slpk) {
371
- this.writeQueue.enqueue({
376
+ await this.writeQueue.enqueue({
372
377
  archiveKey: '3dSceneLayer.json.gz',
373
- writePromise: writeFileForSlpk(
374
- this.layers0Path,
375
- JSON.stringify(this.layers0),
376
- '3dSceneLayer.json'
377
- )
378
+ writePromise: () =>
379
+ writeFileForSlpk(this.layers0Path, JSON.stringify(this.layers0), '3dSceneLayer.json')
378
380
  });
379
381
  } else {
380
- this.writeQueue.enqueue({
381
- writePromise: writeFile(this.layers0Path, JSON.stringify(this.layers0))
382
- });
383
- }
384
- }
385
-
386
- /**
387
- * Write 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md in file
388
- */
389
- private async _writeNodeIndexDocument(
390
- root0: Node3DIndexDocument,
391
- nodePath: string,
392
- rootPath: string
393
- ): Promise<void> {
394
- if (this.options.slpk) {
395
- this.writeQueue.enqueue({
396
- archiveKey: `nodes/${nodePath}/3dNodeIndexDocument.json.gz`,
397
- writePromise: writeFileForSlpk(rootPath, JSON.stringify(root0), '3dNodeIndexDocument.json')
382
+ await this.writeQueue.enqueue({
383
+ writePromise: () => writeFile(this.layers0Path, JSON.stringify(this.layers0))
398
384
  });
399
- } else {
400
- this.writeQueue.enqueue({writePromise: writeFile(rootPath, JSON.stringify(root0))});
401
385
  }
402
386
  }
403
387
 
@@ -446,146 +430,141 @@ export default class I3SConverter {
446
430
  /**
447
431
  * Add child nodes recursively and write them to files
448
432
  * @param data - arguments
433
+ * @param data.parentNode - 3DNodeIndexDocument of parent node
449
434
  * @param data.sourceTiles - array of source child nodes
450
- * @param data.parentNode - 3DNodeIndexDocument of parent node for processing child nodes
451
- * @param data.parentId - id of parent node in node pages
452
435
  * @param data.level - level of node (distanse to root node in the tree)
453
436
  */
454
437
  private async _addChildrenWithNeighborsAndWriteFile(data: {
455
- parentNode: Node3DIndexDocument;
438
+ parentNode: NodeIndexDocument;
456
439
  sourceTiles: TileHeader[];
457
- parentId: number;
458
440
  level: number;
459
441
  }): Promise<void> {
460
- const childNodes = [];
461
- await this._addChildren({...data, childNodes});
462
- await this._addNeighborsAndWriteFile(data.parentNode, childNodes);
442
+ await this._addChildren(data);
443
+ await data.parentNode.addNeighbors();
444
+ }
445
+
446
+ /**
447
+ * Convert nested subtree of 3DTiles dataset
448
+ * @param param0
449
+ * @param data.parentNode - 3DNodeIndexDocument of parent node
450
+ * @param param0.sourceTile - source 3DTile data
451
+ * @param param0.level - tree level
452
+ */
453
+ private async convertNestedTileset({
454
+ parentNode,
455
+ sourceTile,
456
+ level
457
+ }: {
458
+ parentNode: NodeIndexDocument;
459
+ sourceTile: TileHeader;
460
+ level: number;
461
+ }) {
462
+ await this.sourceTileset!._loadTile(sourceTile);
463
+ await this._addChildren({
464
+ parentNode,
465
+ sourceTiles: sourceTile.children,
466
+ level: level + 1
467
+ });
468
+ await sourceTile.unloadContent();
469
+ }
470
+
471
+ /**
472
+ * Convert 3DTiles tile to I3S node
473
+ * @param param0
474
+ * @param param0.parentNode - 3DNodeIndexDocument of parent node
475
+ * @param param0.sourceTile - source 3DTile data
476
+ * @param param0.level - tree level
477
+ */
478
+ private async convertNode({
479
+ parentNode,
480
+ sourceTile,
481
+ level
482
+ }: {
483
+ parentNode: NodeIndexDocument;
484
+ sourceTile: TileHeader;
485
+ level: number;
486
+ }) {
487
+ const childNodes = await this._createNode(parentNode, sourceTile, level);
488
+ await parentNode.addChildren(childNodes);
463
489
  }
464
490
 
465
491
  /**
466
492
  * Add child nodes recursively and write them to files
467
- * @param data - arguments
468
- * @param data.childNodes - array of target child nodes
469
- * @param data.sourceTiles - array of source child nodes
470
- * @param data.parentNode - 3DNodeIndexDocument of parent node for processing child nodes
471
- * @param data.parentId - id of parent node in node pages
472
- * @param data.level - level of node (distanse to root node in the tree)
493
+ * @param param0 - arguments
494
+ * @param param0.parentNode - 3DNodeIndexDocument of parent node
495
+ * @param param0.sourceTile - source 3DTile data
496
+ * @param param0.level - tree level
473
497
  */
474
498
  private async _addChildren(data: {
475
- childNodes: NodeReference[];
499
+ parentNode: NodeIndexDocument;
476
500
  sourceTiles: TileHeader[];
477
- parentNode: Node3DIndexDocument;
478
- parentId: number;
479
501
  level: number;
480
502
  }): Promise<void> {
481
- const {childNodes, sourceTiles, parentNode, parentId, level} = data;
503
+ const {sourceTiles, parentNode, level} = data;
482
504
  if (this.options.maxDepth && level > this.options.maxDepth) {
483
505
  return;
484
506
  }
507
+
508
+ const promises: Promise<void>[] = [];
485
509
  for (const sourceTile of sourceTiles) {
486
510
  if (sourceTile.type === 'json') {
487
- await this.sourceTileset!._loadTile(sourceTile);
488
- await this._addChildren({
489
- parentNode,
490
- sourceTiles: sourceTile.children,
491
- childNodes,
492
- parentId,
493
- level: level + 1
494
- });
495
- await sourceTile.unloadContent();
511
+ if (this.options.instantNodeWriting) {
512
+ await this.convertNestedTileset({parentNode, sourceTile, level});
513
+ } else {
514
+ promises.push(this.convertNestedTileset({parentNode, sourceTile, level}));
515
+ }
496
516
  } else {
497
- const children = await this._createNode(parentNode, sourceTile, parentId, level);
498
- parentNode.children = parentNode.children || [];
499
- for (const child of children) {
500
- parentNode.children.push({
501
- id: child.id,
502
- href: `../${child.path}`,
503
- obb: child.obb,
504
- mbs: child.mbs
505
- });
506
- childNodes.push(child);
517
+ if (this.options.instantNodeWriting) {
518
+ await this.convertNode({parentNode, sourceTile, level});
519
+ } else {
520
+ promises.push(this.convertNode({parentNode, sourceTile, level}));
507
521
  }
508
522
  }
509
523
  if (sourceTile.id) {
510
524
  console.log(sourceTile.id); // eslint-disable-line
511
525
  }
512
526
  }
513
- }
514
-
515
- /**
516
- * Add neightbors to 3DNodeIndexDocument and write it in a file
517
- * @param parentNode - arguments
518
- * @param childNodes - array of target child nodes
519
- */
520
- private async _addNeighborsAndWriteFile(
521
- parentNode: Node3DIndexDocument,
522
- childNodes: Node3DIndexDocument[]
523
- ): Promise<void> {
524
- for (const node of childNodes) {
525
- const childPath = join(this.layers0Path, 'nodes', node.path!);
526
- const nodePath = node.path;
527
- delete node.path;
528
-
529
- // Don't do large amount of "neightbors" to avoid big memory consumption
530
- if (Number(parentNode?.children?.length) < 1000) {
531
- for (const neighbor of parentNode.children || []) {
532
- // eslint-disable-next-line max-depth
533
- if (node.id === neighbor.id) {
534
- continue; // eslint-disable-line
535
- }
536
-
537
- if (node.neighbors) {
538
- node.neighbors.push({...neighbor});
539
- }
540
- }
541
- } else {
542
- // eslint-disable-next-line no-console, no-undef
543
- console.warn(
544
- `Node ${node.id}: neighbors attribute is omited because of large number of neigbors`
545
- );
546
- delete node.neighbors;
547
- }
548
- await this._writeNodeIndexDocument(node, nodePath!, childPath);
549
- node.neighbors = [];
550
- }
527
+ await Promise.all(promises);
551
528
  }
552
529
 
553
530
  /**
554
531
  * Convert tile to one or more I3S nodes
555
- * @param parentTile - parent 3DNodeIndexDocument
556
- * @param sourceTile - source tile (3DTile)
557
- * @param parentId - id of parent node in node pages
558
- * @param level - level of node (distanse to root node in the tree)
532
+ * @param parentNode - 3DNodeIndexDocument of parent node
533
+ * @param sourceTile - source 3DTile data
534
+ * @param level - tree level
559
535
  */
560
536
  private async _createNode(
561
- parentTile: Node3DIndexDocument,
537
+ parentNode: NodeIndexDocument,
562
538
  sourceTile: TileHeader,
563
- parentId: number,
564
539
  level: number
565
- ): Promise<Node3DIndexDocument[]> {
566
- if (this.validate) {
567
- this._checkAddRefinementTypeForTile(sourceTile);
568
- }
540
+ ): Promise<NodeIndexDocument[]> {
541
+ this._checkAddRefinementTypeForTile(sourceTile);
569
542
 
570
543
  await this._updateTilesetOptions();
571
544
  await this.sourceTileset!._loadTile(sourceTile);
572
545
 
573
546
  let boundingVolumes = createBoundingVolumes(sourceTile, this.geoidHeightModel!);
574
547
 
575
- const batchTable = sourceTile?.content?.batchTableJson;
548
+ const propertyTable = getPropertyTable(sourceTile.content);
576
549
 
577
- if (batchTable) {
578
- this._convertAttributeStorageInfo(sourceTile.content);
550
+ if (propertyTable && !this.layers0?.attributeStorageInfo?.length) {
551
+ this._convertPropertyTableToNodeAttributes(propertyTable);
579
552
  }
580
553
 
581
- const resourcesData = await this._convertResources(sourceTile);
554
+ const resourcesData = await this._convertResources(
555
+ sourceTile,
556
+ parentNode.inPageId,
557
+ propertyTable
558
+ );
582
559
 
583
- const nodes: Node3DIndexDocument[] = [];
560
+ const nodes: NodeIndexDocument[] = [];
561
+ const nodeIds: number[] = [];
584
562
  const nodesInPage: NodeInPage[] = [];
585
563
  const emptyResources = {
586
564
  geometry: null,
587
565
  compressedGeometry: null,
588
566
  texture: null,
567
+ hasUvRegions: false,
589
568
  sharedResources: null,
590
569
  meshMaterial: null,
591
570
  vertexCount: null,
@@ -606,34 +585,37 @@ export default class I3SConverter {
606
585
  (val) => val.metricType === 'maxScreenThresholdSQ'
607
586
  ) || {maxError: 0};
608
587
 
609
- const nodeInPage = this._createNodeInNodePages(
588
+ const nodeInPage = await this._updateNodeInNodePages(
610
589
  maxScreenThresholdSQ,
611
590
  boundingVolumes,
612
591
  sourceTile,
613
- parentId,
592
+ parentNode.inPageId,
614
593
  resources
615
594
  );
616
- const node = this._createNodeIndexDocument(
617
- parentTile,
595
+
596
+ const nodeData = await NodeIndexDocument.createNodeIndexDocument(
597
+ parentNode,
618
598
  boundingVolumes,
619
599
  lodSelection,
620
600
  nodeInPage,
621
601
  resources
622
602
  );
603
+ const node = await new NodeIndexDocument(nodeInPage.index, this).addData(nodeData);
604
+ nodes.push(node);
623
605
 
624
606
  if (nodeInPage.mesh) {
625
- await this._writeResources(resources, node.path!);
607
+ await this._writeResources(resources, node.id);
626
608
  }
627
609
 
628
610
  if (this.validate) {
629
- this.boundingVolumeWarnings = validateNodeBoundingVolumes(node);
611
+ this.boundingVolumeWarnings = validateNodeBoundingVolumes(nodeData);
630
612
 
631
613
  if (this.boundingVolumeWarnings && this.boundingVolumeWarnings.length) {
632
614
  console.warn('Bounding Volume Warnings: ', ...this.boundingVolumeWarnings); //eslint-disable-line
633
615
  }
634
616
  }
635
617
 
636
- nodes.push(node);
618
+ nodeIds.push(nodeInPage.index);
637
619
  nodesInPage.push(nodeInPage);
638
620
  }
639
621
 
@@ -642,49 +624,40 @@ export default class I3SConverter {
642
624
  await this._addChildrenWithNeighborsAndWriteFile({
643
625
  parentNode: nodes[0],
644
626
  sourceTiles: sourceTile.children,
645
- parentId: nodesInPage[0].index!,
646
627
  level: level + 1
647
628
  });
648
629
  return nodes;
649
630
  }
650
631
 
651
- /**
652
- * Convert attributesStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
653
- * from B3DM batch table
654
- * @param sourceTileContent - tile content of 3DTile
655
- * @return {void}
656
- */
657
- private _convertAttributeStorageInfo(sourceTileContent: B3DMContent): void {
658
- // In legacy b3dm files sometimes sourceTileContent is null.
659
- const batchTable = sourceTileContent && sourceTileContent.batchTableJson;
660
- if (batchTable && !this.layers0?.attributeStorageInfo?.length) {
661
- this._convertBatchTableInfoToNodeAttributes(batchTable);
662
- }
663
- }
664
-
665
632
  /**
666
633
  * Convert tile to one or more I3S nodes
667
634
  * @param sourceTile - source tile (3DTile)
668
- * result.geometry - ArrayBuffer with geometry attributes
669
- * result.compressedGeometry - ArrayBuffer with compressed (draco) geometry
670
- * result.texture - texture image
671
- * result.sharedResources - shared resource data object
672
- * result.meshMaterial - PBR-like material object
673
- * result.vertexCount - number of vertices in geometry
674
- * result.attributes - feature attributes
675
- * result.featureCount - number of features
635
+ * @param parentId - id of parent node in node pages
636
+ * @param propertyTable - batch table from b3dm / feature properties from EXT_FEATURE_METADATA
637
+ * @returns - converted node resources
676
638
  */
677
- private async _convertResources(sourceTile: TileHeader): Promise<I3SConvertedResources[] | null> {
639
+ private async _convertResources(
640
+ sourceTile: TileHeader,
641
+ parentId: number,
642
+ propertyTable: FeatureTableJson | null
643
+ ): Promise<I3SConvertedResources[] | null> {
678
644
  if (!this.isContentSupported(sourceTile)) {
679
645
  return null;
680
646
  }
647
+ const draftObb = {
648
+ center: [],
649
+ halfSize: [],
650
+ quaternion: []
651
+ };
681
652
  const resourcesData = await convertB3dmToI3sGeometry(
682
653
  sourceTile.content,
683
- Number(this.nodePages.nodesCounter),
654
+ async () => (await this.nodePages.push({index: 0, obb: draftObb}, parentId)).index,
655
+ propertyTable,
684
656
  this.featuresHashArray,
685
657
  this.layers0?.attributeStorageInfo,
686
658
  this.options.draco,
687
659
  this.generateBoundingVolumes,
660
+ this.options.mergeMaterials,
688
661
  this.geoidHeightModel!,
689
662
  this.workerSource
690
663
  );
@@ -692,7 +665,7 @@ export default class I3SConverter {
692
665
  }
693
666
 
694
667
  /**
695
- * Create a new node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
668
+ * Update node object (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/node.cmn.md)
696
669
  * in node pages (https://github.com/Esri/i3s-spec/blob/master/docs/1.7/nodePage.cmn.md)
697
670
  * @param maxScreenThresholdSQ - Level of Details (LOD) metric
698
671
  * @param boundingVolumes - Bounding volumes
@@ -703,16 +676,17 @@ export default class I3SConverter {
703
676
  * @param resources.texture - texture image
704
677
  * @param resources.vertexCount - number of vertices in geometry
705
678
  * @param resources.featureCount - number of features
679
+ * @param resources.geometry - Uint8Array with geometry attributes
706
680
  * @return the node object in node pages
707
681
  */
708
- private _createNodeInNodePages(
682
+ private async _updateNodeInNodePages(
709
683
  maxScreenThresholdSQ: MaxScreenThresholdSQ,
710
684
  boundingVolumes: BoundingVolumes,
711
685
  sourceTile: TileHeader,
712
686
  parentId: number,
713
687
  resources: I3SConvertedResources
714
- ): NodeInPage {
715
- const {meshMaterial, texture, vertexCount, featureCount, geometry} = resources;
688
+ ): Promise<NodeInPage> {
689
+ const {meshMaterial, texture, vertexCount, featureCount, geometry, hasUvRegions} = resources;
716
690
  const nodeInPage: NodeInPage = {
717
691
  index: 0,
718
692
  lodThreshold: maxScreenThresholdSQ.maxError,
@@ -722,7 +696,7 @@ export default class I3SConverter {
722
696
  if (geometry && this.isContentSupported(sourceTile)) {
723
697
  nodeInPage.mesh = {
724
698
  geometry: {
725
- definition: texture ? 0 : 1,
699
+ definition: this.findOrCreateGeometryDefinition(Boolean(texture), hasUvRegions),
726
700
  resource: 0
727
701
  },
728
702
  attribute: {
@@ -733,83 +707,33 @@ export default class I3SConverter {
733
707
  }
734
708
  };
735
709
  }
736
- const nodeId = this.nodePages.push(nodeInPage, parentId);
737
710
 
738
- if (meshMaterial) {
739
- this.nodePages.updateMaterialByNodeId(nodeId, this._findOrCreateMaterial(meshMaterial));
711
+ let nodeId = resources.nodeId;
712
+ let node;
713
+ if (!nodeId) {
714
+ node = await this.nodePages.push(nodeInPage, parentId);
715
+ } else {
716
+ node = await this.nodePages.getNodeById(nodeId);
740
717
  }
741
718
 
719
+ NodePages.updateAll(node, nodeInPage);
720
+ if (meshMaterial) {
721
+ NodePages.updateMaterialByNodeId(node, this._findOrCreateMaterial(meshMaterial));
722
+ }
742
723
  if (texture) {
743
724
  const texelCountHint = texture.image.height * texture.image.width;
744
- this.nodePages.updateTexelCountHintByNodeId(nodeId, texelCountHint);
725
+ NodePages.updateTexelCountHintByNodeId(node, texelCountHint);
745
726
  }
746
-
747
727
  if (vertexCount) {
748
728
  this.vertexCounter += vertexCount;
749
- this.nodePages.updateVertexCountByNodeId(nodeId, vertexCount);
729
+ NodePages.updateVertexCountByNodeId(node, vertexCount);
750
730
  }
751
- this.nodePages.updateNodeAttributeByNodeId(nodeId);
731
+ NodePages.updateNodeAttributeByNodeId(node);
752
732
  if (featureCount) {
753
- this.nodePages.updateFeatureCountByNodeId(nodeId, featureCount);
733
+ NodePages.updateFeatureCountByNodeId(node, featureCount);
754
734
  }
755
735
 
756
- return nodeInPage;
757
- }
758
-
759
- /**
760
- * Create a new node page object in node pages
761
- * @param parentNode - 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md object of the parent node
762
- * @param boundingVolumes - Bounding volumes
763
- * @param lodSelection - Level of Details (LOD) metrics
764
- * @param nodeInPage - corresponding node object in a node page
765
- * @param resources - the node resources data
766
- * @param resources.texture - texture image
767
- * @param resources.attributes - feature attributes
768
- * @return 3DNodeIndexDocument https://github.com/Esri/i3s-spec/blob/master/docs/1.7/3DNodeIndexDocument.cmn.md object
769
- */
770
- private _createNodeIndexDocument(
771
- parentNode: Node3DIndexDocument,
772
- boundingVolumes: BoundingVolumes,
773
- lodSelection: LodSelection[],
774
- nodeInPage: NodeInPage,
775
- resources: I3SConvertedResources
776
- ): Node3DIndexDocument {
777
- const {texture, attributes} = resources;
778
- const nodeId = nodeInPage.index!;
779
- const nodeData = {
780
- version: parentNode.version,
781
- id: nodeId.toString(),
782
- path: nodeId.toString(),
783
- level: parentNode.level! + 1,
784
- ...boundingVolumes,
785
- lodSelection,
786
- parentNode: {
787
- id: parentNode.id,
788
- href: `../${parentNode.id}`,
789
- mbs: parentNode.mbs,
790
- obb: parentNode.obb
791
- },
792
- children: [],
793
- neighbors: []
794
- };
795
- const node = transform(nodeData, nodeTemplate());
796
-
797
- if (nodeInPage.mesh) {
798
- node.geometryData = [{href: './geometries/0'}];
799
- node.sharedResource = {href: './shared'};
800
-
801
- if (texture) {
802
- node.textureData = [{href: './textures/0'}, {href: './textures/1'}];
803
- }
804
-
805
- if (attributes && attributes.length && this.layers0?.attributeStorageInfo?.length) {
806
- node.attributeData = [];
807
- for (let index = 0; index < attributes.length; index++) {
808
- const folderName = this.layers0.attributeStorageInfo[index].key;
809
- node.attributeData.push({href: `./attributes/${folderName}/0`});
810
- }
811
- }
812
- }
736
+ this.nodePages.saveNode(node);
813
737
 
814
738
  return node;
815
739
  }
@@ -856,28 +780,29 @@ export default class I3SConverter {
856
780
  ): Promise<void> {
857
781
  if (this.options.slpk) {
858
782
  const slpkGeometryPath = join(childPath, 'geometries');
859
- this.writeQueue.enqueue({
783
+ await this.writeQueue.enqueue({
860
784
  archiveKey: `${slpkChildPath}/geometries/0.bin.gz`,
861
- writePromise: writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
785
+ writePromise: () => writeFileForSlpk(slpkGeometryPath, geometryBuffer, '0.bin')
862
786
  });
863
787
  } else {
864
788
  const geometryPath = join(childPath, 'geometries/0/');
865
- this.writeQueue.enqueue({
866
- writePromise: writeFile(geometryPath, geometryBuffer, 'index.bin')
789
+ await this.writeQueue.enqueue({
790
+ writePromise: () => writeFile(geometryPath, geometryBuffer, 'index.bin')
867
791
  });
868
792
  }
869
793
 
870
794
  if (this.options.draco) {
871
795
  if (this.options.slpk) {
872
796
  const slpkCompressedGeometryPath = join(childPath, 'geometries');
873
- this.writeQueue.enqueue({
797
+ await this.writeQueue.enqueue({
874
798
  archiveKey: `${slpkChildPath}/geometries/1.bin.gz`,
875
- writePromise: writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
799
+ writePromise: () =>
800
+ writeFileForSlpk(slpkCompressedGeometryPath, compressedGeometry, '1.bin')
876
801
  });
877
802
  } else {
878
803
  const compressedGeometryPath = join(childPath, 'geometries/1/');
879
- this.writeQueue.enqueue({
880
- writePromise: writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
804
+ await this.writeQueue.enqueue({
805
+ writePromise: () => writeFile(compressedGeometryPath, compressedGeometry, 'index.bin')
881
806
  });
882
807
  }
883
808
  }
@@ -904,13 +829,13 @@ export default class I3SConverter {
904
829
  const sharedDataStr = JSON.stringify(sharedData);
905
830
  if (this.options.slpk) {
906
831
  const slpkSharedPath = join(childPath, 'shared');
907
- this.writeQueue.enqueue({
832
+ await this.writeQueue.enqueue({
908
833
  archiveKey: `${slpkChildPath}/shared/sharedResource.json.gz`,
909
- writePromise: writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
834
+ writePromise: () => writeFileForSlpk(slpkSharedPath, sharedDataStr, 'sharedResource.json')
910
835
  });
911
836
  } else {
912
837
  const sharedPath = join(childPath, 'shared/');
913
- this.writeQueue.enqueue({writePromise: writeFile(sharedPath, sharedDataStr)});
838
+ await this.writeQueue.enqueue({writePromise: () => writeFile(sharedPath, sharedDataStr)});
914
839
  }
915
840
  }
916
841
 
@@ -978,6 +903,7 @@ export default class I3SConverter {
978
903
 
979
904
  if (!this.layers0!.textureSetDefinitions!.length) {
980
905
  this.layers0!.textureSetDefinitions!.push({formats});
906
+ this.layers0!.textureSetDefinitions!.push({formats, atlas: true});
981
907
  }
982
908
  }
983
909
  }
@@ -1001,14 +927,15 @@ export default class I3SConverter {
1001
927
  const slpkTexturePath = join(childPath, 'textures');
1002
928
  const compress = false;
1003
929
 
1004
- this.writeQueue.enqueue({
930
+ await this.writeQueue.enqueue({
1005
931
  archiveKey: `${slpkChildPath}/textures/${name}.${format}`,
1006
- writePromise: writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
932
+ writePromise: () =>
933
+ writeFileForSlpk(slpkTexturePath, textureData, `${name}.${format}`, compress)
1007
934
  });
1008
935
  } else {
1009
936
  const texturePath = join(childPath, `textures/${name}/`);
1010
- this.writeQueue.enqueue({
1011
- writePromise: writeFile(texturePath, textureData, `index.${format}`)
937
+ await this.writeQueue.enqueue({
938
+ writePromise: () => writeFile(texturePath, textureData, `index.${format}`)
1012
939
  });
1013
940
  }
1014
941
  }
@@ -1031,14 +958,14 @@ export default class I3SConverter {
1031
958
 
1032
959
  if (this.options.slpk) {
1033
960
  const slpkAttributesPath = join(childPath, 'attributes', folderName);
1034
- this.writeQueue.enqueue({
961
+ await this.writeQueue.enqueue({
1035
962
  archiveKey: `${slpkChildPath}/attributes/${folderName}.bin.gz`,
1036
- writePromise: writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
963
+ writePromise: () => writeFileForSlpk(slpkAttributesPath, fileBuffer, '0.bin')
1037
964
  });
1038
965
  } else {
1039
966
  const attributesPath = join(childPath, `attributes/${folderName}/0`);
1040
- this.writeQueue.enqueue({
1041
- writePromise: writeFile(attributesPath, fileBuffer, 'index.bin')
967
+ await this.writeQueue.enqueue({
968
+ writePromise: () => writeFile(attributesPath, fileBuffer, 'index.bin')
1042
969
  });
1043
970
  }
1044
971
  }
@@ -1070,7 +997,7 @@ export default class I3SConverter {
1070
997
  private _findOrCreateMaterial(material: I3SMaterialDefinition): number {
1071
998
  const hash = md5(JSON.stringify(material));
1072
999
  if (this.materialMap.has(hash)) {
1073
- return this.materialMap.get(hash);
1000
+ return this.materialMap.get(hash) || 0;
1074
1001
  }
1075
1002
  const newMaterialId = this.materialDefinitions.push(material) - 1;
1076
1003
  this.materialMap.set(hash, newMaterialId);
@@ -1078,133 +1005,42 @@ export default class I3SConverter {
1078
1005
  }
1079
1006
 
1080
1007
  /**
1081
- * Generate storage attribute for map segmentation.
1082
- * @param attributeIndex - order index of attribute (f_0, f_1 ...).
1083
- * @param key - attribute key from batch table.\
1084
- * @param attributeType - attribute type.
1085
- * @return Updated storageAttribute.
1086
- */
1087
- private _createdStorageAttribute(
1088
- attributeIndex: number,
1089
- key: string,
1090
- attributeType: Attribute
1091
- ): AttributeStorageInfo {
1092
- const storageAttribute = {
1093
- key: `f_${attributeIndex}`,
1094
- name: key,
1095
- ordering: ['attributeValues'],
1096
- header: [{property: 'count', valueType: 'UInt32'}],
1097
- attributeValues: {valueType: 'Int32', valuesPerElement: 1}
1098
- };
1099
-
1100
- switch (attributeType) {
1101
- case OBJECT_ID_TYPE:
1102
- this._setupIdAttribute(storageAttribute);
1103
- break;
1104
- case STRING_TYPE:
1105
- this._setupStringAttribute(storageAttribute);
1106
- break;
1107
- case DOUBLE_TYPE:
1108
- this._setupDoubleAttribute(storageAttribute);
1109
- break;
1110
- case SHORT_INT_TYPE:
1111
- break;
1112
- default:
1113
- this._setupStringAttribute(storageAttribute);
1114
- }
1115
-
1116
- return storageAttribute;
1117
- }
1118
-
1119
- /**
1120
- * Get the attribute type for attributeStorageInfo https://github.com/Esri/i3s-spec/blob/master/docs/1.7/attributeStorageInfo.cmn.md
1121
- * @param key - attribute's key
1122
- * @param attribute - attribute's type in batchTable
1008
+ * Get unique geometry configuration index
1009
+ * In the end of conversion configurations will be transformed to geometryDefinitions array
1010
+ * @param hasTexture
1011
+ * @param hasUvRegions
1012
+ * @returns
1123
1013
  */
1124
- private getAttributeType(key: string, attribute: string): string {
1125
- if (key === OBJECT_ID_TYPE) {
1126
- return OBJECT_ID_TYPE;
1127
- }
1128
- if (typeof attribute === STRING_TYPE) {
1129
- return STRING_TYPE;
1130
- } else if (typeof attribute === 'number') {
1131
- return Number.isInteger(attribute) ? SHORT_INT_TYPE : DOUBLE_TYPE;
1014
+ private findOrCreateGeometryDefinition(hasTexture: boolean, hasUvRegions: boolean): number {
1015
+ const geometryConfig = {hasTexture, hasUvRegions};
1016
+ const hash = md5(JSON.stringify(geometryConfig));
1017
+ if (this.geometryMap.has(hash)) {
1018
+ return this.geometryMap.get(hash) || 0;
1132
1019
  }
1133
- return STRING_TYPE;
1134
- }
1135
-
1136
- /**
1137
- * Setup storage attribute as string.
1138
- * @param storageAttribute - attribute for map segmentation.
1139
- */
1140
- private _setupStringAttribute(storageAttribute: AttributeStorageInfo): void {
1141
- storageAttribute.ordering!.unshift('attributeByteCounts');
1142
- storageAttribute.header.push({property: 'attributeValuesByteCount', valueType: 'UInt32'});
1143
- storageAttribute.attributeValues = {
1144
- valueType: 'String',
1145
- encoding: 'UTF-8',
1146
- valuesPerElement: 1
1147
- };
1148
- storageAttribute.attributeByteCounts = {
1149
- valueType: 'UInt32',
1150
- valuesPerElement: 1
1151
- };
1152
- }
1153
-
1154
- /**
1155
- * Setup Id attribute for map segmentation.
1156
- * @param storageAttribute - attribute for map segmentation .
1157
- */
1158
- private _setupIdAttribute(storageAttribute: AttributeStorageInfo): void {
1159
- storageAttribute.attributeValues = {
1160
- valueType: 'Oid32',
1161
- valuesPerElement: 1
1162
- };
1163
- }
1164
-
1165
- /**
1166
- * Setup double attribute for map segmentation.
1167
- * @param storageAttribute - attribute for map segmentation .
1168
- */
1169
- private _setupDoubleAttribute(storageAttribute: AttributeStorageInfo): void {
1170
- storageAttribute.attributeValues = {
1171
- valueType: 'Float64',
1172
- valuesPerElement: 1
1173
- };
1174
- }
1175
-
1176
- /**
1177
- * Setup field attribute for map segmentation.
1178
- * @param key - attribute for map segmentation.
1179
- * @param fieldAttributeType - esri attribute type ('esriFieldTypeString' or 'esriFieldTypeOID').
1180
- */
1181
- private _createFieldAttribute(key: string, fieldAttributeType: ESRIField): Field {
1182
- return {
1183
- name: key,
1184
- type: fieldAttributeType,
1185
- alias: key
1186
- };
1020
+ const newGeometryId = this.geometryConfigs.push(geometryConfig) - 1;
1021
+ this.geometryMap.set(hash, newGeometryId);
1022
+ return newGeometryId;
1187
1023
  }
1188
1024
 
1189
1025
  /**
1190
- * Do conversion of 3DTiles batch table to I3s node attributes.
1191
- * @param batchTable - Table with layer meta data.
1026
+ * Do conversion of 3DTiles property table to I3s node attributes.
1027
+ * @param propertyTable - Table with layer meta data.
1192
1028
  */
1193
- private _convertBatchTableInfoToNodeAttributes(batchTable: BatchTableJson): void {
1029
+ private _convertPropertyTableToNodeAttributes(propertyTable: FeatureTableJson): void {
1194
1030
  let attributeIndex = 0;
1195
- const batchTableWithObjectId = {
1031
+ const propertyTableWithObjectId = {
1196
1032
  OBJECTID: [0],
1197
- ...batchTable
1033
+ ...propertyTable
1198
1034
  };
1199
1035
 
1200
- for (const key in batchTableWithObjectId) {
1201
- const firstAttribute = batchTableWithObjectId[key][0];
1202
- const attributeType = this.getAttributeType(key, firstAttribute);
1036
+ for (const key in propertyTableWithObjectId) {
1037
+ const firstAttribute = propertyTableWithObjectId[key][0];
1038
+ const attributeType = getAttributeType(key, firstAttribute);
1203
1039
 
1204
- const storageAttribute = this._createdStorageAttribute(attributeIndex, key, attributeType);
1205
- const fieldAttributeType = this._getFieldAttributeType(attributeType);
1206
- const fieldAttribute = this._createFieldAttribute(key, fieldAttributeType);
1207
- const popupInfo = this._createPopupInfo(batchTableWithObjectId);
1040
+ const storageAttribute = createdStorageAttribute(attributeIndex, key, attributeType);
1041
+ const fieldAttributeType = getFieldAttributeType(attributeType);
1042
+ const fieldAttribute = createFieldAttribute(key, fieldAttributeType);
1043
+ const popupInfo = createPopupInfo(propertyTableWithObjectId);
1208
1044
 
1209
1045
  this.layers0!.attributeStorageInfo!.push(storageAttribute);
1210
1046
  this.layers0!.fields!.push(fieldAttribute);
@@ -1215,62 +1051,6 @@ export default class I3SConverter {
1215
1051
  }
1216
1052
  }
1217
1053
 
1218
- /**
1219
- * Find and return attribute type based on key form Batch table.
1220
- * @param attributeType
1221
- */
1222
- private _getFieldAttributeType(attributeType: Attribute): ESRIField {
1223
- switch (attributeType) {
1224
- case OBJECT_ID_TYPE:
1225
- return 'esriFieldTypeOID';
1226
- case STRING_TYPE:
1227
- return 'esriFieldTypeString';
1228
- case SHORT_INT_TYPE:
1229
- return 'esriFieldTypeInteger';
1230
- case DOUBLE_TYPE:
1231
- return 'esriFieldTypeDouble';
1232
- default:
1233
- return 'esriFieldTypeString';
1234
- }
1235
- }
1236
-
1237
- /**
1238
- * Generate popup info to show metadata on the map.
1239
- * @param batchTable - Batch table data with OBJECTID.
1240
- * @return data for correct rendering of popup.
1241
- */
1242
- private _createPopupInfo(batchTable: BatchTableJson): PopupInfo {
1243
- const title = '{OBJECTID}';
1244
- const mediaInfos = [];
1245
- const fieldInfos: FieldInfo[] = [];
1246
- const popupElements: {
1247
- fieldInfos: FieldInfo[];
1248
- type: string;
1249
- }[] = [];
1250
- const expressionInfos = [];
1251
-
1252
- for (const key in batchTable) {
1253
- fieldInfos.push({
1254
- fieldName: key,
1255
- visible: true,
1256
- isEditable: false,
1257
- label: key
1258
- });
1259
- }
1260
- popupElements.push({
1261
- fieldInfos,
1262
- type: 'fields'
1263
- });
1264
-
1265
- return {
1266
- title,
1267
- mediaInfos,
1268
- popupElements,
1269
- fieldInfos,
1270
- expressionInfos
1271
- };
1272
- }
1273
-
1274
1054
  /**
1275
1055
  * Print statistics in the end of conversion
1276
1056
  * @param params - output files data