Add existing to tracked
This commit is contained in:
+740
@@ -0,0 +1,740 @@
|
||||
import Cartesian3 from "../Core/Cartesian3.js";
|
||||
import defined from "../Core/defined.js";
|
||||
import destroyObject from "../Core/destroyObject.js";
|
||||
import DeveloperError from "../Core/DeveloperError.js";
|
||||
import Ellipsoid from "../Core/Ellipsoid.js";
|
||||
import getJsonFromTypedArray from "../Core/getJsonFromTypedArray.js";
|
||||
import ComponentDatatype from "../Core/ComponentDatatype.js";
|
||||
import CesiumMath from "../Core/Math.js";
|
||||
import Matrix4 from "../Core/Matrix4.js";
|
||||
import Rectangle from "../Core/Rectangle.js";
|
||||
import RuntimeError from "../Core/RuntimeError.js";
|
||||
import Cesium3DTileBatchTable from "./Cesium3DTileBatchTable.js";
|
||||
import Cesium3DTileFeatureTable from "./Cesium3DTileFeatureTable.js";
|
||||
import Vector3DTilePoints from "./Vector3DTilePoints.js";
|
||||
import Vector3DTilePolygons from "./Vector3DTilePolygons.js";
|
||||
import Vector3DTilePolylines from "./Vector3DTilePolylines.js";
|
||||
import Vector3DTileClampedPolylines from "./Vector3DTileClampedPolylines.js";
|
||||
import decodeVectorPolylinePositions from "../Core/decodeVectorPolylinePositions.js";
|
||||
|
||||
/**
|
||||
* Represents the contents of a
|
||||
* {@link https://github.com/CesiumGS/3d-tiles/tree/vctr/TileFormats/VectorData|Vector}
|
||||
* tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification|3D Tiles} tileset.
|
||||
* <p>
|
||||
* Implements the {@link Cesium3DTileContent} interface.
|
||||
* </p>
|
||||
*
|
||||
* @implements Cesium3DTileContent
|
||||
* @private
|
||||
*/
|
||||
class Vector3DTileContent {
|
||||
constructor(tileset, tile, resource, arrayBuffer, byteOffset) {
|
||||
this._tileset = tileset;
|
||||
this._tile = tile;
|
||||
this._resource = resource;
|
||||
|
||||
this._polygons = undefined;
|
||||
this._polylines = undefined;
|
||||
this._points = undefined;
|
||||
|
||||
this._metadata = undefined;
|
||||
|
||||
this._batchTable = undefined;
|
||||
this._features = undefined;
|
||||
|
||||
/**
|
||||
* Part of the {@link Cesium3DTileContent} interface.
|
||||
*/
|
||||
this.featurePropertiesDirty = false;
|
||||
this._group = undefined;
|
||||
|
||||
this._ready = false;
|
||||
|
||||
initialize(this, arrayBuffer, byteOffset);
|
||||
}
|
||||
|
||||
get featuresLength() {
|
||||
return defined(this._batchTable) ? this._batchTable.featuresLength : 0;
|
||||
}
|
||||
|
||||
get pointsLength() {
|
||||
if (defined(this._points)) {
|
||||
return this._points.pointsLength;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
get trianglesLength() {
|
||||
let trianglesLength = 0;
|
||||
if (defined(this._polygons)) {
|
||||
trianglesLength += this._polygons.trianglesLength;
|
||||
}
|
||||
if (defined(this._polylines)) {
|
||||
trianglesLength += this._polylines.trianglesLength;
|
||||
}
|
||||
return trianglesLength;
|
||||
}
|
||||
|
||||
get geometryByteLength() {
|
||||
let geometryByteLength = 0;
|
||||
if (defined(this._polygons)) {
|
||||
geometryByteLength += this._polygons.geometryByteLength;
|
||||
}
|
||||
if (defined(this._polylines)) {
|
||||
geometryByteLength += this._polylines.geometryByteLength;
|
||||
}
|
||||
return geometryByteLength;
|
||||
}
|
||||
|
||||
get texturesByteLength() {
|
||||
if (defined(this._points)) {
|
||||
return this._points.texturesByteLength;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
get batchTableByteLength() {
|
||||
return defined(this._batchTable)
|
||||
? this._batchTable.batchTableByteLength
|
||||
: 0;
|
||||
}
|
||||
|
||||
get innerContents() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the tile's content is ready to render; otherwise false
|
||||
*
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
get ready() {
|
||||
return this._ready;
|
||||
}
|
||||
|
||||
get tileset() {
|
||||
return this._tileset;
|
||||
}
|
||||
|
||||
get tile() {
|
||||
return this._tile;
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this._resource.getUrlComponent(true);
|
||||
}
|
||||
|
||||
get metadata() {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
set metadata(value) {
|
||||
this._metadata = value;
|
||||
}
|
||||
|
||||
get batchTable() {
|
||||
return this._batchTable;
|
||||
}
|
||||
|
||||
get group() {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
set group(value) {
|
||||
this._group = value;
|
||||
}
|
||||
|
||||
hasProperty(batchId, name) {
|
||||
return this._batchTable.hasProperty(batchId, name);
|
||||
}
|
||||
|
||||
getFeature(batchId) {
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
const featuresLength = this.featuresLength;
|
||||
if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {
|
||||
throw new DeveloperError(
|
||||
`batchId is required and between zero and featuresLength - 1 (${
|
||||
featuresLength - 1
|
||||
}).`,
|
||||
);
|
||||
}
|
||||
//>>includeEnd('debug');
|
||||
|
||||
if (!defined(this._features)) {
|
||||
createFeatures(this);
|
||||
}
|
||||
|
||||
return this._features[batchId];
|
||||
}
|
||||
|
||||
applyDebugSettings(enabled, color) {
|
||||
if (defined(this._polygons)) {
|
||||
this._polygons.applyDebugSettings(enabled, color);
|
||||
}
|
||||
if (defined(this._polylines)) {
|
||||
this._polylines.applyDebugSettings(enabled, color);
|
||||
}
|
||||
if (defined(this._points)) {
|
||||
this._points.applyDebugSettings(enabled, color);
|
||||
}
|
||||
}
|
||||
|
||||
applyStyle(style) {
|
||||
if (!defined(this._features)) {
|
||||
createFeatures(this);
|
||||
}
|
||||
if (defined(this._polygons)) {
|
||||
this._polygons.applyStyle(style, this._features);
|
||||
}
|
||||
if (defined(this._polylines)) {
|
||||
this._polylines.applyStyle(style, this._features);
|
||||
}
|
||||
if (defined(this._points)) {
|
||||
this._points.applyStyle(style, this._features);
|
||||
}
|
||||
}
|
||||
|
||||
update(tileset, frameState) {
|
||||
let ready = true;
|
||||
if (defined(this._polygons)) {
|
||||
this._polygons.classificationType = this._tileset.classificationType;
|
||||
this._polygons.debugWireframe = this._tileset.debugWireframe;
|
||||
this._polygons.update(frameState);
|
||||
ready = ready && this._polygons.ready;
|
||||
}
|
||||
if (defined(this._polylines)) {
|
||||
this._polylines.update(frameState);
|
||||
ready = ready && this._polylines.ready;
|
||||
}
|
||||
if (defined(this._points)) {
|
||||
this._points.update(frameState);
|
||||
ready = ready && this._points.ready;
|
||||
}
|
||||
if (defined(this._batchTable) && ready) {
|
||||
if (!defined(this._features)) {
|
||||
createFeatures(this);
|
||||
}
|
||||
this._batchTable.update(tileset, frameState);
|
||||
this._ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
pick(ray, frameState, result) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getPolylinePositions(batchId) {
|
||||
const polylines = this._polylines;
|
||||
if (!defined(polylines)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return polylines.getPositions(batchId);
|
||||
}
|
||||
|
||||
isDestroyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._polygons = this._polygons && this._polygons.destroy();
|
||||
this._polylines = this._polylines && this._polylines.destroy();
|
||||
this._points = this._points && this._points.destroy();
|
||||
this._batchTable = this._batchTable && this._batchTable.destroy();
|
||||
return destroyObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
function createColorChangedCallback(content) {
|
||||
return function (batchId, color) {
|
||||
if (defined(content._polygons)) {
|
||||
content._polygons.updateCommands(batchId, color);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getBatchIds(featureTableJson, featureTableBinary) {
|
||||
let polygonBatchIds;
|
||||
let polylineBatchIds;
|
||||
let pointBatchIds;
|
||||
let i;
|
||||
|
||||
const numberOfPolygons = featureTableJson.POLYGONS_LENGTH ?? 0;
|
||||
const numberOfPolylines = featureTableJson.POLYLINES_LENGTH ?? 0;
|
||||
const numberOfPoints = featureTableJson.POINTS_LENGTH ?? 0;
|
||||
|
||||
if (numberOfPolygons > 0 && defined(featureTableJson.POLYGON_BATCH_IDS)) {
|
||||
const polygonBatchIdsByteOffset =
|
||||
featureTableBinary.byteOffset +
|
||||
featureTableJson.POLYGON_BATCH_IDS.byteOffset;
|
||||
polygonBatchIds = new Uint16Array(
|
||||
featureTableBinary.buffer,
|
||||
polygonBatchIdsByteOffset,
|
||||
numberOfPolygons,
|
||||
);
|
||||
}
|
||||
|
||||
if (numberOfPolylines > 0 && defined(featureTableJson.POLYLINE_BATCH_IDS)) {
|
||||
const polylineBatchIdsByteOffset =
|
||||
featureTableBinary.byteOffset +
|
||||
featureTableJson.POLYLINE_BATCH_IDS.byteOffset;
|
||||
polylineBatchIds = new Uint16Array(
|
||||
featureTableBinary.buffer,
|
||||
polylineBatchIdsByteOffset,
|
||||
numberOfPolylines,
|
||||
);
|
||||
}
|
||||
|
||||
if (numberOfPoints > 0 && defined(featureTableJson.POINT_BATCH_IDS)) {
|
||||
const pointBatchIdsByteOffset =
|
||||
featureTableBinary.byteOffset +
|
||||
featureTableJson.POINT_BATCH_IDS.byteOffset;
|
||||
pointBatchIds = new Uint16Array(
|
||||
featureTableBinary.buffer,
|
||||
pointBatchIdsByteOffset,
|
||||
numberOfPoints,
|
||||
);
|
||||
}
|
||||
|
||||
const atLeastOneDefined =
|
||||
defined(polygonBatchIds) ||
|
||||
defined(polylineBatchIds) ||
|
||||
defined(pointBatchIds);
|
||||
const atLeastOneUndefined =
|
||||
(numberOfPolygons > 0 && !defined(polygonBatchIds)) ||
|
||||
(numberOfPolylines > 0 && !defined(polylineBatchIds)) ||
|
||||
(numberOfPoints > 0 && !defined(pointBatchIds));
|
||||
|
||||
if (atLeastOneDefined && atLeastOneUndefined) {
|
||||
throw new RuntimeError(
|
||||
"If one group of batch ids is defined, then all batch ids must be defined",
|
||||
);
|
||||
}
|
||||
|
||||
const allUndefinedBatchIds =
|
||||
!defined(polygonBatchIds) &&
|
||||
!defined(polylineBatchIds) &&
|
||||
!defined(pointBatchIds);
|
||||
if (allUndefinedBatchIds) {
|
||||
let id = 0;
|
||||
if (!defined(polygonBatchIds) && numberOfPolygons > 0) {
|
||||
polygonBatchIds = new Uint16Array(numberOfPolygons);
|
||||
for (i = 0; i < numberOfPolygons; ++i) {
|
||||
polygonBatchIds[i] = id++;
|
||||
}
|
||||
}
|
||||
if (!defined(polylineBatchIds) && numberOfPolylines > 0) {
|
||||
polylineBatchIds = new Uint16Array(numberOfPolylines);
|
||||
for (i = 0; i < numberOfPolylines; ++i) {
|
||||
polylineBatchIds[i] = id++;
|
||||
}
|
||||
}
|
||||
if (!defined(pointBatchIds) && numberOfPoints > 0) {
|
||||
pointBatchIds = new Uint16Array(numberOfPoints);
|
||||
for (i = 0; i < numberOfPoints; ++i) {
|
||||
pointBatchIds[i] = id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
polygons: polygonBatchIds,
|
||||
polylines: polylineBatchIds,
|
||||
points: pointBatchIds,
|
||||
};
|
||||
}
|
||||
|
||||
const sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
|
||||
|
||||
function createFloatingPolylines(options) {
|
||||
return new Vector3DTilePolylines(options);
|
||||
}
|
||||
|
||||
function createClampedPolylines(options) {
|
||||
return new Vector3DTileClampedPolylines(options);
|
||||
}
|
||||
|
||||
function initialize(content, arrayBuffer, byteOffset) {
|
||||
byteOffset = byteOffset ?? 0;
|
||||
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
const view = new DataView(arrayBuffer);
|
||||
byteOffset += sizeOfUint32; // Skip magic number
|
||||
|
||||
const version = view.getUint32(byteOffset, true);
|
||||
if (version !== 1) {
|
||||
throw new RuntimeError(
|
||||
`Only Vector tile version 1 is supported. Version ${version} is not.`,
|
||||
);
|
||||
}
|
||||
byteOffset += sizeOfUint32;
|
||||
|
||||
const byteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
|
||||
if (byteLength === 0) {
|
||||
content._ready = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const featureTableJSONByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
|
||||
if (featureTableJSONByteLength === 0) {
|
||||
throw new RuntimeError(
|
||||
"Feature table must have a byte length greater than zero",
|
||||
);
|
||||
}
|
||||
|
||||
const featureTableBinaryByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
const batchTableJSONByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
const batchTableBinaryByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
const indicesByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
const positionByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
const polylinePositionByteLength = view.getUint32(byteOffset, true);
|
||||
byteOffset += sizeOfUint32;
|
||||
// Ignore pointsPositionByteLength
|
||||
byteOffset += sizeOfUint32; // For pointsPositionByteLength
|
||||
|
||||
const featureTableJson = getJsonFromTypedArray(
|
||||
uint8Array,
|
||||
byteOffset,
|
||||
featureTableJSONByteLength,
|
||||
);
|
||||
byteOffset += featureTableJSONByteLength;
|
||||
|
||||
const featureTableBinary = new Uint8Array(
|
||||
arrayBuffer,
|
||||
byteOffset,
|
||||
featureTableBinaryByteLength,
|
||||
);
|
||||
byteOffset += featureTableBinaryByteLength;
|
||||
|
||||
let batchTableJson;
|
||||
let batchTableBinary;
|
||||
if (batchTableJSONByteLength > 0) {
|
||||
// PERFORMANCE_IDEA: is it possible to allocate this on-demand? Perhaps keep the
|
||||
// arraybuffer/string compressed in memory and then decompress it when it is first accessed.
|
||||
//
|
||||
// We could also make another request for it, but that would make the property set/get
|
||||
// API async, and would double the number of numbers in some cases.
|
||||
batchTableJson = getJsonFromTypedArray(
|
||||
uint8Array,
|
||||
byteOffset,
|
||||
batchTableJSONByteLength,
|
||||
);
|
||||
byteOffset += batchTableJSONByteLength;
|
||||
|
||||
if (batchTableBinaryByteLength > 0) {
|
||||
// Has a batch table binary
|
||||
batchTableBinary = new Uint8Array(
|
||||
arrayBuffer,
|
||||
byteOffset,
|
||||
batchTableBinaryByteLength,
|
||||
);
|
||||
// Copy the batchTableBinary section and let the underlying ArrayBuffer be freed
|
||||
batchTableBinary = new Uint8Array(batchTableBinary);
|
||||
byteOffset += batchTableBinaryByteLength;
|
||||
}
|
||||
}
|
||||
|
||||
const numberOfPolygons = featureTableJson.POLYGONS_LENGTH ?? 0;
|
||||
const numberOfPolylines = featureTableJson.POLYLINES_LENGTH ?? 0;
|
||||
const numberOfPoints = featureTableJson.POINTS_LENGTH ?? 0;
|
||||
const totalPrimitives = numberOfPolygons + numberOfPolylines + numberOfPoints;
|
||||
|
||||
const batchTable = new Cesium3DTileBatchTable(
|
||||
content,
|
||||
totalPrimitives,
|
||||
batchTableJson,
|
||||
batchTableBinary,
|
||||
createColorChangedCallback(content),
|
||||
);
|
||||
content._batchTable = batchTable;
|
||||
|
||||
if (totalPrimitives === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const featureTable = new Cesium3DTileFeatureTable(
|
||||
featureTableJson,
|
||||
featureTableBinary,
|
||||
);
|
||||
const region = featureTable.getGlobalProperty("REGION");
|
||||
if (!defined(region)) {
|
||||
throw new RuntimeError(
|
||||
"Feature table global property: REGION must be defined",
|
||||
);
|
||||
}
|
||||
const rectangle = Rectangle.unpack(region);
|
||||
const minHeight = region[4];
|
||||
const maxHeight = region[5];
|
||||
|
||||
const modelMatrix = content._tile.computedTransform;
|
||||
|
||||
let center = featureTable.getGlobalProperty(
|
||||
"RTC_CENTER",
|
||||
ComponentDatatype.FLOAT,
|
||||
3,
|
||||
);
|
||||
if (defined(center)) {
|
||||
center = Cartesian3.unpack(center);
|
||||
Matrix4.multiplyByPoint(modelMatrix, center, center);
|
||||
} else {
|
||||
center = Rectangle.center(rectangle);
|
||||
center.height = CesiumMath.lerp(minHeight, maxHeight, 0.5);
|
||||
center = Ellipsoid.WGS84.cartographicToCartesian(center);
|
||||
}
|
||||
|
||||
const batchIds = getBatchIds(featureTableJson, featureTableBinary);
|
||||
byteOffset += (4 - (byteOffset % 4)) % 4;
|
||||
|
||||
if (numberOfPolygons > 0) {
|
||||
featureTable.featuresLength = numberOfPolygons;
|
||||
|
||||
const polygonCounts =
|
||||
featureTable.getPropertyArray(
|
||||
"POLYGON_COUNTS",
|
||||
ComponentDatatype.UNSIGNED_INT,
|
||||
1,
|
||||
) ??
|
||||
featureTable.getPropertyArray(
|
||||
"POLYGON_COUNT",
|
||||
ComponentDatatype.UNSIGNED_INT,
|
||||
1,
|
||||
); // Workaround for old vector tilesets using the non-plural name;
|
||||
|
||||
if (!defined(polygonCounts)) {
|
||||
throw new RuntimeError(
|
||||
"Feature table property: POLYGON_COUNTS must be defined when POLYGONS_LENGTH is greater than 0",
|
||||
);
|
||||
}
|
||||
|
||||
const polygonIndexCounts =
|
||||
featureTable.getPropertyArray(
|
||||
"POLYGON_INDEX_COUNTS",
|
||||
ComponentDatatype.UNSIGNED_INT,
|
||||
1,
|
||||
) ??
|
||||
featureTable.getPropertyArray(
|
||||
"POLYGON_INDEX_COUNT",
|
||||
ComponentDatatype.UNSIGNED_INT,
|
||||
1,
|
||||
); // Workaround for old vector tilesets using the non-plural name;
|
||||
|
||||
if (!defined(polygonIndexCounts)) {
|
||||
throw new RuntimeError(
|
||||
"Feature table property: POLYGON_INDEX_COUNTS must be defined when POLYGONS_LENGTH is greater than 0",
|
||||
);
|
||||
}
|
||||
|
||||
// Use the counts array to determine how many position values we want. If we used the byte length then
|
||||
// zero padding values would be included and cause the delta zig-zag decoding to fail
|
||||
const numPolygonPositions = polygonCounts.reduce(function (total, count) {
|
||||
return total + count * 2;
|
||||
}, 0);
|
||||
|
||||
const numPolygonIndices = polygonIndexCounts.reduce(function (
|
||||
total,
|
||||
count,
|
||||
) {
|
||||
return total + count;
|
||||
}, 0);
|
||||
|
||||
const indices = new Uint32Array(arrayBuffer, byteOffset, numPolygonIndices);
|
||||
byteOffset += indicesByteLength;
|
||||
|
||||
const polygonPositions = new Uint16Array(
|
||||
arrayBuffer,
|
||||
byteOffset,
|
||||
numPolygonPositions,
|
||||
);
|
||||
byteOffset += positionByteLength;
|
||||
|
||||
let polygonMinimumHeights;
|
||||
let polygonMaximumHeights;
|
||||
if (
|
||||
defined(featureTableJson.POLYGON_MINIMUM_HEIGHTS) &&
|
||||
defined(featureTableJson.POLYGON_MAXIMUM_HEIGHTS)
|
||||
) {
|
||||
polygonMinimumHeights = featureTable.getPropertyArray(
|
||||
"POLYGON_MINIMUM_HEIGHTS",
|
||||
ComponentDatatype.FLOAT,
|
||||
1,
|
||||
);
|
||||
polygonMaximumHeights = featureTable.getPropertyArray(
|
||||
"POLYGON_MAXIMUM_HEIGHTS",
|
||||
ComponentDatatype.FLOAT,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
content._polygons = new Vector3DTilePolygons({
|
||||
positions: polygonPositions,
|
||||
counts: polygonCounts,
|
||||
indexCounts: polygonIndexCounts,
|
||||
indices: indices,
|
||||
minimumHeight: minHeight,
|
||||
maximumHeight: maxHeight,
|
||||
polygonMinimumHeights: polygonMinimumHeights,
|
||||
polygonMaximumHeights: polygonMaximumHeights,
|
||||
center: center,
|
||||
rectangle: rectangle,
|
||||
boundingVolume: content.tile.boundingVolume.boundingVolume,
|
||||
batchTable: batchTable,
|
||||
batchIds: batchIds.polygons,
|
||||
modelMatrix: modelMatrix,
|
||||
});
|
||||
}
|
||||
const tileset = content._tileset;
|
||||
if (numberOfPolylines > 0) {
|
||||
featureTable.featuresLength = numberOfPolylines;
|
||||
|
||||
const polylineCounts =
|
||||
featureTable.getPropertyArray(
|
||||
"POLYLINE_COUNTS",
|
||||
ComponentDatatype.UNSIGNED_INT,
|
||||
1,
|
||||
) ??
|
||||
featureTable.getPropertyArray(
|
||||
"POLYLINE_COUNT",
|
||||
ComponentDatatype.UNSIGNED_INT,
|
||||
1,
|
||||
); // Workaround for old vector tilesets using the non-plural name;
|
||||
|
||||
if (!defined(polylineCounts)) {
|
||||
throw new RuntimeError(
|
||||
"Feature table property: POLYLINE_COUNTS must be defined when POLYLINES_LENGTH is greater than 0",
|
||||
);
|
||||
}
|
||||
|
||||
let widths = featureTable.getPropertyArray(
|
||||
"POLYLINE_WIDTHS",
|
||||
ComponentDatatype.UNSIGNED_SHORT,
|
||||
1,
|
||||
);
|
||||
if (!defined(widths)) {
|
||||
widths = new Uint16Array(numberOfPolylines);
|
||||
for (let i = 0; i < numberOfPolylines; ++i) {
|
||||
widths[i] = 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the counts array to determine how many position values we want. If we used the byte length then
|
||||
// zero padding values would be included and cause the delta zig-zag decoding to fail
|
||||
const numPolylinePositions = polylineCounts.reduce(function (total, count) {
|
||||
return total + count * 3;
|
||||
}, 0);
|
||||
const polylinePositions = new Uint16Array(
|
||||
arrayBuffer,
|
||||
byteOffset,
|
||||
numPolylinePositions,
|
||||
);
|
||||
byteOffset += polylinePositionByteLength;
|
||||
|
||||
const examineVectorLinesFunction = tileset.examineVectorLinesFunction;
|
||||
if (defined(examineVectorLinesFunction)) {
|
||||
const decodedPositions = decodeVectorPolylinePositions(
|
||||
new Uint16Array(polylinePositions),
|
||||
rectangle,
|
||||
minHeight,
|
||||
maxHeight,
|
||||
Ellipsoid.WGS84,
|
||||
);
|
||||
examineVectorLines(
|
||||
decodedPositions,
|
||||
polylineCounts,
|
||||
batchIds.polylines,
|
||||
batchTable,
|
||||
content.url,
|
||||
examineVectorLinesFunction,
|
||||
);
|
||||
}
|
||||
|
||||
let createPolylines = createFloatingPolylines;
|
||||
if (defined(tileset.classificationType)) {
|
||||
createPolylines = createClampedPolylines;
|
||||
}
|
||||
|
||||
content._polylines = createPolylines({
|
||||
positions: polylinePositions,
|
||||
widths: widths,
|
||||
counts: polylineCounts,
|
||||
batchIds: batchIds.polylines,
|
||||
minimumHeight: minHeight,
|
||||
maximumHeight: maxHeight,
|
||||
center: center,
|
||||
rectangle: rectangle,
|
||||
boundingVolume: content.tile.boundingVolume.boundingVolume,
|
||||
batchTable: batchTable,
|
||||
classificationType: tileset.classificationType,
|
||||
keepDecodedPositions: tileset.vectorKeepDecodedPositions,
|
||||
});
|
||||
}
|
||||
|
||||
if (numberOfPoints > 0) {
|
||||
const pointPositions = new Uint16Array(
|
||||
arrayBuffer,
|
||||
byteOffset,
|
||||
numberOfPoints * 3,
|
||||
);
|
||||
content._points = new Vector3DTilePoints({
|
||||
positions: pointPositions,
|
||||
batchIds: batchIds.points,
|
||||
minimumHeight: minHeight,
|
||||
maximumHeight: maxHeight,
|
||||
rectangle: rectangle,
|
||||
batchTable: batchTable,
|
||||
heightReference: tileset.heightReference,
|
||||
scene: tileset.scene,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createFeatures(content) {
|
||||
const featuresLength = content.featuresLength;
|
||||
if (!defined(content._features) && featuresLength > 0) {
|
||||
const features = new Array(featuresLength);
|
||||
|
||||
if (defined(content._polygons)) {
|
||||
content._polygons.createFeatures(content, features);
|
||||
}
|
||||
if (defined(content._polylines)) {
|
||||
content._polylines.createFeatures(content, features);
|
||||
}
|
||||
if (defined(content._points)) {
|
||||
content._points.createFeatures(content, features);
|
||||
}
|
||||
content._features = features;
|
||||
}
|
||||
}
|
||||
|
||||
function examineVectorLines(
|
||||
positions,
|
||||
counts,
|
||||
batchIds,
|
||||
batchTable,
|
||||
url,
|
||||
callback,
|
||||
) {
|
||||
const countsLength = counts.length;
|
||||
let polylineStart = 0;
|
||||
for (let i = 0; i < countsLength; i++) {
|
||||
const count = counts[i] * 3;
|
||||
const linePositions = positions.slice(polylineStart, polylineStart + count);
|
||||
polylineStart += count;
|
||||
|
||||
callback(linePositions, batchIds[i], url, batchTable);
|
||||
}
|
||||
}
|
||||
|
||||
export default Vector3DTileContent;
|
||||
Reference in New Issue
Block a user