Skip to content

Commit

Permalink
Merge pull request #9495 from CesiumGS/unpack-vectors
Browse files Browse the repository at this point in the history
3D Tiles Next Metadata: Automatically unpack vector types
  • Loading branch information
lilleyse authored Apr 20, 2021
2 parents ec02386 + dee9bbf commit 70d0d31
Show file tree
Hide file tree
Showing 20 changed files with 661 additions and 209 deletions.
104 changes: 103 additions & 1 deletion Source/Scene/MetadataClassProperty.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import Cartesian2 from "../Core/Cartesian2.js";
import Cartesian3 from "../Core/Cartesian3.js";
import Cartesian4 from "../Core/Cartesian4.js";
import Check from "../Core/Check.js";
import defaultValue from "../Core/defaultValue.js";
import defined from "../Core/defined.js";
Expand Down Expand Up @@ -294,6 +297,79 @@ MetadataClassProperty.prototype.unnormalize = function (value) {
return normalize(this, value, MetadataType.unnormalize);
};

/**
* Unpack array values into {@link Cartesian2}, {@link Cartesian3}, or
* {@link Cartesian4} if this property is an <code>ARRAY</code> of length 2, 3,
* or 4, respectively. All other values (including arrays of other sizes) are
* passed through unaltered.
*
* @param {*} value the original, normalized values.
* @returns {*} The appropriate vector type if the value is a vector type. Otherwise, the value is returned unaltered.
* @private
*/
MetadataClassProperty.prototype.unpackVectorTypes = function (value) {
var type = this._type;
var componentCount = this._componentCount;

if (
type !== MetadataType.ARRAY ||
!defined(componentCount) ||
!MetadataType.isVectorCompatible(this._componentType)
) {
return value;
}

if (componentCount === 2) {
return Cartesian2.unpack(value);
}

if (componentCount === 3) {
return Cartesian3.unpack(value);
}

if (componentCount === 4) {
return Cartesian4.unpack(value);
}

return value;
};

/**
* Pack a {@link Cartesian2}, {@link Cartesian3}, or {@link Cartesian4} into an
* array if this property is an <code>ARRAY</code> of length 2, 3, or 4, respectively.
* All other values (including arrays of other sizes) are passed through unaltered.
*
* @param {*} value The value of this property
* @returns {*} An array of the appropriate length if the property is a vector type. Otherwise, the value is returned unaltered.
* @private
*/
MetadataClassProperty.prototype.packVectorTypes = function (value) {
var type = this._type;
var componentCount = this._componentCount;

if (
type !== MetadataType.ARRAY ||
!defined(componentCount) ||
!MetadataType.isVectorCompatible(this._componentType)
) {
return value;
}

if (componentCount === 2) {
return Cartesian2.pack(value, []);
}

if (componentCount === 3) {
return Cartesian3.pack(value, []);
}

if (componentCount === 4) {
return Cartesian4.pack(value, []);
}

return value;
};

