Add existing to tracked
This commit is contained in:
+548
@@ -0,0 +1,548 @@
|
||||
import Cartesian2 from "../Core/Cartesian2.js";
|
||||
import Cartesian3 from "../Core/Cartesian3.js";
|
||||
import Color from "../Core/Color.js";
|
||||
import defined from "../Core/defined.js";
|
||||
import destroyObject from "../Core/destroyObject.js";
|
||||
import DistanceDisplayCondition from "../Core/DistanceDisplayCondition.js";
|
||||
import Ellipsoid from "../Core/Ellipsoid.js";
|
||||
import NearFarScalar from "../Core/NearFarScalar.js";
|
||||
import Rectangle from "../Core/Rectangle.js";
|
||||
import TaskProcessor from "../Core/TaskProcessor.js";
|
||||
import BillboardCollection from "./BillboardCollection.js";
|
||||
import Cesium3DTilePointFeature from "./Cesium3DTilePointFeature.js";
|
||||
import HorizontalOrigin from "./HorizontalOrigin.js";
|
||||
import LabelCollection from "./LabelCollection.js";
|
||||
import LabelStyle from "./LabelStyle.js";
|
||||
import PolylineCollection from "./PolylineCollection.js";
|
||||
import VerticalOrigin from "./VerticalOrigin.js";
|
||||
import HeightReference from "./HeightReference.js";
|
||||
|
||||
/**
|
||||
* Creates a batch of points or billboards and labels.
|
||||
*
|
||||
* @alias Vector3DTilePoints
|
||||
* @constructor
|
||||
*
|
||||
* @param {object} options An object with following properties:
|
||||
* @param {Uint16Array} options.positions The positions of the polygons.
|
||||
* @param {number} options.minimumHeight The minimum height of the terrain covered by the tile.
|
||||
* @param {number} options.maximumHeight The maximum height of the terrain covered by the tile.
|
||||
* @param {Rectangle} options.rectangle The rectangle containing the tile.
|
||||
* @param {HeightReference} options.heightReference Determines how billboard and label features are positioned relative to terrain or 3d tiles.
|
||||
* @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polygons.
|
||||
* @param {Uint16Array} options.batchIds The batch ids for each polygon.
|
||||
* @param {Scene} options.scene The Cesium Viewer {@link Scene}. This is required for clamping billboards and labels with {@link HeightReference}
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function Vector3DTilePoints(options) {
|
||||
// released after the first update
|
||||
this._positions = options.positions;
|
||||
|
||||
this._batchTable = options.batchTable;
|
||||
this._batchIds = options.batchIds;
|
||||
|
||||
this._rectangle = options.rectangle;
|
||||
this._minHeight = options.minimumHeight;
|
||||
this._maxHeight = options.maximumHeight;
|
||||
this._heightReference = options.heightReference;
|
||||
|
||||
this._billboardCollection = new BillboardCollection({
|
||||
batchTable: options.batchTable,
|
||||
scene: options.scene,
|
||||
});
|
||||
this._labelCollection = new LabelCollection({
|
||||
batchTable: options.batchTable,
|
||||
scene: options.scene,
|
||||
});
|
||||
this._polylineCollection = new PolylineCollection();
|
||||
this._polylineCollection._useHighlightColor = true;
|
||||
|
||||
this._packedBuffer = undefined;
|
||||
|
||||
this._ready = false;
|
||||
this._promise = undefined;
|
||||
this._error = undefined;
|
||||
}
|
||||
|
||||
Object.defineProperties(Vector3DTilePoints.prototype, {
|
||||
/**
|
||||
* Returns true if the points are ready to render
|
||||
*
|
||||
* @memberof Vector3DTilePoints.prototype
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
ready: {
|
||||
get: function () {
|
||||
return this._ready;
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the number of points.
|
||||
*
|
||||
* @memberof Vector3DTilePoints.prototype
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
pointsLength: {
|
||||
get: function () {
|
||||
return this._billboardCollection.length;
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the texture atlas memory in bytes.
|
||||
*
|
||||
* @memberof Vector3DTilePoints.prototype
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
texturesByteLength: {
|
||||
get: function () {
|
||||
const billboardSize = this._billboardCollection.sizeInBytes;
|
||||
const labelSize = this._labelCollection.sizeInBytes;
|
||||
return billboardSize + labelSize;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function packBuffer(points, ellipsoid) {
|
||||
const rectangle = points._rectangle;
|
||||
const minimumHeight = points._minHeight;
|
||||
const maximumHeight = points._maxHeight;
|
||||
|
||||
const packedLength = 2 + Rectangle.packedLength + Ellipsoid.packedLength;
|
||||
const packedBuffer = new Float64Array(packedLength);
|
||||
|
||||
let offset = 0;
|
||||
packedBuffer[offset++] = minimumHeight;
|
||||
packedBuffer[offset++] = maximumHeight;
|
||||
|
||||
Rectangle.pack(rectangle, packedBuffer, offset);
|
||||
offset += Rectangle.packedLength;
|
||||
|
||||
Ellipsoid.pack(ellipsoid, packedBuffer, offset);
|
||||
|
||||
return packedBuffer;
|
||||
}
|
||||
|
||||
const createVerticesTaskProcessor = new TaskProcessor(
|
||||
"createVectorTilePoints",
|
||||
5,
|
||||
);
|
||||
const scratchPosition = new Cartesian3();
|
||||
|
||||
function createPoints(points, ellipsoid) {
|
||||
let positions = points._positions;
|
||||
let packedBuffer = points._packedBuffer;
|
||||
|
||||
if (!defined(packedBuffer)) {
|
||||
// Copy because they may be the views on the same buffer.
|
||||
positions = points._positions = positions.slice();
|
||||
points._batchIds = points._batchIds.slice();
|
||||
|
||||
packedBuffer = points._packedBuffer = packBuffer(points, ellipsoid);
|
||||
}
|
||||
|
||||
const transferrableObjects = [positions.buffer, packedBuffer.buffer];
|
||||
const parameters = {
|
||||
positions: positions.buffer,
|
||||
packedBuffer: packedBuffer.buffer,
|
||||
};
|
||||
|
||||
const verticesPromise = createVerticesTaskProcessor.scheduleTask(
|
||||
parameters,
|
||||
transferrableObjects,
|
||||
);
|
||||
if (!defined(verticesPromise)) {
|
||||
// Postponed
|
||||
return;
|
||||
}
|
||||
|
||||
return verticesPromise
|
||||
.then((result) => {
|
||||
if (points.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
points._positions = new Float64Array(result.positions);
|
||||
const billboardCollection = points._billboardCollection;
|
||||
const labelCollection = points._labelCollection;
|
||||
const polylineCollection = points._polylineCollection;
|
||||
positions = points._positions;
|
||||
const batchIds = points._batchIds;
|
||||
const numberOfPoints = positions.length / 3;
|
||||
|
||||
const heightReference = points._heightReference ?? HeightReference.NONE;
|
||||
|
||||
for (let i = 0; i < numberOfPoints; ++i) {
|
||||
const id = batchIds[i];
|
||||
|
||||
const position = Cartesian3.unpack(positions, i * 3, scratchPosition);
|
||||
|
||||
const b = billboardCollection.add();
|
||||
b.position = position;
|
||||
b._batchIndex = id;
|
||||
b.heightReference = heightReference;
|
||||
|
||||
const l = labelCollection.add();
|
||||
l.text = " ";
|
||||
l.position = position;
|
||||
l._batchIndex = id;
|
||||
l.heightReference = heightReference;
|
||||
|
||||
const p = polylineCollection.add();
|
||||
p.positions = [Cartesian3.clone(position), Cartesian3.clone(position)];
|
||||
}
|
||||
|
||||
points._positions = undefined;
|
||||
points._packedBuffer = undefined;
|
||||
points._ready = true;
|
||||
})
|
||||
.catch((error) => {
|
||||
if (points.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw the error next frame
|
||||
points._error = error;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates features for each point and places it at the batch id index of features.
|
||||
*
|
||||
* @param {Vector3DTileContent} content The vector tile content.
|
||||
* @param {Cesium3DTileFeature[]} features An array of features where the point features will be placed.
|
||||
*/
|
||||
Vector3DTilePoints.prototype.createFeatures = function (content, features) {
|
||||
const billboardCollection = this._billboardCollection;
|
||||
const labelCollection = this._labelCollection;
|
||||
const polylineCollection = this._polylineCollection;
|
||||
|
||||
const batchIds = this._batchIds;
|
||||
const length = batchIds.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const batchId = batchIds[i];
|
||||
|
||||
const billboard = billboardCollection.get(i);
|
||||
const label = labelCollection.get(i);
|
||||
const polyline = polylineCollection.get(i);
|
||||
|
||||
features[batchId] = new Cesium3DTilePointFeature(
|
||||
content,
|
||||
batchId,
|
||||
billboard,
|
||||
label,
|
||||
polyline,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Colors the entire tile when enabled is true. The resulting color will be (batch table color * color).
|
||||
*
|
||||
* @param {boolean} enabled Whether to enable debug coloring.
|
||||
* @param {Color} color The debug color.
|
||||
*/
|
||||
Vector3DTilePoints.prototype.applyDebugSettings = function (enabled, color) {
|
||||
if (enabled) {
|
||||
Color.clone(color, this._billboardCollection._highlightColor);
|
||||
Color.clone(color, this._labelCollection._highlightColor);
|
||||
Color.clone(color, this._polylineCollection._highlightColor);
|
||||
} else {
|
||||
Color.clone(Color.WHITE, this._billboardCollection._highlightColor);
|
||||
Color.clone(Color.WHITE, this._labelCollection._highlightColor);
|
||||
Color.clone(Color.WHITE, this._polylineCollection._highlightColor);
|
||||
}
|
||||
};
|
||||
|
||||
function clearStyle(polygons, features) {
|
||||
const batchIds = polygons._batchIds;
|
||||
const length = batchIds.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const batchId = batchIds[i];
|
||||
const feature = features[batchId];
|
||||
|
||||
feature.show = true;
|
||||
feature.pointSize = Cesium3DTilePointFeature.defaultPointSize;
|
||||
feature.color = Cesium3DTilePointFeature.defaultColor;
|
||||
feature.pointOutlineColor =
|
||||
Cesium3DTilePointFeature.defaultPointOutlineColor;
|
||||
feature.pointOutlineWidth =
|
||||
Cesium3DTilePointFeature.defaultPointOutlineWidth;
|
||||
feature.labelColor = Color.WHITE;
|
||||
feature.labelOutlineColor = Color.WHITE;
|
||||
feature.labelOutlineWidth = 1.0;
|
||||
feature.font = "30px sans-serif";
|
||||
feature.labelStyle = LabelStyle.FILL;
|
||||
feature.labelText = undefined;
|
||||
feature.backgroundColor = new Color(0.165, 0.165, 0.165, 0.8);
|
||||
feature.backgroundPadding = new Cartesian2(7, 5);
|
||||
feature.backgroundEnabled = false;
|
||||
feature.scaleByDistance = undefined;
|
||||
feature.translucencyByDistance = undefined;
|
||||
feature.distanceDisplayCondition = undefined;
|
||||
feature.heightOffset = 0.0;
|
||||
feature.anchorLineEnabled = false;
|
||||
feature.anchorLineColor = Color.WHITE;
|
||||
feature.image = undefined;
|
||||
feature.disableDepthTestDistance = 0.0;
|
||||
feature.horizontalOrigin = HorizontalOrigin.CENTER;
|
||||
feature.verticalOrigin = VerticalOrigin.CENTER;
|
||||
feature.labelHorizontalOrigin = HorizontalOrigin.RIGHT;
|
||||
feature.labelVerticalOrigin = VerticalOrigin.BASELINE;
|
||||
}
|
||||
}
|
||||
|
||||
const scratchColor = new Color();
|
||||
const scratchColor2 = new Color();
|
||||
const scratchColor3 = new Color();
|
||||
const scratchColor4 = new Color();
|
||||
const scratchColor5 = new Color();
|
||||
const scratchColor6 = new Color();
|
||||
const scratchScaleByDistance = new NearFarScalar();
|
||||
const scratchTranslucencyByDistance = new NearFarScalar();
|
||||
const scratchDistanceDisplayCondition = new DistanceDisplayCondition();
|
||||
|
||||
/**
|
||||
* Apply a style to the content.
|
||||
*
|
||||
* @param {Cesium3DTileStyle} style The style.
|
||||
* @param {Cesium3DTileFeature[]} features The array of features.
|
||||
*/
|
||||
Vector3DTilePoints.prototype.applyStyle = function (style, features) {
|
||||
if (!defined(style)) {
|
||||
clearStyle(this, features);
|
||||
return;
|
||||
}
|
||||
|
||||
const batchIds = this._batchIds;
|
||||
const length = batchIds.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
const batchId = batchIds[i];
|
||||
const feature = features[batchId];
|
||||
|
||||
if (defined(style.show)) {
|
||||
feature.show = style.show.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.pointSize)) {
|
||||
feature.pointSize = style.pointSize.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.color)) {
|
||||
feature.color = style.color.evaluateColor(feature, scratchColor);
|
||||
}
|
||||
|
||||
if (defined(style.pointOutlineColor)) {
|
||||
feature.pointOutlineColor = style.pointOutlineColor.evaluateColor(
|
||||
feature,
|
||||
scratchColor2,
|
||||
);
|
||||
}
|
||||
|
||||
if (defined(style.pointOutlineWidth)) {
|
||||
feature.pointOutlineWidth = style.pointOutlineWidth.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.labelColor)) {
|
||||
feature.labelColor = style.labelColor.evaluateColor(
|
||||
feature,
|
||||
scratchColor3,
|
||||
);
|
||||
}
|
||||
|
||||
if (defined(style.labelOutlineColor)) {
|
||||
feature.labelOutlineColor = style.labelOutlineColor.evaluateColor(
|
||||
feature,
|
||||
scratchColor4,
|
||||
);
|
||||
}
|
||||
|
||||
if (defined(style.labelOutlineWidth)) {
|
||||
feature.labelOutlineWidth = style.labelOutlineWidth.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.font)) {
|
||||
feature.font = style.font.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.labelStyle)) {
|
||||
feature.labelStyle = style.labelStyle.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.labelText)) {
|
||||
feature.labelText = style.labelText.evaluate(feature);
|
||||
} else {
|
||||
feature.labelText = undefined;
|
||||
}
|
||||
|
||||
if (defined(style.backgroundColor)) {
|
||||
feature.backgroundColor = style.backgroundColor.evaluateColor(
|
||||
feature,
|
||||
scratchColor5,
|
||||
);
|
||||
}
|
||||
|
||||
if (defined(style.backgroundPadding)) {
|
||||
feature.backgroundPadding = style.backgroundPadding.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.backgroundEnabled)) {
|
||||
feature.backgroundEnabled = style.backgroundEnabled.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.scaleByDistance)) {
|
||||
const scaleByDistanceCart4 = style.scaleByDistance.evaluate(feature);
|
||||
if (defined(scaleByDistanceCart4)) {
|
||||
scratchScaleByDistance.near = scaleByDistanceCart4.x;
|
||||
scratchScaleByDistance.nearValue = scaleByDistanceCart4.y;
|
||||
scratchScaleByDistance.far = scaleByDistanceCart4.z;
|
||||
scratchScaleByDistance.farValue = scaleByDistanceCart4.w;
|
||||
feature.scaleByDistance = scratchScaleByDistance;
|
||||
} else {
|
||||
feature.scaleByDistance = undefined;
|
||||
}
|
||||
} else {
|
||||
feature.scaleByDistance = undefined;
|
||||
}
|
||||
|
||||
if (defined(style.translucencyByDistance)) {
|
||||
const translucencyByDistanceCart4 =
|
||||
style.translucencyByDistance.evaluate(feature);
|
||||
if (defined(translucencyByDistanceCart4)) {
|
||||
scratchTranslucencyByDistance.near = translucencyByDistanceCart4.x;
|
||||
scratchTranslucencyByDistance.nearValue = translucencyByDistanceCart4.y;
|
||||
scratchTranslucencyByDistance.far = translucencyByDistanceCart4.z;
|
||||
scratchTranslucencyByDistance.farValue = translucencyByDistanceCart4.w;
|
||||
feature.translucencyByDistance = scratchTranslucencyByDistance;
|
||||
} else {
|
||||
feature.translucencyByDistance = undefined;
|
||||
}
|
||||
} else {
|
||||
feature.translucencyByDistance = undefined;
|
||||
}
|
||||
|
||||
if (defined(style.distanceDisplayCondition)) {
|
||||
const distanceDisplayConditionCart2 =
|
||||
style.distanceDisplayCondition.evaluate(feature);
|
||||
if (defined(distanceDisplayConditionCart2)) {
|
||||
scratchDistanceDisplayCondition.near = distanceDisplayConditionCart2.x;
|
||||
scratchDistanceDisplayCondition.far = distanceDisplayConditionCart2.y;
|
||||
feature.distanceDisplayCondition = scratchDistanceDisplayCondition;
|
||||
} else {
|
||||
feature.distanceDisplayCondition = undefined;
|
||||
}
|
||||
} else {
|
||||
feature.distanceDisplayCondition = undefined;
|
||||
}
|
||||
|
||||
if (defined(style.heightOffset)) {
|
||||
feature.heightOffset = style.heightOffset.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.anchorLineEnabled)) {
|
||||
feature.anchorLineEnabled = style.anchorLineEnabled.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.anchorLineColor)) {
|
||||
feature.anchorLineColor = style.anchorLineColor.evaluateColor(
|
||||
feature,
|
||||
scratchColor6,
|
||||
);
|
||||
}
|
||||
|
||||
if (defined(style.image)) {
|
||||
feature.image = style.image.evaluate(feature);
|
||||
} else {
|
||||
feature.image = undefined;
|
||||
}
|
||||
|
||||
if (defined(style.disableDepthTestDistance)) {
|
||||
feature.disableDepthTestDistance =
|
||||
style.disableDepthTestDistance.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.horizontalOrigin)) {
|
||||
feature.horizontalOrigin = style.horizontalOrigin.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.verticalOrigin)) {
|
||||
feature.verticalOrigin = style.verticalOrigin.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.labelHorizontalOrigin)) {
|
||||
feature.labelHorizontalOrigin =
|
||||
style.labelHorizontalOrigin.evaluate(feature);
|
||||
}
|
||||
|
||||
if (defined(style.labelVerticalOrigin)) {
|
||||
feature.labelVerticalOrigin = style.labelVerticalOrigin.evaluate(feature);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
Vector3DTilePoints.prototype.update = function (frameState) {
|
||||
if (!this._ready) {
|
||||
if (!defined(this._promise)) {
|
||||
this._promise = createPoints(this, frameState.mapProjection.ellipsoid);
|
||||
}
|
||||
|
||||
if (defined(this._error)) {
|
||||
const error = this._error;
|
||||
this._error = undefined;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this._polylineCollection.update(frameState);
|
||||
this._billboardCollection.update(frameState);
|
||||
this._labelCollection.update(frameState);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if this object was destroyed; otherwise, false.
|
||||
* <p>
|
||||
* If this object was destroyed, it should not be used; calling any function other than
|
||||
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
|
||||
* </p>
|
||||
*
|
||||
* @returns {boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
|
||||
*/
|
||||
Vector3DTilePoints.prototype.isDestroyed = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
|
||||
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
|
||||
* <p>
|
||||
* Once an object is destroyed, it should not be used; calling any function other than
|
||||
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
|
||||
* assign the return value (<code>undefined</code>) to the object as done in the example.
|
||||
* </p>
|
||||
*
|
||||
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
|
||||
*/
|
||||
Vector3DTilePoints.prototype.destroy = function () {
|
||||
this._billboardCollection =
|
||||
this._billboardCollection && this._billboardCollection.destroy();
|
||||
this._labelCollection =
|
||||
this._labelCollection && this._labelCollection.destroy();
|
||||
this._polylineCollection =
|
||||
this._polylineCollection && this._polylineCollection.destroy();
|
||||
return destroyObject(this);
|
||||
};
|
||||
export default Vector3DTilePoints;
|
||||
Reference in New Issue
Block a user