15832144755
2022-01-06 7b4c8991dca9cf2a809a95e239d144697d3afb56
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
import Check from "../Core/Check.js";
import clone from "../Core/clone.js";
import defined from "../Core/defined.js";
import Resource from "../Core/Resource.js";
import RuntimeError from "../Core/RuntimeError.js";
import hasExtension from "./hasExtension.js";
import ImplicitSubdivisionScheme from "./ImplicitSubdivisionScheme.js";
 
/**
 * An ImplicitTileset is a simple struct that stores information about the
 * structure of a single implicit tileset. This includes template URIs for
 * locating resources, details from the implicit root tile (bounding volume,
 * geometricError, etc.), and details about the subtrees (e.g. subtreeLevels,
 * subdivisionScheme).
 *
 * @alias ImplicitTileset
 * @constructor
 *
 * @param {Resource} baseResource The base resource for the tileset
 * @param {Object} tileJson The JSON header of the tile with the 3DTILES_implicit_tiling extension.
 * @param {MetadataSchema} [metadataSchema] The metadata schema containing the implicit tile metadata class.
 * @private
 * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
 */
export default function ImplicitTileset(
  baseResource,
  tileJson,
  metadataSchema
) {
  var extension = tileJson.extensions["3DTILES_implicit_tiling"];
  //>>includeStart('debug', pragmas.debug);
  Check.typeOf.object(
    'tileJson.extensions["3DTILES_implicit_tiling"]',
    extension
  );
  //>>includeEnd('debug');
 
  /**
   * The base resource for the tileset. This is stored here as it is needed
   * later when expanding Implicit3DTileContents so tile URLs are relative
   * to the tileset, not the subtree file.
   *
   * @type {Resource}
   * @readonly
   * @private
   */
  this.baseResource = baseResource;
 
  /**
   * The geometric error of the root tile
   *
   * @type {Number}
   * @readonly
   * @private
   */
  this.geometricError = tileJson.geometricError;
 
  /**
   * The metadata schema containing the implicit tile metadata class.
   *
   * @type {MetadataSchema|undefined}
   * @readonly
   * @private
   */
  this.metadataSchema = metadataSchema;
 
  if (
    !defined(tileJson.boundingVolume.box) &&
    !defined(tileJson.boundingVolume.region) &&
    !hasExtension(tileJson.boundingVolume, "3DTILES_bounding_volume_S2")
  ) {
    throw new RuntimeError(
      "Only box, region and 3DTILES_bounding_volume_S2 are supported for implicit tiling"
    );
  }
 
  /**
   * The JSON representation of a bounding volume. This is either a box or a
   * region.
   *
   * @type {Object}
   * @readonly
   * @private
   */
  this.boundingVolume = tileJson.boundingVolume;
 
  /**
   * The refine strategy as a string, either 'ADD' or 'REPLACE'
   *
   * @type {String}
   * @readonly
   * @private
   */
  this.refine = tileJson.refine;
 
  /**
   * Template URI for the subtree resources, e.g.
   * <code>https://example.com/{level}/{x}/{y}.subtree</code>
   *
   * @type {Resource}
   * @readonly
   * @private
   */
 
  this.subtreeUriTemplate = new Resource({ url: extension.subtrees.uri });
 
  /**
   * Template URIs for locating content resources, e.g.
   * <code>https://example.com/{level}/{x}/{y}.b3dm</code>.
   * <p>
   * This is an array to support <code>3DTILES_multiple_contents</code>
   * </p>
   *
   * @type {Resource[]}
   * @readonly
   * @private
   */
  this.contentUriTemplates = [];
 
  /**
   * Store a copy of the content headers, so properties such as
   * <code>extras</code> or <code>extensions</code> are preserved when
   * {@link Cesium3DTile}s are created for each tile.
   * <p>
   * This is an array to support <code>3DTILES_multiple_contents</code>
   * </p>
   *
   * @type {Object[]}
   * @readonly
   * @private
   */
  this.contentHeaders = [];
 
  var contentHeaders = gatherContentHeaders(tileJson);
  for (var i = 0; i < contentHeaders.length; i++) {
    var contentHeader = contentHeaders[i];
    this.contentHeaders.push(clone(contentHeader, true));
    var contentResource = new Resource({ url: contentHeader.uri });
    this.contentUriTemplates.push(contentResource);
  }
 
  /**
   * The maximum number of contents as well as content availability bitstreams.
   * This is used for loop bounds when checking content availability.
   *
   * @type {Number}
   * @readonly
   * @private
   */
  this.contentCount = this.contentHeaders.length;
 
  /**
   * Stores a copy of the root implicit tile's JSON header. This is used
   * as a template for creating {@link Cesium3DTile}s. The following properties
   * are removed:
   *
   * <ul>
   * <li><code>tile.extensions["3DTILES_implicit_tiling"]</code> to prevent infinite loops of implicit tiling</li>
   * <li><code>tile.content</code> since this is handled separately</li>
   * <li><code>tile.extensions["3DTILES_multiple_contents"]</code>, again
   *  because contents are handled separately</li>
   * </ul>
   *
   * @type {Object}
   * @readonly
   * @private
   */
  this.tileHeader = makeTileHeaderTemplate(tileJson);
 
  /**
   * The subdivision scheme for this implicit tileset; either OCTREE or QUADTREE
   *
   * @type {ImplicitSubdivisionScheme}
   * @readonly
   * @private
   */
  this.subdivisionScheme =
    ImplicitSubdivisionScheme[extension.subdivisionScheme];
 
  /**
   * The branching factor for this tileset. Either 4 for quadtrees or 8 for
   * octrees.
   *
   * @type {Number}
   * @readonly
   * @private
   */
  this.branchingFactor = ImplicitSubdivisionScheme.getBranchingFactor(
    this.subdivisionScheme
  );
 
  /**
   * How many distinct levels within each subtree. For example, a quadtree
   * with subtreeLevels = 2 will have 5 nodes per quadtree (1 root + 4 children)
   *
   * @type {Number}
   * @readonly
   * @private
   */
  this.subtreeLevels = extension.subtreeLevels;
 
  /**
   * The deepest level of any available tile in the entire tileset.
   *
   * @type {Number}
   * @readonly
   * @private
   */
  this.maximumLevel = extension.maximumLevel;
}
 
/**
 * Gather JSON headers for all contents in the tile.
 * This handles both regular tiles and tiles with the
 * `3DTILES_multiple_contents` extension
 *
 * @param {Object} tileJson The JSON header of the tile with the 3DTILES_implicit_tiling extension.
 * @return {Object[]} An array of JSON headers for the contents of each tile
 * @private
 */
function gatherContentHeaders(tileJson) {
  if (hasExtension(tileJson, "3DTILES_multiple_contents")) {
    return tileJson.extensions["3DTILES_multiple_contents"].content;
  }
 
  if (defined(tileJson.content)) {
    return [tileJson.content];
  }
 
  return [];
}
 
function makeTileHeaderTemplate(tileJson) {
  var template = clone(tileJson, true);
 
  // remove the implicit tiling extension to prevent infinite loops
  delete template.extensions["3DTILES_implicit_tiling"];
 
  // content is handled separately, so remove content-related properties
  delete template.content;
  delete template.extensions["3DTILES_multiple_contents"];
 
  // if there are no other extensions, remove the extensions property to
  // keep each tile simple
  if (Object.keys(template.extensions).length === 0) {
    delete template.extensions;
  }
 
  return template;
}