/**
* Validates whether the given value conforms to the property.
*
Expand All @@ -304,11 +380,23 @@ MetadataClassProperty.prototype.validate = function (value) {
var message;
var type = this._type;
if (type === MetadataType.ARRAY) {
var componentCount = this._componentCount;

// arrays of length 2, 3, and 4 are implicitly converted to CartesianN
if (
defined(componentCount) &&
componentCount >= 2 &&
componentCount <= 4 &&
MetadataType.isVectorCompatible(this._componentType)
) {
return validateVector(value, componentCount);
}

if (!Array.isArray(value)) {
return getTypeErrorMessage(value, type);
}
var length = value.length;
if (defined(this._componentCount) && this._componentCount !== length) {
if (defined(componentCount) && componentCount !== length) {
return "Array length does not match componentCount";
}
for (var i = 0; i < length; ++i) {
Expand All @@ -325,6 +413,20 @@ MetadataClassProperty.prototype.validate = function (value) {
}
};

function validateVector(value, componentCount) {
if (componentCount === 2 && !(value instanceof Cartesian2)) {
return "vector value " + value + " must be a Cartesian2";
}

if (componentCount === 3 && !(value instanceof Cartesian3)) {
return "vector value " + value + " must be a Cartesian3";
}

if (componentCount === 4 && !(value instanceof Cartesian4)) {
return "vector value " + value + " must be a Cartesian4";
}
}

function getTypeErrorMessage(value, type) {
return "value " + value + " does not match type " + type;
}
Expand Down
2 changes: 2 additions & 0 deletions Source/Scene/MetadataEntity.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ MetadataEntity.getProperty = function (

if (defined(classProperty)) {
value = classProperty.normalize(value);
value = classProperty.unpackVectorTypes(value);
}

return value;
Expand Down Expand Up @@ -269,6 +270,7 @@ MetadataEntity.setProperty = function (
if (defined(classDefinition)) {
var classProperty = classDefinition.properties[propertyId];
if (defined(classProperty)) {
value = classProperty.packVectorTypes(value);
value = classProperty.unnormalize(value);
}
}
Expand Down
3 changes: 2 additions & 1 deletion Source/Scene/MetadataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ function getDefault(classDefinition, propertyId) {
if (classProperty.type === MetadataType.ARRAY) {
value = value.slice(); // clone
}
return classProperty.normalize(value);
value = classProperty.normalize(value);
return classProperty.unpackVectorTypes(value);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Scene/MetadataTableProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ MetadataTableProperty.prototype.get = function (index) {
//>>includeEnd('debug');

var value = get(this, index);
return this._classProperty.normalize(value);
value = this._classProperty.normalize(value);
return this._classProperty.unpackVectorTypes(value);
};

/**
Expand All @@ -209,6 +210,7 @@ MetadataTableProperty.prototype.set = function (index, value) {
}
//>>includeEnd('debug');

value = classProperty.packVectorTypes(value);
value = classProperty.unnormalize(value);

set(this, index, value);
Expand Down
25 changes: 25 additions & 0 deletions Source/Scene/MetadataType.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,31 @@ MetadataType.isUnsignedIntegerType = function (type) {
}
};

/**
* Returns whether a type can be used in a vector, i.e. the {@link Cartesian2},
* {@link Cartesian3}, or {@link Cartesian4} classes. This includes all numeric
* types except for types requiring 64-bits
*/
MetadataType.isVectorCompatible = function (type) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.string("type", type);
//>>includeEnd('debug');

switch (type) {
case MetadataType.INT8:
case MetadataType.UINT8:
case MetadataType.INT16:
case MetadataType.UINT16:
case MetadataType.INT32:
case MetadataType.UINT32:
case MetadataType.FLOAT32:
case MetadataType.FLOAT64:
return true;
default:
return false;
}
};

