Skip to content

Commit 44c13e4

Browse files
authored
Merge pull request #11710 from gdiehlEB/vector-point-clamping
Add support for clamping Vector 3D Tile point features to Terrain or 3d Tiles
2 parents 70920bb + 19ee96d commit 44c13e4

File tree

7 files changed

+135
-2
lines changed

7 files changed

+135
-2
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
- Updates use of deprecated options on createImageBitmap. [#12664](https://github.com/CesiumGS/cesium/pull/12664)
1010

11+
#### Additions :tada:
12+
13+
- Added `HeightReference` to `Cesium3DTileset.ConstructorOptions` to allow clamping point features in 3D Tile vector data to terrain or 3D Tiles [#11710](https://github.com/CesiumGS/cesium/pull/11710)
14+
1115
## 1.130 - 2025-06-02
1216

1317
### @cesium/engine

CONTRIBUTORS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
206206
- [IKangXu](https://github.com/IKangXu)
207207
- [EMapGIS](https://github.com/EMapGIS)
208208
- [CandyACE](https://github.com/CandyACE)
209+
- [EARTHBRAIN, Ltd.](https://www.earthbrain.com/en/)
210+
- [Gregory Diehl](https://github.com/gdiehleb)
209211

210212
## [Individual CLA](Documentation/Contributors/CLAs/individual-contributor-license-agreement-v1.0.pdf)
211213

packages/engine/Source/Scene/Cesium3DTileset.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ import ImageryLayerCollection from "./ImageryLayerCollection.js";
102102
* @property {ClippingPlaneCollection} [clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset.
103103
* @property {ClippingPolygonCollection} [clippingPolygons] The {@link ClippingPolygonCollection} used to selectively disable rendering the tileset.
104104
* @property {ClassificationType} [classificationType] Determines whether terrain, 3D Tiles or both will be classified by this tileset. See {@link Cesium3DTileset#classificationType} for details about restrictions and limitations.
105+
* @property {HeightReference} [heightReference] Sets the {@link HeightReference} for point features in vector tilesets.
106+
* @property {Scene} [scene] The {@link CesiumWidget#scene} that the tileset will be rendered in, required for tilesets that specify a {@link heightReference} value for clamping 3D Tiles vector data content- like points, lines, and labels- to terrain or 3D tiles.
105107
* @property {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe.
106108
* @property {object} [pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
107109
* @property {Cartesian3} [lightColor] The light color when shading models. When <code>undefined</code> the scene's light color is used instead.
@@ -337,6 +339,8 @@ function Cesium3DTileset(options) {
337339
this._tileDebugLabels = undefined;
338340

339341
this._classificationType = options.classificationType;
342+
this._heightReference = options.heightReference;
343+
this._scene = options.scene;
340344

341345
this._ellipsoid = options.ellipsoid ?? Ellipsoid.WGS84;
342346

@@ -1808,6 +1812,43 @@ Object.defineProperties(Cesium3DTileset.prototype, {
18081812
},
18091813
},
18101814

1815+
/**
1816+
* Specifies if the height is relative to terrain, 3D Tiles, or both.
1817+
* <p>
1818+
* This option is only applied to point features in tilesets containing vector data.
1819+
* This option requires the Viewer's scene to be passed in through options.scene.
1820+
* </p>
1821+
*
1822+
* @memberof Cesium3DTileset.prototype
1823+
*
1824+
* @type {HeightReference | undefined}
1825+
* @default undefined
1826+
*
1827+
* @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.
1828+
* @readonly
1829+
*/
1830+
heightReference: {
1831+
get: function () {
1832+
return this._heightReference;
1833+
},
1834+
},
1835+
1836+
/**
1837+
* The {@link CesiumWidget#scene} that the tileset will be rendered in, required for tilesets that specify a {@link heightReference} value for clamping 3D Tiles vector data content- like points, lines, and labels- to terrain or 3D tiles.
1838+
*
1839+
* @member of Cesium3DTileset.prototype
1840+
*
1841+
* @type {Scene | undefined}
1842+
* @default undefined
1843+
* @readonly
1844+
*
1845+
*/
1846+
scene: {
1847+
get: function () {
1848+
return this._scene;
1849+
},
1850+
},
1851+
18111852
/**
18121853
* Gets an ellipsoid describing the shape of the globe.
18131854
*

packages/engine/Source/Scene/Vector3DTileContent.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ function initialize(content, arrayBuffer, byteOffset) {
524524
modelMatrix: modelMatrix,
525525
});
526526
}
527-
527+
const tileset = content._tileset;
528528
if (numberOfPolylines > 0) {
529529
featureTable.featuresLength = numberOfPolylines;
530530

@@ -570,7 +570,6 @@ function initialize(content, arrayBuffer, byteOffset) {
570570
);
571571
byteOffset += polylinePositionByteLength;
572572

573-
const tileset = content._tileset;
574573
const examineVectorLinesFunction = tileset.examineVectorLinesFunction;
575574
if (defined(examineVectorLinesFunction)) {
576575
const decodedPositions = decodeVectorPolylinePositions(
@@ -625,6 +624,8 @@ function initialize(content, arrayBuffer, byteOffset) {
625624
maximumHeight: maxHeight,
626625
rectangle: rectangle,
627626
batchTable: batchTable,
627+
heightReference: tileset.heightReference,
628+
scene: tileset.scene,
628629
});
629630
}
630631
}

packages/engine/Source/Scene/Vector3DTilePoints.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import LabelCollection from "./LabelCollection.js";
1515
import LabelStyle from "./LabelStyle.js";
1616
import PolylineCollection from "./PolylineCollection.js";
1717
import VerticalOrigin from "./VerticalOrigin.js";
18+
import HeightReference from "./HeightReference.js";
1819

1920
/**
2021
* Creates a batch of points or billboards and labels.
@@ -27,8 +28,10 @@ import VerticalOrigin from "./VerticalOrigin.js";
2728
* @param {number} options.minimumHeight The minimum height of the terrain covered by the tile.
2829
* @param {number} options.maximumHeight The maximum height of the terrain covered by the tile.
2930
* @param {Rectangle} options.rectangle The rectangle containing the tile.
31+
* @param {HeightReference} options.heightReference Determines how billboard and label features are positioned relative to terrain or 3d tiles.
3032
* @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polygons.
3133
* @param {Uint16Array} options.batchIds The batch ids for each polygon.
34+
* @param {Scene} options.scene The Cesium Viewer {@link Scene}. This is required for clamping billboards and labels with {@link HeightReference}
3235
*
3336
* @private
3437
*/
@@ -42,12 +45,15 @@ function Vector3DTilePoints(options) {
4245
this._rectangle = options.rectangle;
4346
this._minHeight = options.minimumHeight;
4447
this._maxHeight = options.maximumHeight;
48+
this._heightReference = options.heightReference;
4549

4650
this._billboardCollection = new BillboardCollection({
4751
batchTable: options.batchTable,
52+
scene: options.scene,
4853
});
4954
this._labelCollection = new LabelCollection({
5055
batchTable: options.batchTable,
56+
scene: options.scene,
5157
});
5258
this._polylineCollection = new PolylineCollection();
5359
this._polylineCollection._useHighlightColor = true;
@@ -175,6 +181,8 @@ function createPoints(points, ellipsoid) {
175181
const batchIds = points._batchIds;
176182
const numberOfPoints = positions.length / 3;
177183

184+
const heightReference = points._heightReference ?? HeightReference.NONE;
185+
178186
for (let i = 0; i < numberOfPoints; ++i) {
179187
const id = batchIds[i];
180188

@@ -183,11 +191,13 @@ function createPoints(points, ellipsoid) {
183191
const b = billboardCollection.add();
184192
b.position = position;
185193
b._batchIndex = id;
194+
b.heightReference = heightReference;
186195

187196
const l = labelCollection.add();
188197
l.text = " ";
189198
l.position = position;
190199
l._batchIndex = id;
200+
l.heightReference = heightReference;
191201

192202
const p = polylineCollection.add();
193203
p.positions = [Cartesian3.clone(position), Cartesian3.clone(position)];

packages/engine/Specs/Scene/Vector3DTileContentSpec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Cesium3DTileset,
88
Cesium3DTileStyle,
99
ClassificationType,
10+
HeightReference,
1011
Color,
1112
ColorGeometryInstanceAttribute,
1213
destroyObject,
@@ -613,6 +614,22 @@ describe(
613614
expect(scene).toRender(whitePixel);
614615
});
615616
});
617+
618+
it("sets the heightReference for Vector3DTilePoints", async () => {
619+
const heightReference = HeightReference.CLAMP_TO_3D_TILE;
620+
const tileset = await Cesium3DTilesTester.loadTileset(
621+
scene,
622+
vectorTilePointsTileset,
623+
{
624+
heightReference: heightReference,
625+
scene,
626+
},
627+
);
628+
const vectorTile = tileset._root.children[0];
629+
const vectorTilePoint = vectorTile._content._points;
630+
631+
expect(vectorTilePoint._heightReference).toEqual(heightReference);
632+
});
616633
});
617634

618635
describe("polygons", () => {

packages/engine/Specs/Scene/Vector3DTilePointsSpec.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
DistanceDisplayCondition,
1010
Ellipsoid,
1111
Math as CesiumMath,
12+
HeightReference,
1213
NearFarScalar,
1314
Rectangle,
1415
Cesium3DTileBatchTable,
@@ -577,6 +578,7 @@ describe(
577578
maxHeight,
578579
cartoPositions,
579580
);
581+
const heightReference = HeightReference.CLAMP_TO_TERRAIN;
580582

581583
const batchTable = new Cesium3DTileBatchTable(mockTileset, 1);
582584
batchTable.update(mockTileset, scene.frameState);
@@ -589,6 +591,8 @@ describe(
589591
rectangle: rectangle,
590592
minimumHeight: minHeight,
591593
maximumHeight: maxHeight,
594+
heightReference: heightReference,
595+
scene,
592596
}),
593597
);
594598

@@ -616,10 +620,64 @@ describe(
616620
}).then(function () {
617621
expect(billboard.ready).toEqual(true);
618622
expect(scene).toRender([0, 0, 255, 255]);
623+
expect(billboard.heightReference).toEqual(heightReference);
619624
});
620625
});
621626
});
622627

628+
it("renders a point with a label", function () {
629+
const minHeight = 0.0;
630+
const maxHeight = 100.0;
631+
const cartoPositions = [Cartographic.fromDegrees(0.0, 0.0, 10.0)];
632+
const positions = encodePositions(
633+
rectangle,
634+
minHeight,
635+
maxHeight,
636+
cartoPositions,
637+
);
638+
const heightReference = HeightReference.CLAMP_TO_TERRAIN;
639+
640+
const batchTable = new Cesium3DTileBatchTable(mockTileset, 1);
641+
batchTable.update(mockTileset, scene.frameState);
642+
643+
points = scene.primitives.add(
644+
new Vector3DTilePoints({
645+
positions: positions,
646+
batchTable: batchTable,
647+
batchIds: new Uint16Array([0]),
648+
rectangle: rectangle,
649+
minimumHeight: minHeight,
650+
maximumHeight: maxHeight,
651+
heightReference: heightReference,
652+
scene,
653+
}),
654+
);
655+
656+
const style = new Cesium3DTileStyle({
657+
labelText: '"test"',
658+
labelColor: "rgba(100, 255, 0, 255)",
659+
labelHorizontalOrigin: HorizontalOrigin.LEFT,
660+
});
661+
return loadPoints(points).then(function () {
662+
const features = [];
663+
points.createFeatures(mockTileset, features);
664+
points.applyStyle(style, features);
665+
666+
const collection = points._labelCollection;
667+
expect(collection.length).toEqual(1);
668+
const label = collection.get(0);
669+
expect(label).toBeDefined();
670+
671+
scene.camera.lookAt(
672+
Cartesian3.fromDegrees(0.0, 0.0, 10.0),
673+
new Cartesian3(0.0, 0.0, 50.0),
674+
);
675+
676+
expect(scene).toRender([100, 255, 0, 255]);
677+
expect(label.heightReference).toEqual(heightReference);
678+
});
679+
});
680+
623681
it("renders multiple points with debug color", function () {
624682
const minHeight = 0.0;
625683
const maxHeight = 100.0;

0 commit comments

Comments
 (0)