/**
* Normalizes signed integers to the range [-1.0, 1.0] and unsigned integers to
* the range [0.0, 1.0].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"description": "Center of the tileset as [longitude, latitude, height] where longitude and latitude are in radians, and height is in meters].",
"type": "ARRAY",
"componentType": "FLOAT64",
"componentCount": "3"
"componentCount": 3
},
"tileCount": {
"description": "Total number of tiles in the tileset",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"description": "Center of the tileset as [longitude, latitude, height] where longitude and latitude are in radians, and height is in meters].",
"type": "ARRAY",
"componentType": "FLOAT64",
"componentCount": "3"
"componentCount": 3
},
"tileCount": {
"description": "Total number of tiles in the tileset",
Expand Down
58 changes: 23 additions & 35 deletions Specs/Scene/Cesium3DTileFeatureSpec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Cartesian3,
Cartesian4,
Cesium3DTileFeature,
HeadingPitchRange,
} from "../../Source/Cesium.js";
Expand Down Expand Up @@ -55,22 +56,16 @@ describe(

it("getPropertyInherited returns tile property by semantic", function () {
var feature = new Cesium3DTileFeature(childContents["ll.b3dm"], 0);
expect(feature.getPropertyInherited("COLOR")).toEqual([
255,
255,
0,
1.0,
]);
expect(feature.getPropertyInherited("COLOR")).toEqual(
new Cartesian4(255, 255, 0, 1.0)
);
});

it("getPropertyInherited returns tile property", function () {
var feature = new Cesium3DTileFeature(childContents["ll.b3dm"], 0);
expect(feature.getPropertyInherited("color")).toEqual([
255,
255,
0,
1.0,
]);
expect(feature.getPropertyInherited("color")).toEqual(
new Cartesian4(255, 255, 0, 1.0)
);
expect(feature.getPropertyInherited("population")).toBe(50);
});

Expand All @@ -92,12 +87,9 @@ describe(

it("getPropertyInherited returns tileset property by semantic", function () {
var feature = new Cesium3DTileFeature(parentContent, 0);
expect(feature.getPropertyInherited("COLOR")).toEqual([
255,
0,
255,
1.0,
]);
expect(feature.getPropertyInherited("COLOR")).toEqual(
new Cartesian4(255, 0, 255, 1.0)
);
expect(feature.getPropertyInherited("DATE_ISO_8601")).toBe(
"2021-04-07"
);
Expand All @@ -106,17 +98,16 @@ describe(

it("getPropertyInherited returns tileset property", function () {
var feature = new Cesium3DTileFeature(parentContent, 0);
expect(feature.getPropertyInherited("color")).toEqual([
255,
0,
255,
1.0,
]);
expect(feature.getPropertyInherited("centerCartographic")).toEqual([
-1.3196816996258511,
0.6988767486400521,
45.78600543644279,
]);
expect(feature.getPropertyInherited("color")).toEqual(
new Cartesian4(255, 0, 255, 1.0)
);
expect(feature.getPropertyInherited("centerCartographic")).toEqual(
new Cartesian3(
-1.3196816996258511,
0.6988767486400521,
45.78600543644279
)
);
expect(feature.getPropertyInherited("date")).toBe("2021-04-07");
expect(feature.getPropertyInherited("author")).toBe("Cesium");
expect(feature.getPropertyInherited("tileCount")).toBe(5);
Expand All @@ -126,12 +117,9 @@ describe(
// tile metadata is more specific than tileset metadata so this returns
// yellow not magenta
var feature = new Cesium3DTileFeature(childContents["ll.b3dm"], 0);
expect(feature.getPropertyInherited("color")).toEqual([
255,
255,
0,
1.0,
]);
expect(feature.getPropertyInherited("color")).toEqual(
new Cartesian4(255, 255, 0, 1.0)
);

// group metadata is more specific than tileset metadata, so this returns
// 2 not 5
Expand Down
20 changes: 10 additions & 10 deletions Specs/Scene/Cesium3DTilesetSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5198,7 +5198,7 @@ describe(
tilesetProperties.date
);
expect(tilesetMetadata.getProperty("centerCartographic")).toEqual(
tilesetProperties.centerCartographic
Cartesian3.unpack(tilesetProperties.centerCartographic)
);
expect(tilesetMetadata.getProperty("tileCount")).toBe(
tilesetProperties.tileCount
Expand Down Expand Up @@ -5298,23 +5298,23 @@ describe(
).then(function (tileset) {
var expected = {
"parent.b3dm": {
color: [0.5, 0.0, 1.0],
color: new Cartesian3(0.5, 0.0, 1.0),
population: 530,
},
"ll.b3dm": {
color: [1.0, 1.0, 0.0],
color: new Cartesian3(1.0, 1.0, 0.0),
population: 50,
},
"lr.b3dm": {
color: [1.0, 0.0, 0.5],
color: new Cartesian3(1.0, 0.0, 0.5),
population: 230,
},
"ur.b3dm": {
color: [1.0, 0.5, 0.0],
color: new Cartesian3(1.0, 0.5, 0.0),
population: 150,
},
"ul.b3dm": {
color: [1.0, 0.0, 0.0],
color: new Cartesian3(1.0, 0.0, 0.0),
population: 100,
},
};
Expand Down Expand Up @@ -5360,10 +5360,10 @@ describe(
"Northeast",
];
var expectedColors = [
[255, 255, 255],
[255, 0, 0],
[0, 255, 0],
[0, 0, 255],
new Cartesian3(255, 255, 255),
new Cartesian3(255, 0, 0),
new Cartesian3(0, 255, 0),
new Cartesian3(0, 0, 255),
];

var tiles = [transcodedRoot].concat(transcodedRoot.children);
Expand Down
Loading

0 comments on commit 70d0d31

Please sign in to comment.